From cc4c3afe9209ac5ce5cbc5034b3f9d427371abc4 Mon Sep 17 00:00:00 2001 From: Marwan Sulaiman Date: Tue, 5 Jan 2021 12:42:53 -0500 Subject: [PATCH] Add schema options for sql builders (#1134) --- dialect/sql/builder.go | 34 ++++++++++++++++++++++++++++++++-- dialect/sql/builder_test.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/dialect/sql/builder.go b/dialect/sql/builder.go index 3cc5e1ade..1edcb18f2 100644 --- a/dialect/sql/builder.go +++ b/dialect/sql/builder.go @@ -616,6 +616,7 @@ func (d *DropIndexBuilder) Query() (string, []interface{}) { type InsertBuilder struct { Builder table string + schema string columns []string defaults string returning []string @@ -632,6 +633,12 @@ type InsertBuilder struct { // Note: Insert inserts all values in one batch. func Insert(table string) *InsertBuilder { return &InsertBuilder{table: table} } +// Schema sets the database name for the insert table. +func (i *InsertBuilder) Schema(name string) *InsertBuilder { + i.schema = name + return i +} + // Set is a syntactic sugar API for inserting only one row. func (i *InsertBuilder) Set(column string, v interface{}) *InsertBuilder { i.columns = append(i.columns, column) @@ -675,6 +682,9 @@ func (i *InsertBuilder) Returning(columns ...string) *InsertBuilder { // Query returns query representation of an `INSERT INTO` statement. func (i *InsertBuilder) Query() (string, []interface{}) { i.WriteString("INSERT INTO ") + if i.schema != "" { + i.Ident(i.schema).WriteByte('.') + } i.Ident(i.table).Pad() if i.defaults != "" && len(i.columns) == 0 { i.WriteString(i.defaults) @@ -703,6 +713,7 @@ func (i *InsertBuilder) Query() (string, []interface{}) { type UpdateBuilder struct { Builder table string + schema string where *Predicate nulls []string columns []string @@ -715,6 +726,12 @@ type UpdateBuilder struct { // func Update(table string) *UpdateBuilder { return &UpdateBuilder{table: table} } +// Schema sets the database name for the updated table. +func (u *UpdateBuilder) Schema(name string) *UpdateBuilder { + u.schema = name + return u +} + // Set sets a column and a its value. func (u *UpdateBuilder) Set(column string, v interface{}) *UpdateBuilder { u.columns = append(u.columns, column) @@ -769,6 +786,9 @@ func (u *UpdateBuilder) Empty() bool { // Query returns query representation of an `UPDATE` statement. func (u *UpdateBuilder) Query() (string, []interface{}) { u.WriteString("UPDATE ") + if u.schema != "" { + u.Ident(u.schema).WriteByte('.') + } u.Ident(u.table).WriteString(" SET ") for i, c := range u.nulls { if i > 0 { @@ -801,8 +821,9 @@ func (u *UpdateBuilder) Query() (string, []interface{}) { // DeleteBuilder is a builder for `DELETE` statement. type DeleteBuilder struct { Builder - table string - where *Predicate + table string + schema string + where *Predicate } // Delete creates a builder for the `DELETE` statement. @@ -821,6 +842,12 @@ type DeleteBuilder struct { // func Delete(table string) *DeleteBuilder { return &DeleteBuilder{table: table} } +// Schema sets the database name for the table whose row will be deleted. +func (d *DeleteBuilder) Schema(name string) *DeleteBuilder { + d.schema = name + return d +} + // Where appends a where predicate to the `DELETE` statement. func (d *DeleteBuilder) Where(p *Predicate) *DeleteBuilder { if d.where != nil { @@ -843,6 +870,9 @@ func (d *DeleteBuilder) FromSelect(s *Selector) *DeleteBuilder { // Query returns query representation of a `DELETE` statement. func (d *DeleteBuilder) Query() (string, []interface{}) { d.WriteString("DELETE FROM ") + if d.schema != "" { + d.Ident(d.schema).WriteByte('.') + } d.Ident(d.table) if d.where != nil { d.WriteString(" WHERE ") diff --git a/dialect/sql/builder_test.go b/dialect/sql/builder_test.go index fdf0c3761..d9d44b9a9 100644 --- a/dialect/sql/builder_test.go +++ b/dialect/sql/builder_test.go @@ -223,11 +223,21 @@ func TestBuilder(t *testing.T) { wantQuery: "INSERT INTO `users` (`age`) VALUES (?)", wantArgs: []interface{}{1}, }, + { + input: Insert("users").Columns("age").Values(1).Schema("mydb"), + wantQuery: "INSERT INTO `mydb`.`users` (`age`) VALUES (?)", + wantArgs: []interface{}{1}, + }, { input: Dialect(dialect.Postgres).Insert("users").Columns("age").Values(1), wantQuery: `INSERT INTO "users" ("age") VALUES ($1)`, wantArgs: []interface{}{1}, }, + { + input: Dialect(dialect.Postgres).Insert("users").Columns("age").Values(1).Schema("mydb"), + wantQuery: `INSERT INTO "mydb"."users" ("age") VALUES ($1)`, + wantArgs: []interface{}{1}, + }, { input: Dialect(dialect.Postgres).Insert("users").Columns("age").Values(1).Returning("id"), wantQuery: `INSERT INTO "users" ("age") VALUES ($1) RETURNING "id"`, @@ -272,11 +282,21 @@ func TestBuilder(t *testing.T) { wantQuery: "UPDATE `users` SET `name` = ?", wantArgs: []interface{}{"foo"}, }, + { + input: Update("users").Set("name", "foo").Schema("mydb"), + wantQuery: "UPDATE `mydb`.`users` SET `name` = ?", + wantArgs: []interface{}{"foo"}, + }, { input: Dialect(dialect.Postgres).Update("users").Set("name", "foo"), wantQuery: `UPDATE "users" SET "name" = $1`, wantArgs: []interface{}{"foo"}, }, + { + input: Dialect(dialect.Postgres).Update("users").Set("name", "foo").Schema("mydb"), + wantQuery: `UPDATE "mydb"."users" SET "name" = $1`, + wantArgs: []interface{}{"foo"}, + }, { input: Update("users").Set("name", "foo").Set("age", 10), wantQuery: "UPDATE `users` SET `name` = ?, `age` = ?", @@ -489,12 +509,25 @@ func TestBuilder(t *testing.T) { Where(NotNull("parent_id")), wantQuery: "DELETE FROM `users` WHERE `parent_id` IS NOT NULL", }, + { + input: Delete("users"). + Where(NotNull("parent_id")). + Schema("mydb"), + wantQuery: "DELETE FROM `mydb`.`users` WHERE `parent_id` IS NOT NULL", + }, { input: Dialect(dialect.Postgres). Delete("users"). Where(IsNull("parent_id")), wantQuery: `DELETE FROM "users" WHERE "parent_id" IS NULL`, }, + { + input: Dialect(dialect.Postgres). + Delete("users"). + Where(IsNull("parent_id")). + Schema("mydb"), + wantQuery: `DELETE FROM "mydb"."users" WHERE "parent_id" IS NULL`, + }, { input: Delete("users"). Where(And(IsNull("parent_id"), NotIn("name", "foo", "bar"))),