From dd898008f6e216b488f5ee1536a47eff2ff1c634 Mon Sep 17 00:00:00 2001 From: "cemre.mengu" Date: Sat, 18 Nov 2023 12:36:05 +0300 Subject: [PATCH 1/2] add subselect builder for insert --- insert.go | 41 +++++++++++++++++++++++++++++++++++++++++ insert_test.go | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/insert.go b/insert.go index 3f3276e..ff84bbd 100644 --- a/insert.go +++ b/insert.go @@ -13,6 +13,7 @@ const ( insertMarkerAfterInsertInto insertMarkerAfterCols insertMarkerAfterValues + insertMarkerAfterSelect ) // NewInsertBuilder creates a new INSERT builder. @@ -40,6 +41,8 @@ type InsertBuilder struct { injection *injection marker injectionMarker + + sbHolder string } var _ Builder = new(InsertBuilder) @@ -89,6 +92,13 @@ func (ib *InsertBuilder) Cols(col ...string) *InsertBuilder { return ib } +// Select returns a new SelectBuilder to build a SELECT statement inside the INSERT INTO. +func (isb *InsertBuilder) Select(col ...string) *SelectBuilder { + sb := Select(col...) + isb.sbHolder = isb.args.Add(sb) + return sb +} + // Values adds a list of values for a row in INSERT. func (ib *InsertBuilder) Values(value ...interface{}) *InsertBuilder { placeholders := make([]string, 0, len(value)) @@ -120,6 +130,29 @@ func (ib *InsertBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{ buf := newStringBuilder() ib.injection.WriteTo(buf, insertMarkerInit) + if ib.sbHolder != "" && ib.args.Flavor == Oracle { + buf.WriteLeadingString(ib.verb) + + if len(ib.table) > 0 { + buf.WriteString(" INTO ") + buf.WriteString(ib.table) + } + ib.injection.WriteTo(buf, insertMarkerAfterInsertInto) + if len(ib.cols) > 0 { + buf.WriteLeadingString("(") + buf.WriteString(strings.Join(ib.cols, ", ")) + buf.WriteString(")") + + ib.injection.WriteTo(buf, insertMarkerAfterCols) + } + + buf.WriteString(" ") + buf.WriteString(ib.sbHolder) + + ib.injection.WriteTo(buf, insertMarkerAfterSelect) + return ib.args.CompileWithFlavor(buf.String(), flavor, initialArg...) + } + if len(ib.values) > 1 && ib.args.Flavor == Oracle { buf.WriteLeadingString(ib.verb) buf.WriteString(" ALL") @@ -167,6 +200,14 @@ func (ib *InsertBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{ ib.injection.WriteTo(buf, insertMarkerAfterCols) } + if ib.sbHolder != "" { + buf.WriteString(" ") + buf.WriteString(ib.sbHolder) + + ib.injection.WriteTo(buf, insertMarkerAfterSelect) + return ib.args.CompileWithFlavor(buf.String(), flavor, initialArg...) + } + if len(ib.values) > 0 { buf.WriteLeadingString("VALUES ") values := make([]string, 0, len(ib.values)) diff --git a/insert_test.go b/insert_test.go index 23d5333..0f5087c 100644 --- a/insert_test.go +++ b/insert_test.go @@ -179,3 +179,35 @@ func ExampleInsertBuilder_SQL() { // /* before */ INSERT INTO demo.user PARTITION (p0) (id, name, status, created_at) /* after cols */ VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE status = ? // [3 Shawn Du 1 1234567890 1] } + +func ExampleInsertBuilder_subSelect() { + ib := NewInsertBuilder() + ib.InsertInto("demo.user") + ib.Cols("id", "name") + sb := ib.Select("id", "name").From("demo.test") + sb.Where(sb.EQ("id", 1)) + + sql, args := ib.Build() + fmt.Println(sql) + fmt.Println(args) + + // Output: + // INSERT INTO demo.user (id, name) SELECT id, name FROM demo.test WHERE id = ? + // [1] +} + +func ExampleInsertBuilder_subSelect_oracle() { + ib := Oracle.NewInsertBuilder() + ib.InsertInto("demo.user") + ib.Cols("id", "name") + sb := ib.Select("id", "name").From("demo.test") + sb.Where(sb.EQ("id", 1)) + + sql, args := ib.Build() + fmt.Println(sql) + fmt.Println(args) + + // Output: + // INSERT INTO demo.user (id, name) SELECT id, name FROM demo.test WHERE id = :1 + // [1] +} From 9c1c18301b96f2ac66bc41ce9758cfc61fef0c2b Mon Sep 17 00:00:00 2001 From: "cemre.mengu" Date: Sun, 19 Nov 2023 20:26:16 +0300 Subject: [PATCH 2/2] remove unecessary oracle check --- insert.go | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/insert.go b/insert.go index ff84bbd..6ff1576 100644 --- a/insert.go +++ b/insert.go @@ -130,29 +130,6 @@ func (ib *InsertBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{ buf := newStringBuilder() ib.injection.WriteTo(buf, insertMarkerInit) - if ib.sbHolder != "" && ib.args.Flavor == Oracle { - buf.WriteLeadingString(ib.verb) - - if len(ib.table) > 0 { - buf.WriteString(" INTO ") - buf.WriteString(ib.table) - } - ib.injection.WriteTo(buf, insertMarkerAfterInsertInto) - if len(ib.cols) > 0 { - buf.WriteLeadingString("(") - buf.WriteString(strings.Join(ib.cols, ", ")) - buf.WriteString(")") - - ib.injection.WriteTo(buf, insertMarkerAfterCols) - } - - buf.WriteString(" ") - buf.WriteString(ib.sbHolder) - - ib.injection.WriteTo(buf, insertMarkerAfterSelect) - return ib.args.CompileWithFlavor(buf.String(), flavor, initialArg...) - } - if len(ib.values) > 1 && ib.args.Flavor == Oracle { buf.WriteLeadingString(ib.verb) buf.WriteString(" ALL")