From 47139b4e97f2d3c9840d9d17164a13c6509cfd4b Mon Sep 17 00:00:00 2001 From: akm Date: Wed, 19 Mar 2025 00:38:51 +0900 Subject: [PATCH 01/18] =?UTF-8?q?=F0=9F=A4=96=20[sql-slog/examples/with-sq?= =?UTF-8?q?lc]=20$=20go=20mod=20init=20tutorial.sqlc.dev/app?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit go: creating new go.mod: module tutorial.sqlc.dev/app --- examples/with-sqlc/go.mod | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 examples/with-sqlc/go.mod diff --git a/examples/with-sqlc/go.mod b/examples/with-sqlc/go.mod new file mode 100644 index 0000000..31f8fdc --- /dev/null +++ b/examples/with-sqlc/go.mod @@ -0,0 +1,3 @@ +module tutorial.sqlc.dev/app + +go 1.23.2 From 74e5d2e6ea8667c5ec14bfc4c84f7b88a9874f80 Mon Sep 17 00:00:00 2001 From: akm Date: Wed, 19 Mar 2025 00:32:22 +0900 Subject: [PATCH 02/18] =?UTF-8?q?=F0=9F=94=A7=20Add=20sqlc.yaml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/with-sqlc/sqlc.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 examples/with-sqlc/sqlc.yaml diff --git a/examples/with-sqlc/sqlc.yaml b/examples/with-sqlc/sqlc.yaml new file mode 100644 index 0000000..d46738d --- /dev/null +++ b/examples/with-sqlc/sqlc.yaml @@ -0,0 +1,9 @@ +version: "2" +sql: + - engine: "sqlite" + queries: "query.sql" + schema: "schema.sql" + gen: + go: + package: "tutorial" + out: "tutorial" From af67bb31c36a3e3066236f29972e4f7cf61507ca Mon Sep 17 00:00:00 2001 From: akm Date: Wed, 19 Mar 2025 00:32:46 +0900 Subject: [PATCH 03/18] =?UTF-8?q?=E2=9C=A8=20Add=20schema.sql?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/with-sqlc/schema.sql | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 examples/with-sqlc/schema.sql diff --git a/examples/with-sqlc/schema.sql b/examples/with-sqlc/schema.sql new file mode 100644 index 0000000..9d2770b --- /dev/null +++ b/examples/with-sqlc/schema.sql @@ -0,0 +1,5 @@ +CREATE TABLE authors ( + id INTEGER PRIMARY KEY, + name text NOT NULL, + bio text +); From e9345ebfb80ff7053d4940f7cf49c3506f755c35 Mon Sep 17 00:00:00 2001 From: akm Date: Wed, 19 Mar 2025 00:33:15 +0900 Subject: [PATCH 04/18] =?UTF-8?q?=E2=9C=A8=20Add=20query.sql?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/with-sqlc/query.sql | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 examples/with-sqlc/query.sql diff --git a/examples/with-sqlc/query.sql b/examples/with-sqlc/query.sql new file mode 100644 index 0000000..212a226 --- /dev/null +++ b/examples/with-sqlc/query.sql @@ -0,0 +1,25 @@ +-- name: GetAuthor :one +SELECT * FROM authors +WHERE id = ? LIMIT 1; + +-- name: ListAuthors :many +SELECT * FROM authors +ORDER BY name; + +-- name: CreateAuthor :one +INSERT INTO authors ( + name, bio +) VALUES ( + ?, ? +) +RETURNING *; + +-- name: UpdateAuthor :exec +UPDATE authors +set name = ?, +bio = ? +WHERE id = ?; + +-- name: DeleteAuthor :exec +DELETE FROM authors +WHERE id = ?; From e182e1109e48d0d6c700b897f103d7537eafa853 Mon Sep 17 00:00:00 2001 From: akm Date: Wed, 19 Mar 2025 00:39:18 +0900 Subject: [PATCH 05/18] =?UTF-8?q?=F0=9F=A4=96=20[sql-slog/examples/with-sq?= =?UTF-8?q?lc]=20$=20sqlc=20generate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/with-sqlc/tutorial/db.go | 31 +++++++ examples/with-sqlc/tutorial/models.go | 15 ++++ examples/with-sqlc/tutorial/query.sql.go | 100 +++++++++++++++++++++++ 3 files changed, 146 insertions(+) create mode 100644 examples/with-sqlc/tutorial/db.go create mode 100644 examples/with-sqlc/tutorial/models.go create mode 100644 examples/with-sqlc/tutorial/query.sql.go diff --git a/examples/with-sqlc/tutorial/db.go b/examples/with-sqlc/tutorial/db.go new file mode 100644 index 0000000..11d58e5 --- /dev/null +++ b/examples/with-sqlc/tutorial/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.28.0 + +package tutorial + +import ( + "context" + "database/sql" +) + +type DBTX interface { + ExecContext(context.Context, string, ...interface{}) (sql.Result, error) + PrepareContext(context.Context, string) (*sql.Stmt, error) + QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error) + QueryRowContext(context.Context, string, ...interface{}) *sql.Row +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx *sql.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/examples/with-sqlc/tutorial/models.go b/examples/with-sqlc/tutorial/models.go new file mode 100644 index 0000000..246392a --- /dev/null +++ b/examples/with-sqlc/tutorial/models.go @@ -0,0 +1,15 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.28.0 + +package tutorial + +import ( + "database/sql" +) + +type Author struct { + ID int64 + Name string + Bio sql.NullString +} diff --git a/examples/with-sqlc/tutorial/query.sql.go b/examples/with-sqlc/tutorial/query.sql.go new file mode 100644 index 0000000..4d7a6c6 --- /dev/null +++ b/examples/with-sqlc/tutorial/query.sql.go @@ -0,0 +1,100 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.28.0 +// source: query.sql + +package tutorial + +import ( + "context" + "database/sql" +) + +const createAuthor = `-- name: CreateAuthor :one +INSERT INTO authors ( + name, bio +) VALUES ( + ?, ? +) +RETURNING id, name, bio +` + +type CreateAuthorParams struct { + Name string + Bio sql.NullString +} + +func (q *Queries) CreateAuthor(ctx context.Context, arg CreateAuthorParams) (Author, error) { + row := q.db.QueryRowContext(ctx, createAuthor, arg.Name, arg.Bio) + var i Author + err := row.Scan(&i.ID, &i.Name, &i.Bio) + return i, err +} + +const deleteAuthor = `-- name: DeleteAuthor :exec +DELETE FROM authors +WHERE id = ? +` + +func (q *Queries) DeleteAuthor(ctx context.Context, id int64) error { + _, err := q.db.ExecContext(ctx, deleteAuthor, id) + return err +} + +const getAuthor = `-- name: GetAuthor :one +SELECT id, name, bio FROM authors +WHERE id = ? LIMIT 1 +` + +func (q *Queries) GetAuthor(ctx context.Context, id int64) (Author, error) { + row := q.db.QueryRowContext(ctx, getAuthor, id) + var i Author + err := row.Scan(&i.ID, &i.Name, &i.Bio) + return i, err +} + +const listAuthors = `-- name: ListAuthors :many +SELECT id, name, bio FROM authors +ORDER BY name +` + +func (q *Queries) ListAuthors(ctx context.Context) ([]Author, error) { + rows, err := q.db.QueryContext(ctx, listAuthors) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Author + for rows.Next() { + var i Author + if err := rows.Scan(&i.ID, &i.Name, &i.Bio); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const updateAuthor = `-- name: UpdateAuthor :exec +UPDATE authors +set name = ?, +bio = ? +WHERE id = ? +` + +type UpdateAuthorParams struct { + Name string + Bio sql.NullString + ID int64 +} + +func (q *Queries) UpdateAuthor(ctx context.Context, arg UpdateAuthorParams) error { + _, err := q.db.ExecContext(ctx, updateAuthor, arg.Name, arg.Bio, arg.ID) + return err +} From d001cc64a2268c3e633c03696019a439e3c24711 Mon Sep 17 00:00:00 2001 From: akm Date: Wed, 19 Mar 2025 00:41:51 +0900 Subject: [PATCH 06/18] =?UTF-8?q?=E2=9C=A8=20Add=20tutorial.go?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/with-sqlc/tutorial.go | 65 ++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 examples/with-sqlc/tutorial.go diff --git a/examples/with-sqlc/tutorial.go b/examples/with-sqlc/tutorial.go new file mode 100644 index 0000000..55592be --- /dev/null +++ b/examples/with-sqlc/tutorial.go @@ -0,0 +1,65 @@ +package main + +import ( + "context" + "database/sql" + _ "embed" + "log" + "reflect" + + _ "modernc.org/sqlite" + + "tutorial.sqlc.dev/app/tutorial" +) + +//go:embed schema.sql +var ddl string + +func run() error { + ctx := context.Background() + + db, err := sql.Open("sqlite", ":memory:") + if err != nil { + return err + } + + // create tables + if _, err := db.ExecContext(ctx, ddl); err != nil { + return err + } + + queries := tutorial.New(db) + + // list all authors + authors, err := queries.ListAuthors(ctx) + if err != nil { + return err + } + log.Println(authors) + + // create an author + insertedAuthor, err := queries.CreateAuthor(ctx, tutorial.CreateAuthorParams{ + Name: "Brian Kernighan", + Bio: sql.NullString{String: "Co-author of The C Programming Language and The Go Programming Language", Valid: true}, + }) + if err != nil { + return err + } + log.Println(insertedAuthor) + + // get the author we just inserted + fetchedAuthor, err := queries.GetAuthor(ctx, insertedAuthor.ID) + if err != nil { + return err + } + + // prints true + log.Println(reflect.DeepEqual(insertedAuthor, fetchedAuthor)) + return nil +} + +func main() { + if err := run(); err != nil { + log.Fatal(err) + } +} From a50e5d911cf1d261bc421095f5cc77f90e389374 Mon Sep 17 00:00:00 2001 From: akm Date: Wed, 19 Mar 2025 00:42:14 +0900 Subject: [PATCH 07/18] =?UTF-8?q?=F0=9F=A4=96=20[sql-slog/examples/with-sq?= =?UTF-8?q?lc]=20$=20go=20get=20modernc.org/sqlite?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit go: downloading modernc.org/sqlite v1.36.1 go: downloading modernc.org/libc v1.61.13 go: downloading golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0 go: downloading modernc.org/mathutil v1.7.1 go: downloading modernc.org/memory v1.8.2 go: added github.com/dustin/go-humanize v1.0.1 go: added github.com/google/uuid v1.6.0 go: added github.com/mattn/go-isatty v0.0.20 go: added github.com/ncruces/go-strftime v0.1.9 go: added github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec go: added golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0 go: added golang.org/x/sys v0.30.0 go: added modernc.org/libc v1.61.13 go: added modernc.org/mathutil v1.7.1 go: added modernc.org/memory v1.8.2 go: added modernc.org/sqlite v1.36.1 --- examples/with-sqlc/go.mod | 14 ++++++++++++++ examples/with-sqlc/go.sum | 23 +++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 examples/with-sqlc/go.sum diff --git a/examples/with-sqlc/go.mod b/examples/with-sqlc/go.mod index 31f8fdc..d34a801 100644 --- a/examples/with-sqlc/go.mod +++ b/examples/with-sqlc/go.mod @@ -1,3 +1,17 @@ module tutorial.sqlc.dev/app go 1.23.2 + +require ( + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/ncruces/go-strftime v0.1.9 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect + golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0 // indirect + golang.org/x/sys v0.30.0 // indirect + modernc.org/libc v1.61.13 // indirect + modernc.org/mathutil v1.7.1 // indirect + modernc.org/memory v1.8.2 // indirect + modernc.org/sqlite v1.36.1 // indirect +) diff --git a/examples/with-sqlc/go.sum b/examples/with-sqlc/go.sum new file mode 100644 index 0000000..b838c33 --- /dev/null +++ b/examples/with-sqlc/go.sum @@ -0,0 +1,23 @@ +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= +github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0 h1:pVgRXcIictcr+lBQIFeiwuwtDIs4eL21OuM9nyAADmo= +golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +modernc.org/libc v1.61.13 h1:3LRd6ZO1ezsFiX1y+bHd1ipyEHIJKvuprv0sLTBwLW8= +modernc.org/libc v1.61.13/go.mod h1:8F/uJWL/3nNil0Lgt1Dpz+GgkApWh04N3el3hxJcA6E= +modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= +modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= +modernc.org/memory v1.8.2 h1:cL9L4bcoAObu4NkxOlKWBWtNHIsnnACGF/TbqQ6sbcI= +modernc.org/memory v1.8.2/go.mod h1:ZbjSvMO5NQ1A2i3bWeDiVMxIorXwdClKE/0SZ+BMotU= +modernc.org/sqlite v1.36.1 h1:bDa8BJUH4lg6EGkLbahKe/8QqoF8p9gArSc6fTqYhyQ= +modernc.org/sqlite v1.36.1/go.mod h1:7MPwH7Z6bREicF9ZVUR78P1IKuxfZ8mRIDHD0iD+8TU= From 23c92980b58f844f3ba3dc7c7040104084749acf Mon Sep 17 00:00:00 2001 From: akm Date: Wed, 19 Mar 2025 00:43:55 +0900 Subject: [PATCH 08/18] =?UTF-8?q?=F0=9F=A4=96=20$=20[sql-slog/examples/wit?= =?UTF-8?q?h-sqlc]=20go=20mod=20edit=20-replace=20github.com/akm/sql-slog?= =?UTF-8?q?=3D../..?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/with-sqlc/go.mod | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/with-sqlc/go.mod b/examples/with-sqlc/go.mod index d34a801..20e798f 100644 --- a/examples/with-sqlc/go.mod +++ b/examples/with-sqlc/go.mod @@ -15,3 +15,5 @@ require ( modernc.org/memory v1.8.2 // indirect modernc.org/sqlite v1.36.1 // indirect ) + +replace github.com/akm/sql-slog => ../.. From 9c4766e415fecdd78fb651fcba662827bdaf9c39 Mon Sep 17 00:00:00 2001 From: akm Date: Wed, 19 Mar 2025 00:45:11 +0900 Subject: [PATCH 09/18] =?UTF-8?q?=F0=9F=A4=96=20[sql-slog/examples/with-sq?= =?UTF-8?q?lc]=20$=20go=20get=20github.com/akm/sql-slog?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit go: added github.com/akm/sql-slog v0.2.0 --- examples/with-sqlc/go.mod | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/with-sqlc/go.mod b/examples/with-sqlc/go.mod index 20e798f..1cbea99 100644 --- a/examples/with-sqlc/go.mod +++ b/examples/with-sqlc/go.mod @@ -3,6 +3,7 @@ module tutorial.sqlc.dev/app go 1.23.2 require ( + github.com/akm/sql-slog v0.2.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/google/uuid v1.6.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect From cefb5e303c01116bdeef9de4c786a89c195296bb Mon Sep 17 00:00:00 2001 From: akm Date: Wed, 19 Mar 2025 01:35:45 +0900 Subject: [PATCH 10/18] =?UTF-8?q?=E2=9C=A8=20Implement=20driver.NamedValue?= =?UTF-8?q?Checker=20with=20stmt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- stmt.go | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/stmt.go b/stmt.go index d3b0c77..75b0f28 100644 --- a/stmt.go +++ b/stmt.go @@ -37,11 +37,18 @@ func wrapStmt(original driver.Stmt, logger *stepLogger, options *stmtOptions) dr stmtExec, withExecContext := original.(driver.StmtExecContext) stmtQuery, withQueryContext := original.(driver.StmtQueryContext) if withExecContext && withQueryContext { - return &stmtContextWrapper{ + stmtCtxW := &stmtContextWrapper{ stmtWrapper: stmtWrapper, stmtExecContextWrapperImpl: stmtExecContextWrapperImpl{original: stmtExec, logger: logger, options: options}, stmtQueryContextWrapperImpl: stmtQueryContextWrapperImpl{original: stmtQuery, logger: logger, options: options}, } + if nvc, ok := original.(driver.NamedValueChecker); ok { + return &stmtContextNvcWrapper{ + stmtContextWrapper: *stmtCtxW, + NamedValueChecker: nvc, + } + } + return stmtCtxW } // Commented out because the original implementation does not have this check. // @@ -57,6 +64,13 @@ func wrapStmt(original driver.Stmt, logger *stepLogger, options *stmtOptions) dr // stmtQueryContextWrapperImpl: stmtQueryContextWrapperImpl{original: stmtQuery, logger: logger}, // } // } + + if nvc, ok := original.(driver.NamedValueChecker); ok { + return &stmtNvcWrapper{ + stmtWrapper: stmtWrapper, + NamedValueChecker: nvc, + } + } return &stmtWrapper } @@ -185,3 +199,49 @@ var ( _ driver.StmtExecContext = (*stmtContextWrapper)(nil) _ driver.StmtQueryContext = (*stmtContextWrapper)(nil) ) + +// With driver.NamedValueChecker + +type stmtNvcWrapper struct { + stmtWrapper + driver.NamedValueChecker +} + +var ( + _ driver.Stmt = (*stmtNvcWrapper)(nil) + _ driver.NamedValueChecker = (*stmtNvcWrapper)(nil) +) + +type stmtExecContextNvcWrapper struct { + stmtExecContextWrapper + driver.NamedValueChecker +} + +var ( + _ driver.Stmt = (*stmtExecContextNvcWrapper)(nil) + _ driver.StmtExecContext = (*stmtExecContextNvcWrapper)(nil) + _ driver.NamedValueChecker = (*stmtExecContextNvcWrapper)(nil) +) + +type stmtQueryContextNvcWrapper struct { + stmtQueryContextWrapper + driver.NamedValueChecker +} + +var ( + _ driver.Stmt = (*stmtQueryContextNvcWrapper)(nil) + _ driver.StmtQueryContext = (*stmtQueryContextNvcWrapper)(nil) + _ driver.NamedValueChecker = (*stmtQueryContextNvcWrapper)(nil) +) + +type stmtContextNvcWrapper struct { + stmtContextWrapper + driver.NamedValueChecker +} + +var ( + _ driver.Stmt = (*stmtContextNvcWrapper)(nil) + _ driver.StmtExecContext = (*stmtContextNvcWrapper)(nil) + _ driver.StmtQueryContext = (*stmtContextNvcWrapper)(nil) + _ driver.NamedValueChecker = (*stmtContextNvcWrapper)(nil) +) From 055356a391a8c760ea6014c16996e7eb53f6489d Mon Sep 17 00:00:00 2001 From: akm Date: Wed, 19 Mar 2025 01:42:27 +0900 Subject: [PATCH 11/18] =?UTF-8?q?=F0=9F=92=A1=20Remove=20commented-out=20N?= =?UTF-8?q?amedValueChecker=20code=20in=20wrapStmt=20function?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- stmt.go | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/stmt.go b/stmt.go index 75b0f28..2a0eb14 100644 --- a/stmt.go +++ b/stmt.go @@ -64,13 +64,12 @@ func wrapStmt(original driver.Stmt, logger *stepLogger, options *stmtOptions) dr // stmtQueryContextWrapperImpl: stmtQueryContextWrapperImpl{original: stmtQuery, logger: logger}, // } // } - - if nvc, ok := original.(driver.NamedValueChecker); ok { - return &stmtNvcWrapper{ - stmtWrapper: stmtWrapper, - NamedValueChecker: nvc, - } - } + // if nvc, ok := original.(driver.NamedValueChecker); ok { + // return &stmtNvcWrapper{ + // stmtWrapper: stmtWrapper, + // NamedValueChecker: nvc, + // } + // } return &stmtWrapper } From f9e52c86acfa0dfdc222462c8040b9976d66e5eb Mon Sep 17 00:00:00 2001 From: akm Date: Wed, 19 Mar 2025 02:08:43 +0900 Subject: [PATCH 12/18] =?UTF-8?q?=E2=9C=A8=20Enhance=20connection=20wrappe?= =?UTF-8?q?rs=20to=20support=20NamedValueChecker?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- conn.go | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/conn.go b/conn.go index a82225c..8837256 100644 --- a/conn.go +++ b/conn.go @@ -71,7 +71,11 @@ func wrapConn(original driver.Conn, logger *stepLogger, options *connOptions) dr connWrapper := connWrapper{original: original, logger: logger, options: options} if cwc, ok := original.(connWithContext); ok { - return &connWithContextWrapper{connWrapper, cwc} + connWithContextWrapper := &connWithContextWrapper{connWrapper, cwc} + if nvc, ok := original.(driver.NamedValueChecker); ok { + return &connNvcWithContextWrapper{*connWithContextWrapper, nvc} + } + return connWithContextWrapper } // Commented out because it's not used. @@ -109,11 +113,6 @@ var ( _ driver.Validator = (*connWrapper)(nil) ) -// To support custom data types, implement NamedValueChecker. -// NamedValueChecker also allows queries to accept per-query -// options as a parameter by returning ErrRemoveArgument from CheckNamedValue. -var _ driver.NamedValueChecker = (*connWrapper)(nil) - // Begin implements driver.Conn. func (c *connWrapper) Begin() (driver.Tx, error) { var origTx driver.Tx @@ -172,14 +171,6 @@ func (c *connWrapper) IsValid() bool { return true } -// CheckNamedValue implements driver.NamedValueChecker. -func (c *connWrapper) CheckNamedValue(namedValue *driver.NamedValue) error { - if v, ok := c.original.(driver.NamedValueChecker); ok { - return v.CheckNamedValue(namedValue) - } - return nil -} - type connWithContext interface { driver.Conn driver.ExecerContext @@ -349,3 +340,23 @@ func ConnQueryContextErrorHandler(driverName string) func(err error) (bool, []sl return nil } } + +type connNvcWrapper struct { + connWrapper + driver.NamedValueChecker +} + +var ( + _ driver.Conn = (*connNvcWrapper)(nil) + _ driver.NamedValueChecker = (*connNvcWrapper)(nil) +) + +type connNvcWithContextWrapper struct { + connWithContextWrapper + driver.NamedValueChecker +} + +var ( + _ driver.Conn = (*connNvcWithContextWrapper)(nil) + _ driver.NamedValueChecker = (*connNvcWithContextWrapper)(nil) +) From 9d5be0a6e0f57b508111421c72863971ba825a8a Mon Sep 17 00:00:00 2001 From: akm Date: Wed, 19 Mar 2025 02:10:05 +0900 Subject: [PATCH 13/18] =?UTF-8?q?=E2=9C=A8=20Use=20sqlslog=20package=20in?= =?UTF-8?q?=20examples/with-sqlc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/with-sqlc/tutorial.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/with-sqlc/tutorial.go b/examples/with-sqlc/tutorial.go index 55592be..2700988 100644 --- a/examples/with-sqlc/tutorial.go +++ b/examples/with-sqlc/tutorial.go @@ -7,6 +7,7 @@ import ( "log" "reflect" + sqlslog "github.com/akm/sql-slog" _ "modernc.org/sqlite" "tutorial.sqlc.dev/app/tutorial" @@ -18,7 +19,7 @@ var ddl string func run() error { ctx := context.Background() - db, err := sql.Open("sqlite", ":memory:") + db, _, err := sqlslog.Open(ctx, "sqlite", ":memory:") if err != nil { return err } From 485d1f5c2ca332c9514d1c8a53482589ff2ffda8 Mon Sep 17 00:00:00 2001 From: akm Date: Wed, 19 Mar 2025 20:46:21 +0900 Subject: [PATCH 14/18] =?UTF-8?q?=E2=9C=A8=20Skip=20wrapping=20for=20wrapp?= =?UTF-8?q?er=20objects?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- conn.go | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/conn.go b/conn.go index 8837256..43b9bd4 100644 --- a/conn.go +++ b/conn.go @@ -65,17 +65,24 @@ func wrapConn(original driver.Conn, logger *stepLogger, options *connOptions) dr if original == nil { return nil } - if _, ok := original.(*connWithContextWrapper); ok { + switch original.(type) { + case *connWrapper: + return original + // case *connNvcWrapper: + // return original + case *connWithContextWrapper: + return original + case *connNvcWithContextWrapper: return original } connWrapper := connWrapper{original: original, logger: logger, options: options} if cwc, ok := original.(connWithContext); ok { - connWithContextWrapper := &connWithContextWrapper{connWrapper, cwc} + connWrapper2 := connWithContextWrapper{connWrapper, cwc} if nvc, ok := original.(driver.NamedValueChecker); ok { - return &connNvcWithContextWrapper{*connWithContextWrapper, nvc} + return &connNvcWithContextWrapper{connWrapper2, nvc} } - return connWithContextWrapper + return &connWrapper2 } // Commented out because it's not used. From 2de31e2e755a236cb657a4fd65a64f3a0afee946 Mon Sep 17 00:00:00 2001 From: akm Date: Wed, 19 Mar 2025 20:46:50 +0900 Subject: [PATCH 15/18] =?UTF-8?q?=E2=9C=85=20Add=20test=20of=20wrapConn=20?= =?UTF-8?q?for=20wrapper?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- conn_test.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/conn_test.go b/conn_test.go index d8f3982..28faaa8 100644 --- a/conn_test.go +++ b/conn_test.go @@ -44,6 +44,13 @@ func TestWrapConn(t *testing.T) { if conn == nil { t.Fatal("Expected non-nil") } + + t.Run("skip wrapped driver.Conn object", func(t *testing.T) { + res := wrapConn(conn, logger, connOptions) + if res != conn { + t.Fatal("Expected same object") + } + }) }) } From 63f48d07f04668224e172957e07654158ec2cd8d Mon Sep 17 00:00:00 2001 From: akm Date: Wed, 19 Mar 2025 21:27:13 +0900 Subject: [PATCH 16/18] =?UTF-8?q?=E2=9C=A8=20Switch=20using=20sqlslog=20by?= =?UTF-8?q?=20environment=20variable=20SKIP=5FSQLSLOG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/with-sqlc/tutorial.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/examples/with-sqlc/tutorial.go b/examples/with-sqlc/tutorial.go index 2700988..387359a 100644 --- a/examples/with-sqlc/tutorial.go +++ b/examples/with-sqlc/tutorial.go @@ -5,6 +5,7 @@ import ( "database/sql" _ "embed" "log" + "os" "reflect" sqlslog "github.com/akm/sql-slog" @@ -19,7 +20,13 @@ var ddl string func run() error { ctx := context.Background() - db, _, err := sqlslog.Open(ctx, "sqlite", ":memory:") + var db *sql.DB + var err error + if os.Getenv("SKIP_SQLSLOG") != "" { + db, err = sql.Open("sqlite", ":memory:") + } else { + db, _, err = sqlslog.Open(ctx, "sqlite", ":memory:") + } if err != nil { return err } From 46af83042e1c2c9f7fff2cc10796700e741ba572 Mon Sep 17 00:00:00 2001 From: akm Date: Wed, 19 Mar 2025 21:27:33 +0900 Subject: [PATCH 17/18] =?UTF-8?q?=F0=9F=94=A8=20Add=20Makefile=20to=20exam?= =?UTF-8?q?ples/with-sqlc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/with-sqlc/Makefile | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 examples/with-sqlc/Makefile diff --git a/examples/with-sqlc/Makefile b/examples/with-sqlc/Makefile new file mode 100644 index 0000000..b0c99d9 --- /dev/null +++ b/examples/with-sqlc/Makefile @@ -0,0 +1,10 @@ +.PHONY: default +default: run + +.PHONY: build +build: + go build ./... + +.PHONY: run +run: build + go run . From 6bd1fd1ccb88bca979494f1367b42ffde555cd1d Mon Sep 17 00:00:00 2001 From: akm Date: Wed, 19 Mar 2025 21:30:42 +0900 Subject: [PATCH 18/18] =?UTF-8?q?=F0=9F=93=9D=20Add=20description=20about?= =?UTF-8?q?=20examples/with-sqlc=20to=20README.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/README.md b/README.md index 3585d8f..608ec78 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,44 @@ See [godoc examples](https://pkg.go.dev/github.com/akm/sql-slog#example-Open) fo ## EXAMPLES +### [examples/with-sqlc](./examples/with-sqlc/) + +An example showing how sql-slog works with [sqlc](https://sqlc.dev/). +This example is almost same as [Getting started with SQLite](https://docs.sqlc.dev/en/latest/tutorials/getting-started-sqlite.html) but uses [sqlslog.Open](https://pkg.go.dev/github.com/akm/sql-slog#Open) instead of [sql.Open](https://pkg.go.dev/database/sql#Open). + +
Stdout with sqlslog package + +``` +$ make -C examples/with-sqlc run +go build ./... +go run . +time=2025-03-19T21:23:36.992+09:00 level=INFO msg=Open driver=sqlite dsn=:memory: duration=22083 +time=2025-03-19T21:23:36.992+09:00 level=INFO msg=Driver.Open dsn=:memory: duration=274042 conn_id=_hMZDi7TQfEgBKN_ +time=2025-03-19T21:23:36.992+09:00 level=INFO msg=Connector.Connect duration=294292 +time=2025-03-19T21:23:36.993+09:00 level=INFO msg=Conn.ExecContext conn_id=_hMZDi7TQfEgBKN_ query="CREATE TABLE authors (\n id INTEGER PRIMARY KEY,\n name text NOT NULL,\n bio text\n);\n" args=[] duration=537125 +time=2025-03-19T21:23:36.993+09:00 level=INFO msg=Conn.QueryContext conn_id=_hMZDi7TQfEgBKN_ query="-- name: ListAuthors :many\nSELECT id, name, bio FROM authors\nORDER BY name\n" args=[] duration=23250 +2025/03/19 21:23:36 [] +time=2025-03-19T21:23:36.993+09:00 level=INFO msg=Conn.QueryContext conn_id=_hMZDi7TQfEgBKN_ query="-- name: CreateAuthor :one\nINSERT INTO authors (\n name, bio\n) VALUES (\n ?, ?\n)\nRETURNING id, name, bio\n" args="[{Name: Ordinal:1 Value:Brian Kernighan} {Name: Ordinal:2 Value:Co-author of The C Programming Language and The Go Programming Language}]" duration=20375 +2025/03/19 21:23:36 {1 Brian Kernighan {Co-author of The C Programming Language and The Go Programming Language true}} +time=2025-03-19T21:23:36.993+09:00 level=INFO msg=Conn.QueryContext conn_id=_hMZDi7TQfEgBKN_ query="-- name: GetAuthor :one\nSELECT id, name, bio FROM authors\nWHERE id = ? LIMIT 1\n" args="[{Name: Ordinal:1 Value:1}]" duration=8083 +2025/03/19 21:23:36 true +``` + +
+ +
Stdout without sqlslog package + +``` +$ SKIP_SQLSLOG=1 make -C examples/with-sqlc run +go build ./... +go run . +2025/03/19 21:23:19 [] +2025/03/19 21:23:19 {1 Brian Kernighan {Co-author of The C Programming Language and The Go Programming Language true}} +2025/03/19 21:23:19 true +``` + +
+ ### [examples/with-go-requestid](./examples/with-go-requestid/) An example showing how sql-slog works with [go-requestid](https://github.com/akm/go-requestid).