package orm import ( "github.com/go-pg/pg/types" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) type InsertTest struct { Id int Value string } type EmbeddingTest struct { tableName struct{} `sql:"name"` Id int Field int } type EmbeddedInsertTest struct { tableName struct{} `sql:"my_name"` EmbeddingTest Field2 int } type InheritInsertTest struct { EmbeddingTest `pg:",inherit"` Field2 int } type InsertNullTest struct { F1 int F2 int `sql:",notnull"` F3 int `sql:",pk"` F4 int `sql:",pk,notnull"` } type InsertQTest struct { Geo types.Q Func types.ValueAppender } var _ = Describe("Insert", func() { It("supports Column", func() { model := &InsertTest{ Id: 1, Value: "hello", } q := NewQuery(nil, model).Column("id") b, err := (&insertQuery{q: q}).AppendQuery(nil) Expect(err).NotTo(HaveOccurred()) Expect(string(b)).To(Equal(`INSERT INTO "insert_tests" ("id") VALUES (1)`)) }) It("supports Value", func() { model := &InsertTest{ Id: 1, Value: "hello", } q := NewQuery(nil, model).Value("value", "upper(?)", model.Value) b, err := (&insertQuery{q: q}).AppendQuery(nil) Expect(err).NotTo(HaveOccurred()) Expect(string(b)).To(Equal(`INSERT INTO "insert_tests" ("id", "value") VALUES (1, upper('hello'))`)) }) It("supports Value 2", func() { model := &InsertTest{ Id: 1, Value: "hello", } q := NewQuery(nil, model).Value("value", "upper(?value)") b, err := (&insertQuery{q: q}).AppendQuery(nil) Expect(err).NotTo(HaveOccurred()) Expect(string(b)).To(Equal(`INSERT INTO "insert_tests" ("id", "value") VALUES (1, upper('hello'))`)) }) It("multi inserts", func() { q := NewQuery(nil, &InsertTest{ Id: 1, Value: "hello", }, &InsertTest{ Id: 2, }) b, err := (&insertQuery{q: q}).AppendQuery(nil) Expect(err).NotTo(HaveOccurred()) Expect(string(b)).To(Equal(`INSERT INTO "insert_tests" ("id", "value") VALUES (1, 'hello'), (2, DEFAULT) RETURNING "value"`)) }) It("supports ON CONFLICT DO UPDATE", func() { q := NewQuery(nil, &InsertTest{}). Where("1 = 1"). OnConflict("(unq1) DO UPDATE"). Set("count1 = count1 + 1"). Where("2 = 2") b, err := (&insertQuery{q: q}).AppendQuery(nil) Expect(err).NotTo(HaveOccurred()) Expect(string(b)).To(Equal(`INSERT INTO "insert_tests" AS "insert_test" ("id", "value") VALUES (DEFAULT, DEFAULT) ON CONFLICT (unq1) DO UPDATE SET count1 = count1 + 1 WHERE (2 = 2) RETURNING "id", "value"`)) }) It("supports ON CONFLICT DO UPDATE without SET", func() { q := NewQuery(nil, &InsertTest{}). OnConflict("(unq1) DO UPDATE") b, err := (&insertQuery{q: q}).AppendQuery(nil) Expect(err).NotTo(HaveOccurred()) Expect(string(b)).To(Equal(`INSERT INTO "insert_tests" AS "insert_test" ("id", "value") VALUES (DEFAULT, DEFAULT) ON CONFLICT (unq1) DO UPDATE SET "value" = EXCLUDED."value" RETURNING "id", "value"`)) }) It("supports ON CONFLICT DO NOTHING", func() { q := NewQuery(nil, &InsertTest{}). OnConflict("(unq1) DO NOTHING"). Set("count1 = count1 + 1"). Where("cond1 IS TRUE") b, err := (&insertQuery{q: q}).AppendQuery(nil) Expect(err).NotTo(HaveOccurred()) Expect(string(b)).To(Equal(`INSERT INTO "insert_tests" AS "insert_test" ("id", "value") VALUES (DEFAULT, DEFAULT) ON CONFLICT (unq1) DO NOTHING RETURNING "id", "value"`)) }) It("supports custom table name on embedded struct", func() { q := NewQuery(nil, &EmbeddedInsertTest{}) b, err := (&insertQuery{q: q}).AppendQuery(nil) Expect(err).NotTo(HaveOccurred()) Expect(string(b)).To(Equal(`INSERT INTO my_name ("id", "field", "field2") VALUES (DEFAULT, DEFAULT, DEFAULT) RETURNING "id", "field", "field2"`)) }) It("inherits table name from embedded struct", func() { q := NewQuery(nil, &InheritInsertTest{}) b, err := (&insertQuery{q: q}).AppendQuery(nil) Expect(err).NotTo(HaveOccurred()) Expect(string(b)).To(Equal(`INSERT INTO name ("id", "field", "field2") VALUES (DEFAULT, DEFAULT, DEFAULT) RETURNING "id", "field", "field2"`)) }) It("supports notnull", func() { q := NewQuery(nil, &InsertNullTest{}) b, err := (&insertQuery{q: q}).AppendQuery(nil) Expect(err).NotTo(HaveOccurred()) Expect(string(b)).To(Equal(`INSERT INTO "insert_null_tests" ("f1", "f2", "f3", "f4") VALUES (DEFAULT, 0, DEFAULT, 0) RETURNING "f1", "f3"`)) }) It("inserts types.Q", func() { q := NewQuery(nil, &InsertQTest{ Geo: types.Q("ST_GeomFromText('POLYGON((75.150000 29.530000, 77.000000 29.000000, 77.600000 29.500000, 75.150000 29.530000))')"), Func: Q("my_func(?)", "param"), }) b, err := (&insertQuery{q: q}).AppendQuery(nil) Expect(err).NotTo(HaveOccurred()) Expect(string(b)).To(Equal(`INSERT INTO "insert_q_tests" ("geo", "func") VALUES (ST_GeomFromText('POLYGON((75.150000 29.530000, 77.000000 29.000000, 77.600000 29.500000, 75.150000 29.530000))'), my_func('param'))`)) }) It("supports FROM", func() { q := NewQuery(nil, (*InsertTest)(nil)) q = q.WrapWith("data"). TableExpr("dst"). ColumnExpr("dst_col1, dst_col2"). TableExpr("data") b, err := (&insertQuery{q: q}).AppendQuery(nil) Expect(err).NotTo(HaveOccurred()) Expect(string(b)).To(Equal(`WITH "data" AS (SELECT "insert_test"."id", "insert_test"."value" FROM "insert_tests" AS "insert_test") INSERT INTO dst (dst_col1, dst_col2) SELECT * FROM data`)) }) It("bulk inserts", func() { q := NewQuery(nil, &InsertTest{}, &InsertTest{}) b, err := (&insertQuery{q: q}).AppendQuery(nil) Expect(err).NotTo(HaveOccurred()) Expect(string(b)).To(Equal(`INSERT INTO "insert_tests" ("id", "value") VALUES (DEFAULT, DEFAULT), (DEFAULT, DEFAULT) RETURNING "id", "value"`)) }) It("bulk inserts overriding column value", func() { q := NewQuery(nil, &InsertTest{}, &InsertTest{}). Value("id", "123") b, err := (&insertQuery{q: q}).AppendQuery(nil) Expect(err).NotTo(HaveOccurred()) Expect(string(b)).To(Equal(`INSERT INTO "insert_tests" ("id", "value") VALUES (123, DEFAULT), (123, DEFAULT) RETURNING "value"`)) }) It("returns an error for empty bulk insert", func() { slice := make([]InsertTest, 0) q := NewQuery(nil, &slice) _, err := (&insertQuery{q: q}).AppendQuery(nil) Expect(err).To(MatchError("pg: can't bulk-insert empty slice []orm.InsertTest")) }) It("supports notnull and default", func() { type Model struct { Id int Bool bool `sql:",notnull,default:_"` } q := NewQuery(nil, &Model{}) b, err := (&insertQuery{q: q}).AppendQuery(nil) Expect(err).NotTo(HaveOccurred()) Expect(string(b)).To(Equal(`INSERT INTO "models" ("id", "bool") VALUES (DEFAULT, DEFAULT) RETURNING "id", "bool"`)) }) It("support models without a name", func() { type Model struct { tableName struct{} `sql:"_"` Id int } q := NewQuery(nil, &Model{}).Table("dynamic_name") b, err := (&insertQuery{q: q}).AppendQuery(nil) Expect(err).NotTo(HaveOccurred()) Expect(string(b)).To(Equal(`INSERT INTO "dynamic_name" ("id") VALUES (DEFAULT) RETURNING "id"`)) }) })