From db9de4b7a710a1daf3131fd385849cc8e6afea42 Mon Sep 17 00:00:00 2001 From: stevexu <1161176156@qq.com> Date: Fri, 17 Mar 2023 23:12:45 +0800 Subject: [PATCH 1/2] fix: update panic --- examples/update/noparams/db.go | 31 +++++++++ examples/update/noparams/db_test.go | 67 ++++++++++++++++++ examples/update/noparams/models.go | 22 ++++++ examples/update/noparams/query.sql | 37 ++++++++++ examples/update/noparams/query.sql.go | 93 +++++++++++++++++++++++++ examples/update/noparams/schema.sql | 14 ++++ examples/update/sqlc.json | 27 +++++++ examples/update/withparams/db.go | 31 +++++++++ examples/update/withparams/db_test.go | 62 +++++++++++++++++ examples/update/withparams/models.go | 21 ++++++ examples/update/withparams/query.sql | 32 +++++++++ examples/update/withparams/query.sql.go | 80 +++++++++++++++++++++ examples/update/withparams/schema.sql | 11 +++ internal/engine/dolphin/convert.go | 23 +----- internal/engine/dolphin/utils.go | 37 ++++++++++ 15 files changed, 566 insertions(+), 22 deletions(-) create mode 100644 examples/update/noparams/db.go create mode 100644 examples/update/noparams/db_test.go create mode 100644 examples/update/noparams/models.go create mode 100644 examples/update/noparams/query.sql create mode 100644 examples/update/noparams/query.sql.go create mode 100644 examples/update/noparams/schema.sql create mode 100644 examples/update/sqlc.json create mode 100644 examples/update/withparams/db.go create mode 100644 examples/update/withparams/db_test.go create mode 100644 examples/update/withparams/models.go create mode 100644 examples/update/withparams/query.sql create mode 100644 examples/update/withparams/query.sql.go create mode 100644 examples/update/withparams/schema.sql diff --git a/examples/update/noparams/db.go b/examples/update/noparams/db.go new file mode 100644 index 0000000000..bd986277b7 --- /dev/null +++ b/examples/update/noparams/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.17.2 + +package update + +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/update/noparams/db_test.go b/examples/update/noparams/db_test.go new file mode 100644 index 0000000000..dff1ffa037 --- /dev/null +++ b/examples/update/noparams/db_test.go @@ -0,0 +1,67 @@ +//go:build examples +// +build examples + +package update + +import ( + "context" + "testing" + + "github.com/kyleconroy/sqlc/internal/sqltest" +) + +func TestUpdate(t *testing.T) { + sdb, cleanup := sqltest.MySQL(t, []string{"schema.sql"}) + defer cleanup() + + ctx := context.Background() + db := New(sdb) + + _, err := db.CreateT1(ctx, CreateT1Params{ + UserID: int32(2), + Name: "", + }) + if err != nil { + t.Fatal(err) + } + + // get the data we just inserted + oldData, err := db.GetT1(ctx, int32(2)) + if err != nil { + t.Fatal(err) + } + + if oldData.Name != "" { + t.Fatal("create fail") + } + + _, err = db.CreateT2(ctx, CreateT2Params{ + Email: "test@gmail.com", + Name: "test", + }) + if err != nil { + t.Fatal(err) + } + + _, err = db.CreateT3(ctx, CreateT3Params{ + UserID: int32(2), + Email: "test@gmail.com", + }) + if err != nil { + t.Fatal(err) + } + + err = db.UpdateAll(ctx) + if err != nil { + t.Fatal(err) + } + + newData, err := db.GetT1(ctx, int32(2)) + if err != nil { + t.Fatal(err) + } + + if newData.Name != "test" { + t.Fatal("update fail") + } +} diff --git a/examples/update/noparams/models.go b/examples/update/noparams/models.go new file mode 100644 index 0000000000..6568975c72 --- /dev/null +++ b/examples/update/noparams/models.go @@ -0,0 +1,22 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.17.2 + +package update + +import () + +type T1 struct { + UserID int32 + Name string +} + +type T2 struct { + Email string + Name string +} + +type T3 struct { + UserID int32 + Email string +} diff --git a/examples/update/noparams/query.sql b/examples/update/noparams/query.sql new file mode 100644 index 0000000000..2ba9a6e8ba --- /dev/null +++ b/examples/update/noparams/query.sql @@ -0,0 +1,37 @@ +/* name: CreateT1 :execresult */ +INSERT INTO + t1 (user_id, name) +VALUES + (?, ?); + +/* name: CreateT2 :execresult */ +INSERT INTO + t2 (email, name) +VALUES + (?, ?); + +/* name: CreateT3 :execresult */ +INSERT INTO + t3 (user_id, email) +VALUES + (?, ?); + +/* name: UpdateAll :exec */ +UPDATE + t1 + INNER JOIN t3 ON t3.user_id = t1.user_id + INNER JOIN t2 ON t2.email = t3.email +SET + t1.name = t2.name +WHERE + t1.name = ''; + +/* name: GetT1 :one */ +SELECT + * +FROM + t1 +WHERE + user_id = ? +LIMIT + 1; \ No newline at end of file diff --git a/examples/update/noparams/query.sql.go b/examples/update/noparams/query.sql.go new file mode 100644 index 0000000000..b3bccc0708 --- /dev/null +++ b/examples/update/noparams/query.sql.go @@ -0,0 +1,93 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.17.2 +// source: query.sql + +package update + +import ( + "context" + "database/sql" +) + +const createT1 = `-- name: CreateT1 :execresult +INSERT INTO + t1 (user_id, name) +VALUES + (?, ?) +` + +type CreateT1Params struct { + UserID int32 + Name string +} + +func (q *Queries) CreateT1(ctx context.Context, arg CreateT1Params) (sql.Result, error) { + return q.db.ExecContext(ctx, createT1, arg.UserID, arg.Name) +} + +const createT2 = `-- name: CreateT2 :execresult +INSERT INTO + t2 (email, name) +VALUES + (?, ?) +` + +type CreateT2Params struct { + Email string + Name string +} + +func (q *Queries) CreateT2(ctx context.Context, arg CreateT2Params) (sql.Result, error) { + return q.db.ExecContext(ctx, createT2, arg.Email, arg.Name) +} + +const createT3 = `-- name: CreateT3 :execresult +INSERT INTO + t3 (user_id, email) +VALUES + (?, ?) +` + +type CreateT3Params struct { + UserID int32 + Email string +} + +func (q *Queries) CreateT3(ctx context.Context, arg CreateT3Params) (sql.Result, error) { + return q.db.ExecContext(ctx, createT3, arg.UserID, arg.Email) +} + +const getT1 = `-- name: GetT1 :one +SELECT + user_id, name +FROM + t1 +WHERE + user_id = ? +LIMIT + 1 +` + +func (q *Queries) GetT1(ctx context.Context, userID int32) (T1, error) { + row := q.db.QueryRowContext(ctx, getT1, userID) + var i T1 + err := row.Scan(&i.UserID, &i.Name) + return i, err +} + +const updateAll = `-- name: UpdateAll :exec +UPDATE + t1 + INNER JOIN t3 ON t3.user_id = t1.user_id + INNER JOIN t2 ON t2.email = t3.email +SET + t1.name = t2.name +WHERE + t1.name = '' +` + +func (q *Queries) UpdateAll(ctx context.Context) error { + _, err := q.db.ExecContext(ctx, updateAll) + return err +} diff --git a/examples/update/noparams/schema.sql b/examples/update/noparams/schema.sql new file mode 100644 index 0000000000..fce347c590 --- /dev/null +++ b/examples/update/noparams/schema.sql @@ -0,0 +1,14 @@ +CREATE TABLE t1 ( + user_id int NOT NULL, + name varchar(255) NOT NULL +); + +CREATE TABLE t2 ( + email varchar(255) NOT NULL, + name varchar(255) NOT NULL +); + +CREATE TABLE t3 ( + user_id int NOT NULL, + email varchar(255) NOT NULL +); \ No newline at end of file diff --git a/examples/update/sqlc.json b/examples/update/sqlc.json new file mode 100644 index 0000000000..8c7815073a --- /dev/null +++ b/examples/update/sqlc.json @@ -0,0 +1,27 @@ +{ + "version": "2", + "sql": [ + { + "schema": "withparams/schema.sql", + "queries": "withparams/query.sql", + "engine": "mysql", + "gen": { + "go": { + "package": "update", + "out": "withparams" + } + } + }, + { + "schema": "noparams/schema.sql", + "queries": "noparams/query.sql", + "engine": "mysql", + "gen": { + "go": { + "package": "update", + "out": "noparams" + } + } + } + ] +} \ No newline at end of file diff --git a/examples/update/withparams/db.go b/examples/update/withparams/db.go new file mode 100644 index 0000000000..bd986277b7 --- /dev/null +++ b/examples/update/withparams/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.17.2 + +package update + +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/update/withparams/db_test.go b/examples/update/withparams/db_test.go new file mode 100644 index 0000000000..c96fafcea3 --- /dev/null +++ b/examples/update/withparams/db_test.go @@ -0,0 +1,62 @@ +//go:build examples +// +build examples + +package update + +import ( + "context" + "testing" + "time" + + "github.com/kyleconroy/sqlc/internal/sqltest" +) + +func TestAuthor(t *testing.T) { + sdb, cleanup := sqltest.MySQL(t, []string{"schema.sql"}) + defer cleanup() + + ctx := context.Background() + db := New(sdb) + + // create an author + result, err := db.CreateAuthor(ctx, CreateAuthorParams{ + Name: "Brian Kernighan", + DeletedAt: time.Now(), + UpdatedAt: time.Now(), + }) + if err != nil { + t.Fatal(err) + } + authorID, err := result.LastInsertId() + if err != nil { + t.Fatal(err) + } + t.Log(authorID) + + // get the author we just inserted + fetchedAuthor, err := db.GetAuthor(ctx, authorID) + if err != nil { + t.Fatal(err) + } + + // create a book + _, err = db.CreateBook(ctx, true) + if err != nil { + t.Fatal(err) + } + + err = db.DeleteAuthor(ctx, "Brian Kernighan") + if err != nil { + t.Fatal(err) + } + + // get the author we just inserted + newFetchedAuthor, err := db.GetAuthor(ctx, authorID) + if err != nil { + t.Fatal(err) + } + t.Log(fetchedAuthor) + if newFetchedAuthor.DeletedAt.Unix() != fetchedAuthor.DeletedAt.Unix() && newFetchedAuthor.DeletedAt.Unix() != newFetchedAuthor.UpdatedAt.Unix() { + t.Fatal("update fail") + } +} diff --git a/examples/update/withparams/models.go b/examples/update/withparams/models.go new file mode 100644 index 0000000000..d9d947d4e9 --- /dev/null +++ b/examples/update/withparams/models.go @@ -0,0 +1,21 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.17.2 + +package update + +import ( + "time" +) + +type Author struct { + ID int64 + Name string + DeletedAt time.Time + UpdatedAt time.Time +} + +type Book struct { + ID int64 + IsAmazing bool +} diff --git a/examples/update/withparams/query.sql b/examples/update/withparams/query.sql new file mode 100644 index 0000000000..0df304a467 --- /dev/null +++ b/examples/update/withparams/query.sql @@ -0,0 +1,32 @@ +/* name: CreateAuthor :execresult */ +INSERT INTO + authors (name, deleted_at, updated_at) +VALUES + (?, ?, ?); + +/* name: CreateBook :execresult */ +INSERT INTO + books (is_amazing) +VALUES + (?); + +/* name: GetAuthor :one */ +SELECT + * +FROM + authors +WHERE + id = ? +LIMIT + 1; + +/* name: DeleteAuthor :exec */ +UPDATE + authors, + books +SET + authors.deleted_at = now(), + authors.updated_at = now() +WHERE + books.is_amazing = 1 + AND authors.name = sqlc.arg(name); \ No newline at end of file diff --git a/examples/update/withparams/query.sql.go b/examples/update/withparams/query.sql.go new file mode 100644 index 0000000000..423659d8f1 --- /dev/null +++ b/examples/update/withparams/query.sql.go @@ -0,0 +1,80 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.17.2 +// source: query.sql + +package update + +import ( + "context" + "database/sql" + "time" +) + +const createAuthor = `-- name: CreateAuthor :execresult +INSERT INTO + authors (name, deleted_at, updated_at) +VALUES + (?, ?, ?) +` + +type CreateAuthorParams struct { + Name string + DeletedAt time.Time + UpdatedAt time.Time +} + +func (q *Queries) CreateAuthor(ctx context.Context, arg CreateAuthorParams) (sql.Result, error) { + return q.db.ExecContext(ctx, createAuthor, arg.Name, arg.DeletedAt, arg.UpdatedAt) +} + +const createBook = `-- name: CreateBook :execresult +INSERT INTO + books (is_amazing) +VALUES + (?) +` + +func (q *Queries) CreateBook(ctx context.Context, isAmazing bool) (sql.Result, error) { + return q.db.ExecContext(ctx, createBook, isAmazing) +} + +const deleteAuthor = `-- name: DeleteAuthor :exec +UPDATE + authors, + books +SET + authors.deleted_at = now(), + authors.updated_at = now() +WHERE + books.is_amazing = 1 + AND authors.name = ? +` + +func (q *Queries) DeleteAuthor(ctx context.Context, name string) error { + _, err := q.db.ExecContext(ctx, deleteAuthor, name) + return err +} + +const getAuthor = `-- name: GetAuthor :one +SELECT + id, name, deleted_at, updated_at +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.DeletedAt, + &i.UpdatedAt, + ) + return i, err +} diff --git a/examples/update/withparams/schema.sql b/examples/update/withparams/schema.sql new file mode 100644 index 0000000000..96ca3aeb47 --- /dev/null +++ b/examples/update/withparams/schema.sql @@ -0,0 +1,11 @@ +CREATE TABLE authors ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + name text NOT NULL, + deleted_at datetime NOT NULL, + updated_at datetime NOT NULL +); + +CREATE TABLE books ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + is_amazing tinyint(1) NOT NULL +); \ No newline at end of file diff --git a/internal/engine/dolphin/convert.go b/internal/engine/dolphin/convert.go index 744eb538e8..e38aefe4a5 100644 --- a/internal/engine/dolphin/convert.go +++ b/internal/engine/dolphin/convert.go @@ -565,28 +565,7 @@ func (c *cc) convertUpdateStmt(n *pcast.UpdateStmt) *ast.UpdateStmt { } relations := &ast.List{} - switch rel := rels.Items[0].(type) { - - // Special case for joins in updates - case *ast.JoinExpr: - left, ok := rel.Larg.(*ast.RangeVar) - if !ok { - panic("expected range var") - } - relations.Items = append(relations.Items, left) - - right, ok := rel.Rarg.(*ast.RangeVar) - if !ok { - panic("expected range var") - } - relations.Items = append(relations.Items, right) - - case *ast.RangeVar: - relations.Items = append(relations.Items, rel) - - default: - panic("expected range var") - } + convertToRangeVarList(rels, relations) // TargetList list := &ast.List{} diff --git a/internal/engine/dolphin/utils.go b/internal/engine/dolphin/utils.go index d39d189afc..9ca273614a 100644 --- a/internal/engine/dolphin/utils.go +++ b/internal/engine/dolphin/utils.go @@ -96,3 +96,40 @@ func isNotNull(n *pcast.ColumnDef) bool { } return false } + +func convertToRangeVarList(list *ast.List, result *ast.List) { + switch rel := list.Items[0].(type) { + + // Special case for joins in updates + case *ast.JoinExpr: + left, ok := rel.Larg.(*ast.RangeVar) + if !ok { + if list, check := rel.Larg.(*ast.List); check { + convertToRangeVarList(list, result) + } else { + panic("expected range var") + } + } + if left != nil { + result.Items = append(result.Items, left) + } + + right, ok := rel.Rarg.(*ast.RangeVar) + if !ok { + if list, check := rel.Rarg.(*ast.List); check { + convertToRangeVarList(list, result) + } else { + panic("expected range var") + } + } + if right != nil { + result.Items = append(result.Items, right) + } + + case *ast.RangeVar: + result.Items = append(result.Items, rel) + + default: + panic("expected range var") + } +} From 8ae0107fb2e62120e3648b01618f55a19c86de9b Mon Sep 17 00:00:00 2001 From: stevexu <1161176156@qq.com> Date: Sat, 18 Mar 2023 10:44:15 +0800 Subject: [PATCH 2/2] fix: add test data --- examples/update/noparams/db_test.go | 67 ------------- examples/update/noparams/models.go | 22 ----- examples/update/noparams/query.sql | 37 -------- examples/update/noparams/query.sql.go | 93 ------------------- examples/update/noparams/schema.sql | 14 --- examples/update/sqlc.json | 27 ------ examples/update/withparams/db.go | 31 ------- examples/update/withparams/db_test.go | 62 ------------- examples/update/withparams/query.sql | 32 ------- examples/update/withparams/query.sql.go | 80 ---------------- examples/update/withparams/schema.sql | 11 --- .../testdata/update_two_table/mysql/go}/db.go | 2 +- .../update_two_table/mysql/go}/models.go | 8 +- .../update_two_table/mysql/go/query.sql.go | 27 ++++++ .../testdata/update_two_table/mysql/query.sql | 25 +++++ .../testdata/update_two_table/mysql/sqlc.json | 12 +++ internal/engine/dolphin/utils.go | 3 + 17 files changed, 73 insertions(+), 480 deletions(-) delete mode 100644 examples/update/noparams/db_test.go delete mode 100644 examples/update/noparams/models.go delete mode 100644 examples/update/noparams/query.sql delete mode 100644 examples/update/noparams/query.sql.go delete mode 100644 examples/update/noparams/schema.sql delete mode 100644 examples/update/sqlc.json delete mode 100644 examples/update/withparams/db.go delete mode 100644 examples/update/withparams/db_test.go delete mode 100644 examples/update/withparams/query.sql delete mode 100644 examples/update/withparams/query.sql.go delete mode 100644 examples/update/withparams/schema.sql rename {examples/update/noparams => internal/endtoend/testdata/update_two_table/mysql/go}/db.go (97%) rename {examples/update/withparams => internal/endtoend/testdata/update_two_table/mysql/go}/models.go (67%) create mode 100644 internal/endtoend/testdata/update_two_table/mysql/go/query.sql.go create mode 100644 internal/endtoend/testdata/update_two_table/mysql/query.sql create mode 100644 internal/endtoend/testdata/update_two_table/mysql/sqlc.json diff --git a/examples/update/noparams/db_test.go b/examples/update/noparams/db_test.go deleted file mode 100644 index dff1ffa037..0000000000 --- a/examples/update/noparams/db_test.go +++ /dev/null @@ -1,67 +0,0 @@ -//go:build examples -// +build examples - -package update - -import ( - "context" - "testing" - - "github.com/kyleconroy/sqlc/internal/sqltest" -) - -func TestUpdate(t *testing.T) { - sdb, cleanup := sqltest.MySQL(t, []string{"schema.sql"}) - defer cleanup() - - ctx := context.Background() - db := New(sdb) - - _, err := db.CreateT1(ctx, CreateT1Params{ - UserID: int32(2), - Name: "", - }) - if err != nil { - t.Fatal(err) - } - - // get the data we just inserted - oldData, err := db.GetT1(ctx, int32(2)) - if err != nil { - t.Fatal(err) - } - - if oldData.Name != "" { - t.Fatal("create fail") - } - - _, err = db.CreateT2(ctx, CreateT2Params{ - Email: "test@gmail.com", - Name: "test", - }) - if err != nil { - t.Fatal(err) - } - - _, err = db.CreateT3(ctx, CreateT3Params{ - UserID: int32(2), - Email: "test@gmail.com", - }) - if err != nil { - t.Fatal(err) - } - - err = db.UpdateAll(ctx) - if err != nil { - t.Fatal(err) - } - - newData, err := db.GetT1(ctx, int32(2)) - if err != nil { - t.Fatal(err) - } - - if newData.Name != "test" { - t.Fatal("update fail") - } -} diff --git a/examples/update/noparams/models.go b/examples/update/noparams/models.go deleted file mode 100644 index 6568975c72..0000000000 --- a/examples/update/noparams/models.go +++ /dev/null @@ -1,22 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. -// versions: -// sqlc v1.17.2 - -package update - -import () - -type T1 struct { - UserID int32 - Name string -} - -type T2 struct { - Email string - Name string -} - -type T3 struct { - UserID int32 - Email string -} diff --git a/examples/update/noparams/query.sql b/examples/update/noparams/query.sql deleted file mode 100644 index 2ba9a6e8ba..0000000000 --- a/examples/update/noparams/query.sql +++ /dev/null @@ -1,37 +0,0 @@ -/* name: CreateT1 :execresult */ -INSERT INTO - t1 (user_id, name) -VALUES - (?, ?); - -/* name: CreateT2 :execresult */ -INSERT INTO - t2 (email, name) -VALUES - (?, ?); - -/* name: CreateT3 :execresult */ -INSERT INTO - t3 (user_id, email) -VALUES - (?, ?); - -/* name: UpdateAll :exec */ -UPDATE - t1 - INNER JOIN t3 ON t3.user_id = t1.user_id - INNER JOIN t2 ON t2.email = t3.email -SET - t1.name = t2.name -WHERE - t1.name = ''; - -/* name: GetT1 :one */ -SELECT - * -FROM - t1 -WHERE - user_id = ? -LIMIT - 1; \ No newline at end of file diff --git a/examples/update/noparams/query.sql.go b/examples/update/noparams/query.sql.go deleted file mode 100644 index b3bccc0708..0000000000 --- a/examples/update/noparams/query.sql.go +++ /dev/null @@ -1,93 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. -// versions: -// sqlc v1.17.2 -// source: query.sql - -package update - -import ( - "context" - "database/sql" -) - -const createT1 = `-- name: CreateT1 :execresult -INSERT INTO - t1 (user_id, name) -VALUES - (?, ?) -` - -type CreateT1Params struct { - UserID int32 - Name string -} - -func (q *Queries) CreateT1(ctx context.Context, arg CreateT1Params) (sql.Result, error) { - return q.db.ExecContext(ctx, createT1, arg.UserID, arg.Name) -} - -const createT2 = `-- name: CreateT2 :execresult -INSERT INTO - t2 (email, name) -VALUES - (?, ?) -` - -type CreateT2Params struct { - Email string - Name string -} - -func (q *Queries) CreateT2(ctx context.Context, arg CreateT2Params) (sql.Result, error) { - return q.db.ExecContext(ctx, createT2, arg.Email, arg.Name) -} - -const createT3 = `-- name: CreateT3 :execresult -INSERT INTO - t3 (user_id, email) -VALUES - (?, ?) -` - -type CreateT3Params struct { - UserID int32 - Email string -} - -func (q *Queries) CreateT3(ctx context.Context, arg CreateT3Params) (sql.Result, error) { - return q.db.ExecContext(ctx, createT3, arg.UserID, arg.Email) -} - -const getT1 = `-- name: GetT1 :one -SELECT - user_id, name -FROM - t1 -WHERE - user_id = ? -LIMIT - 1 -` - -func (q *Queries) GetT1(ctx context.Context, userID int32) (T1, error) { - row := q.db.QueryRowContext(ctx, getT1, userID) - var i T1 - err := row.Scan(&i.UserID, &i.Name) - return i, err -} - -const updateAll = `-- name: UpdateAll :exec -UPDATE - t1 - INNER JOIN t3 ON t3.user_id = t1.user_id - INNER JOIN t2 ON t2.email = t3.email -SET - t1.name = t2.name -WHERE - t1.name = '' -` - -func (q *Queries) UpdateAll(ctx context.Context) error { - _, err := q.db.ExecContext(ctx, updateAll) - return err -} diff --git a/examples/update/noparams/schema.sql b/examples/update/noparams/schema.sql deleted file mode 100644 index fce347c590..0000000000 --- a/examples/update/noparams/schema.sql +++ /dev/null @@ -1,14 +0,0 @@ -CREATE TABLE t1 ( - user_id int NOT NULL, - name varchar(255) NOT NULL -); - -CREATE TABLE t2 ( - email varchar(255) NOT NULL, - name varchar(255) NOT NULL -); - -CREATE TABLE t3 ( - user_id int NOT NULL, - email varchar(255) NOT NULL -); \ No newline at end of file diff --git a/examples/update/sqlc.json b/examples/update/sqlc.json deleted file mode 100644 index 8c7815073a..0000000000 --- a/examples/update/sqlc.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "version": "2", - "sql": [ - { - "schema": "withparams/schema.sql", - "queries": "withparams/query.sql", - "engine": "mysql", - "gen": { - "go": { - "package": "update", - "out": "withparams" - } - } - }, - { - "schema": "noparams/schema.sql", - "queries": "noparams/query.sql", - "engine": "mysql", - "gen": { - "go": { - "package": "update", - "out": "noparams" - } - } - } - ] -} \ No newline at end of file diff --git a/examples/update/withparams/db.go b/examples/update/withparams/db.go deleted file mode 100644 index bd986277b7..0000000000 --- a/examples/update/withparams/db.go +++ /dev/null @@ -1,31 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. -// versions: -// sqlc v1.17.2 - -package update - -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/update/withparams/db_test.go b/examples/update/withparams/db_test.go deleted file mode 100644 index c96fafcea3..0000000000 --- a/examples/update/withparams/db_test.go +++ /dev/null @@ -1,62 +0,0 @@ -//go:build examples -// +build examples - -package update - -import ( - "context" - "testing" - "time" - - "github.com/kyleconroy/sqlc/internal/sqltest" -) - -func TestAuthor(t *testing.T) { - sdb, cleanup := sqltest.MySQL(t, []string{"schema.sql"}) - defer cleanup() - - ctx := context.Background() - db := New(sdb) - - // create an author - result, err := db.CreateAuthor(ctx, CreateAuthorParams{ - Name: "Brian Kernighan", - DeletedAt: time.Now(), - UpdatedAt: time.Now(), - }) - if err != nil { - t.Fatal(err) - } - authorID, err := result.LastInsertId() - if err != nil { - t.Fatal(err) - } - t.Log(authorID) - - // get the author we just inserted - fetchedAuthor, err := db.GetAuthor(ctx, authorID) - if err != nil { - t.Fatal(err) - } - - // create a book - _, err = db.CreateBook(ctx, true) - if err != nil { - t.Fatal(err) - } - - err = db.DeleteAuthor(ctx, "Brian Kernighan") - if err != nil { - t.Fatal(err) - } - - // get the author we just inserted - newFetchedAuthor, err := db.GetAuthor(ctx, authorID) - if err != nil { - t.Fatal(err) - } - t.Log(fetchedAuthor) - if newFetchedAuthor.DeletedAt.Unix() != fetchedAuthor.DeletedAt.Unix() && newFetchedAuthor.DeletedAt.Unix() != newFetchedAuthor.UpdatedAt.Unix() { - t.Fatal("update fail") - } -} diff --git a/examples/update/withparams/query.sql b/examples/update/withparams/query.sql deleted file mode 100644 index 0df304a467..0000000000 --- a/examples/update/withparams/query.sql +++ /dev/null @@ -1,32 +0,0 @@ -/* name: CreateAuthor :execresult */ -INSERT INTO - authors (name, deleted_at, updated_at) -VALUES - (?, ?, ?); - -/* name: CreateBook :execresult */ -INSERT INTO - books (is_amazing) -VALUES - (?); - -/* name: GetAuthor :one */ -SELECT - * -FROM - authors -WHERE - id = ? -LIMIT - 1; - -/* name: DeleteAuthor :exec */ -UPDATE - authors, - books -SET - authors.deleted_at = now(), - authors.updated_at = now() -WHERE - books.is_amazing = 1 - AND authors.name = sqlc.arg(name); \ No newline at end of file diff --git a/examples/update/withparams/query.sql.go b/examples/update/withparams/query.sql.go deleted file mode 100644 index 423659d8f1..0000000000 --- a/examples/update/withparams/query.sql.go +++ /dev/null @@ -1,80 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. -// versions: -// sqlc v1.17.2 -// source: query.sql - -package update - -import ( - "context" - "database/sql" - "time" -) - -const createAuthor = `-- name: CreateAuthor :execresult -INSERT INTO - authors (name, deleted_at, updated_at) -VALUES - (?, ?, ?) -` - -type CreateAuthorParams struct { - Name string - DeletedAt time.Time - UpdatedAt time.Time -} - -func (q *Queries) CreateAuthor(ctx context.Context, arg CreateAuthorParams) (sql.Result, error) { - return q.db.ExecContext(ctx, createAuthor, arg.Name, arg.DeletedAt, arg.UpdatedAt) -} - -const createBook = `-- name: CreateBook :execresult -INSERT INTO - books (is_amazing) -VALUES - (?) -` - -func (q *Queries) CreateBook(ctx context.Context, isAmazing bool) (sql.Result, error) { - return q.db.ExecContext(ctx, createBook, isAmazing) -} - -const deleteAuthor = `-- name: DeleteAuthor :exec -UPDATE - authors, - books -SET - authors.deleted_at = now(), - authors.updated_at = now() -WHERE - books.is_amazing = 1 - AND authors.name = ? -` - -func (q *Queries) DeleteAuthor(ctx context.Context, name string) error { - _, err := q.db.ExecContext(ctx, deleteAuthor, name) - return err -} - -const getAuthor = `-- name: GetAuthor :one -SELECT - id, name, deleted_at, updated_at -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.DeletedAt, - &i.UpdatedAt, - ) - return i, err -} diff --git a/examples/update/withparams/schema.sql b/examples/update/withparams/schema.sql deleted file mode 100644 index 96ca3aeb47..0000000000 --- a/examples/update/withparams/schema.sql +++ /dev/null @@ -1,11 +0,0 @@ -CREATE TABLE authors ( - id BIGINT PRIMARY KEY AUTO_INCREMENT, - name text NOT NULL, - deleted_at datetime NOT NULL, - updated_at datetime NOT NULL -); - -CREATE TABLE books ( - id BIGINT PRIMARY KEY AUTO_INCREMENT, - is_amazing tinyint(1) NOT NULL -); \ No newline at end of file diff --git a/examples/update/noparams/db.go b/internal/endtoend/testdata/update_two_table/mysql/go/db.go similarity index 97% rename from examples/update/noparams/db.go rename to internal/endtoend/testdata/update_two_table/mysql/go/db.go index bd986277b7..02974bda59 100644 --- a/examples/update/noparams/db.go +++ b/internal/endtoend/testdata/update_two_table/mysql/go/db.go @@ -2,7 +2,7 @@ // versions: // sqlc v1.17.2 -package update +package querytest import ( "context" diff --git a/examples/update/withparams/models.go b/internal/endtoend/testdata/update_two_table/mysql/go/models.go similarity index 67% rename from examples/update/withparams/models.go rename to internal/endtoend/testdata/update_two_table/mysql/go/models.go index d9d947d4e9..56be609dcb 100644 --- a/examples/update/withparams/models.go +++ b/internal/endtoend/testdata/update_two_table/mysql/go/models.go @@ -2,20 +2,22 @@ // versions: // sqlc v1.17.2 -package update +package querytest import ( "time" ) type Author struct { - ID int64 Name string DeletedAt time.Time + CreatedAt time.Time UpdatedAt time.Time } type Book struct { - ID int64 IsAmazing bool + DeletedAt time.Time + CreatedAt time.Time + UpdatedAt time.Time } diff --git a/internal/endtoend/testdata/update_two_table/mysql/go/query.sql.go b/internal/endtoend/testdata/update_two_table/mysql/go/query.sql.go new file mode 100644 index 0000000000..6d960f030d --- /dev/null +++ b/internal/endtoend/testdata/update_two_table/mysql/go/query.sql.go @@ -0,0 +1,27 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.17.2 +// source: query.sql + +package querytest + +import ( + "context" +) + +const deleteAuthor = `-- name: DeleteAuthor :exec +UPDATE + authors, + books +SET + authors.deleted_at = now(), + books.deleted_at = now() +WHERE + books.is_amazing = 1 + AND authors.name = ? +` + +func (q *Queries) DeleteAuthor(ctx context.Context, name string) error { + _, err := q.db.ExecContext(ctx, deleteAuthor, name) + return err +} diff --git a/internal/endtoend/testdata/update_two_table/mysql/query.sql b/internal/endtoend/testdata/update_two_table/mysql/query.sql new file mode 100644 index 0000000000..1d8f9dd1e8 --- /dev/null +++ b/internal/endtoend/testdata/update_two_table/mysql/query.sql @@ -0,0 +1,25 @@ +-- https://github.com/kyleconroy/sqlc/issues/1590 +CREATE TABLE authors ( + name text NOT NULL, + deleted_at datetime NOT NULL, + created_at datetime NOT NULL, + updated_at datetime NOT NULL +); + +CREATE TABLE books ( + is_amazing tinyint(1) NOT NULL, + deleted_at datetime NOT NULL, + created_at datetime NOT NULL, + updated_at datetime NOT NULL +); + +-- name: DeleteAuthor :exec +UPDATE + authors, + books +SET + authors.deleted_at = now(), + books.deleted_at = now() +WHERE + books.is_amazing = 1 + AND authors.name = sqlc.arg(name); \ No newline at end of file diff --git a/internal/endtoend/testdata/update_two_table/mysql/sqlc.json b/internal/endtoend/testdata/update_two_table/mysql/sqlc.json new file mode 100644 index 0000000000..445bbd1589 --- /dev/null +++ b/internal/endtoend/testdata/update_two_table/mysql/sqlc.json @@ -0,0 +1,12 @@ +{ + "version": "1", + "packages": [ + { + "path": "go", + "engine": "mysql", + "name": "querytest", + "schema": "query.sql", + "queries": "query.sql" + } + ] +} diff --git a/internal/engine/dolphin/utils.go b/internal/engine/dolphin/utils.go index 9ca273614a..8284785c93 100644 --- a/internal/engine/dolphin/utils.go +++ b/internal/engine/dolphin/utils.go @@ -98,6 +98,9 @@ func isNotNull(n *pcast.ColumnDef) bool { } func convertToRangeVarList(list *ast.List, result *ast.List) { + if len(list.Items) == 0 { + return + } switch rel := list.Items[0].(type) { // Special case for joins in updates