-
Notifications
You must be signed in to change notification settings - Fork 69
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using returning clause causes errors #192
Comments
Here is a way to reproduce the issue package main
import (
"context"
"fmt"
"log"
"os"
"github.com/canonical/go-dqlite/app"
)
func main() {
ctx := context.Background()
exitIf(os.MkdirAll("data", 0755))
dqlite, err := app.New("data")
exitIf(err)
exitIf(dqlite.Ready(ctx))
db, err := dqlite.Open(ctx, "test")
exitIf(err)
exitIf(db.Ping())
_, err = db.ExecContext(ctx, "create table if not exists test (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, value TEXT NOT NULL)")
exitIf(err)
var (
id int64
value string
)
for i := 0; i < 10; i++ {
exitIf(db.QueryRowContext(ctx, "INSERT INTO test (value) VALUES (?) RETURNING *", i).Scan(&id, &value))
log.Printf("inserted %d, %s", id, value)
}
}
func exitIf(err error) {
if err != nil {
fmt.Printf("error: %v\n", err)
os.Exit(1)
}
} Expand to see Dockerfile# shared deps
FROM golang as base
RUN apt-get -y update
RUN apt-get -y --no-install-recommends install autoconf automake make \
libtool liblz4-dev libuv1-dev libsqlite3-dev
# raft & dqlite
FROM base as dqlite
# raft
RUN git clone https://github.com/canonical/raft.git /tmp/raft
WORKDIR /tmp/raft
RUN autoreconf -i
RUN ./configure
RUN make
RUN make install
# dqlite
RUN git clone https://github.com/canonical/dqlite.git /tmp/dqlite
WORKDIR /tmp/dqlite
RUN autoreconf -i
RUN ./configure
RUN make
RUN make install
# sqlite3
FROM base as sqlite3
RUN curl -fsSL https://www.sqlite.org/2022/sqlite-autoconf-3380300.tar.gz | tar -xz -C /tmp
WORKDIR /tmp/sqlite-autoconf-3380300
RUN autoreconf -i
RUN ./configure
RUN make
RUN make install
# consolidate
FROM dqlite as builder-base
COPY --from=sqlite3 /usr/local/lib /usr/local/lib
RUN ldconfig
ENV CGO_LDFLAGS_ALLOW="-Wl,-z,now"
# build go source
FROM builder-base as builder
WORKDIR /workspace
COPY go.mod go.sum ./
RUN go mod download
COPY main.go ./
RUN go build -tags libsqlite3 -o server .
# final image
FROM debian:bullseye-slim
RUN apt -y update && apt -y install libuv1-dev
COPY --from=builder /usr/local/lib /usr/local/lib
RUN ldconfig
WORKDIR /app
COPY --from=builder /workspace/server ./server
CMD [ "/app/server" ] If you build and run this, you get the error consistently: $ docker build -t test .
$ docker run --rm test
2022/05/05 19:44:32 inserted 1, 0
server: src/vfs.c:1701: vfsFileShmLock: Assertion `wal->n_tx == 0' failed. I noticed that it works when using a transaction: for i := 0; i < 10; i++ {
txn, err := db.BeginTx(ctx, nil)
exitIf(err)
exitIf(txn.QueryRowContext(ctx, "INSERT INTO test (value) VALUES (?) RETURNING *", i).Scan(&id, &value))
exitIf(txn.Commit())
log.Printf("inserted %d, %s", id, value)
} $ docker build -t test .
$ docker run --rm test
2022/05/05 19:47:08 inserted 1, 0
2022/05/05 19:47:08 inserted 2, 1
2022/05/05 19:47:08 inserted 3, 2
2022/05/05 19:47:08 inserted 4, 3
2022/05/05 19:47:08 inserted 5, 4
2022/05/05 19:47:08 inserted 6, 5
2022/05/05 19:47:08 inserted 7, 6
2022/05/05 19:47:08 inserted 8, 7
2022/05/05 19:47:08 inserted 9, 8
2022/05/05 19:47:08 inserted 10, 9 |
Thanks that's interesting information. |
I more or less have an idea what's happening. Statements like
that assumption clearly doesn't hold and the internal logic breaks down. I think |
It also looks like libsqlite3 on Ubuntu Bionic Beaver https://launchpad.net/ubuntu/bionic/amd64/libsqlite3-dev/3.22.0-1 and Focal Fossa https://launchpad.net/ubuntu/focal/amd64/libsqlite3-dev/3.31.1-4 both don't support it. What do you think @stgraber, I guess dqlite shouldn't be able to support |
Indeed it looks like support for The use cases for |
Some ORMs and such build on top of it though. I.e. https://github.com/volatiletech/sqlboiler. This would make the dqlite library kind of incompatible with some popular existing abstractions on top of the std sql package. |
Please can you point where The |
It's using returning on the first class insert method. var m models.MyModel
m.Name = "foo"
m.Insert(r.Context(), db, boil.Infer()) Thats the most straight forward and probably suggested way to use the models. You can get around my using rawQuery and things like that, but I would think those methods are for edge cases. model.Insert is for primary use. You can see it for example here:: https://github.com/volatiletech/sqlboiler/blob/master/templates/main/15_insert.go.tpl#L95 Maybe there are some other ways to disable it, but it's the default behaviour AFAIK. I don't know that package well, it's just one I know of that is using returning. |
I think returning makes also sense when dealing with default values and partial updates. For example you have a http patch request handler. The user sends only 1 column to update but you want to respond with the full row. You would use returning after the update statement, to get the full row and respond with it. |
It looks like setting the |
|
Fair enough, I didn't think about that use case. You can still just do a Having said that, dqlite could eventually support |
I also met this error when I use dqlite with ent. It uses |
The easiest workaround would probably be to add dqlite as a new ent dialect, and have it behave the same as the sqlite dialect, except that it would not support |
I have made a fork and do this, but I still hope for a better solution. |
I still think, it would be good to aim for full feature parity with sqlite3. Otherwise, it's difficult to use dqlite as a drop-in replacement for existing code. |
I agree this is annoying and should be fixed. It's not going to be easy though, because it most probably requires a wire protocol change. Since we have now one more ORM using |
Actually @cole-miller's PR canonical/dqlite#477 should be a good first step for solving this. I believe what we'd need is to also return rows for non read-only statements submitted using the |
Unfortunately we can't increment a sequence in one query because we run into the following dqlite issue[1]. For now we can just do a two step dance. Considering this won't be exercised that often this isn't going to be that taxing. 1. canonical/go-dqlite#192
Unfortunately we can't increment a sequence in one query because we run into the following dqlite issue[1]. For now we can just do a two step dance. Considering this won't be exercised that often this isn't going to be that taxing. 1. canonical/go-dqlite#192
Unfortunately we can't increment a sequence in one query because we run into the following dqlite issue[1]. For now we can just do a two step dance. Considering this won't be exercised that often this isn't going to be that taxing. 1. canonical/go-dqlite#192
Unfortunately we can't increment a sequence in one query because we run into the following dqlite issue[1]. For now we can just do a two step dance. Considering this won't be exercised that often this isn't going to be that taxing. 1. canonical/go-dqlite#192
Unfortunately we can't increment a sequence in one query because we run into the following dqlite issue[1]. For now we can just do a two step dance. Considering this won't be exercised that often this isn't going to be that taxing. 1. canonical/go-dqlite#192
Unfortunately we can't increment a sequence in one query because we run into the following dqlite issue[1]. For now we can just do a two step dance. Considering this won't be exercised that often this isn't going to be that taxing. 1. canonical/go-dqlite#192
Hi, I noticed different types of errors when using the returning clause.
Sometimes I see this:
And sometimes this:
These errors happen with the below code after the app is ready and the DB has been created.
It works OK, when removing the returning clause.
I have installed the c libraries with this script: https://gist.github.com/bluebrown/85e1b39980f50c66682743afe0d8b316.
The text was updated successfully, but these errors were encountered: