From 2183af42f426ba0f27f529dbab50b3c4a52946ef Mon Sep 17 00:00:00 2001 From: go-jet Date: Fri, 1 Nov 2024 12:34:46 +0100 Subject: [PATCH] Add PostgreSQL-specific character type constructors: Text, Char, and VarChar. --- README.md | 70 ++++++++++++++--------------- examples/quick-start/quick-start.go | 4 +- go.mod | 8 ++-- go.sum | 4 +- postgres/literal.go | 67 ++++++++++++++++----------- postgres/literal_test.go | 29 ++++-------- postgres/values.go | 4 +- tests/postgres/alltypes_test.go | 38 ++++++++-------- tests/postgres/select_test.go | 48 ++++++++++---------- tests/postgres/values_test.go | 24 +++++----- 10 files changed, 152 insertions(+), 144 deletions(-) diff --git a/README.md b/README.md index c84dd4e7..3d5f57d2 100644 --- a/README.md +++ b/README.md @@ -175,9 +175,9 @@ stmt := SELECT( INNER_JOIN(FilmCategory, FilmCategory.FilmID.EQ(Film.FilmID)). INNER_JOIN(Category, Category.CategoryID.EQ(FilmCategory.CategoryID)), ).WHERE( - Language.Name.EQ(String("English")). - AND(Category.Name.NOT_EQ(String("Action"))). - AND(Film.Length.GT(Int(180))), + Language.Name.EQ(Char(20)("English")). + AND(Category.Name.NOT_EQ(Text("Action"))). + AND(Film.Length.GT(Int32(180))), ).ORDER_BY( Actor.ActorID.ASC(), Film.FilmID.ASC(), @@ -200,35 +200,35 @@ args - query parameters ```sql SELECT actor.actor_id AS "actor.actor_id", - actor.first_name AS "actor.first_name", - actor.last_name AS "actor.last_name", - actor.last_update AS "actor.last_update", - film.film_id AS "film.film_id", - film.title AS "film.title", - film.description AS "film.description", - film.release_year AS "film.release_year", - film.language_id AS "film.language_id", - film.rental_duration AS "film.rental_duration", - film.rental_rate AS "film.rental_rate", - film.length AS "film.length", - film.replacement_cost AS "film.replacement_cost", - film.rating AS "film.rating", - film.last_update AS "film.last_update", - film.special_features AS "film.special_features", - film.fulltext AS "film.fulltext", - language.language_id AS "language.language_id", - language.name AS "language.name", - language.last_update AS "language.last_update", - category.category_id AS "category.category_id", - category.name AS "category.name", - category.last_update AS "category.last_update" + actor.first_name AS "actor.first_name", + actor.last_name AS "actor.last_name", + actor.last_update AS "actor.last_update", + film.film_id AS "film.film_id", + film.title AS "film.title", + film.description AS "film.description", + film.release_year AS "film.release_year", + film.language_id AS "film.language_id", + film.rental_duration AS "film.rental_duration", + film.rental_rate AS "film.rental_rate", + film.length AS "film.length", + film.replacement_cost AS "film.replacement_cost", + film.rating AS "film.rating", + film.last_update AS "film.last_update", + film.special_features AS "film.special_features", + film.fulltext AS "film.fulltext", + language.language_id AS "language.language_id", + language.name AS "language.name", + language.last_update AS "language.last_update", + category.category_id AS "category.category_id", + category.name AS "category.name", + category.last_update AS "category.last_update" FROM dvds.actor - INNER JOIN dvds.film_actor ON (actor.actor_id = film_actor.actor_id) - INNER JOIN dvds.film ON (film.film_id = film_actor.film_id) - INNER JOIN dvds.language ON (language.language_id = film.language_id) - INNER JOIN dvds.film_category ON (film_category.film_id = film.film_id) - INNER JOIN dvds.category ON (category.category_id = film_category.category_id) -WHERE ((language.name = $1) AND (category.name != $2)) AND (film.length > $3) + INNER JOIN dvds.film_actor ON (actor.actor_id = film_actor.actor_id) + INNER JOIN dvds.film ON (film.film_id = film_actor.film_id) + INNER JOIN dvds.language ON (language.language_id = film.language_id) + INNER JOIN dvds.film_category ON (film_category.film_id = film.film_id) + INNER JOIN dvds.category ON (category.category_id = film_category.category_id) +WHERE ((language.name = $1::char(20)) AND (category.name != $2::text)) AND (film.length > $3::integer) ORDER BY actor.actor_id ASC, film.film_id ASC; ``` ```sh @@ -277,7 +277,7 @@ FROM dvds.actor INNER JOIN dvds.language ON (language.language_id = film.language_id) INNER JOIN dvds.film_category ON (film_category.film_id = film.film_id) INNER JOIN dvds.category ON (category.category_id = film_category.category_id) -WHERE ((language.name = 'English') AND (category.name != 'Action')) AND (film.length > 180) +WHERE ((language.name = 'English'::char(20)) AND (category.name != 'Action'::text)) AND (film.length > 180::integer) ORDER BY actor.actor_id ASC, film.film_id ASC; ``` @@ -545,18 +545,18 @@ The most expensive bugs are the one discovered on the production, and the least With automatically generated type safe SQL, not only queries are written faster but bugs are found sooner. Let's return to quick start example, and take closer look at a line: ```go -AND(Film.Length.GT(Int(180))), +AND(Film.Length.GT(Int32(180))), ``` Let's say someone changes column `length` to `duration` from `film` table. The next go build will fail at that line, and the bug will be caught at compile time. -Let's say someone changes the type of `length` column to some non integer type. Build will also fail at the same line +Let's say someone changes the type of `length` column to some non-integer type. Build will also fail at the same line because integer columns and expressions can be only compared to other integer columns and expressions. Build will also fail if someone removes `length` column from `film` table. `Film` field will be omitted from SQL Builder and Model types, next time `jet` generator is run. -Without Jet these bugs will have to be either caught by some test or by manual testing. +Without Jet these bugs will have to be either caught by tests or by manual testing. ## Dependencies At the moment Jet dependence only of: diff --git a/examples/quick-start/quick-start.go b/examples/quick-start/quick-start.go index dc849898..f4201693 100644 --- a/examples/quick-start/quick-start.go +++ b/examples/quick-start/quick-start.go @@ -46,8 +46,8 @@ func main() { INNER_JOIN(FilmCategory, FilmCategory.FilmID.EQ(Film.FilmID)). INNER_JOIN(Category, Category.CategoryID.EQ(FilmCategory.CategoryID)), ).WHERE( - Language.Name.EQ(String("English")). - AND(Category.Name.NOT_EQ(String("Action"))). + Language.Name.EQ(Char(20)("English")). + AND(Category.Name.NOT_EQ(Text("Action"))). AND(Film.Length.GT(Int(180))), ).ORDER_BY( Actor.ActorID.ASC(), diff --git a/go.mod b/go.mod index cf29d08c..a52dcf78 100644 --- a/go.mod +++ b/go.mod @@ -1,19 +1,21 @@ module github.com/go-jet/jet/v2 -go 1.20 +go 1.21 +// used by jet generator require ( github.com/go-sql-driver/mysql v1.8.1 - github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 github.com/jackc/pgconn v1.14.3 - github.com/jackc/pgtype v1.14.3 + github.com/jackc/pgtype v1.14.4 github.com/jackc/pgx/v4 v4.18.3 github.com/lib/pq v1.10.9 github.com/mattn/go-sqlite3 v1.14.24 ) +// used in tests require ( + github.com/google/go-cmp v0.6.0 github.com/pkg/profile v1.7.0 github.com/shopspring/decimal v1.4.0 github.com/stretchr/testify v1.9.0 diff --git a/go.sum b/go.sum index c04d912f..72aa88a0 100644 --- a/go.sum +++ b/go.sum @@ -71,8 +71,8 @@ github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCM github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= github.com/jackc/pgtype v1.14.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= -github.com/jackc/pgtype v1.14.3 h1:h6W9cPuHsRWQFTWUZMAKMgG5jSwQI0Zurzdvlx3Plus= -github.com/jackc/pgtype v1.14.3/go.mod h1:aKeozOde08iifGosdJpz9MBZonJOUJxqNpPBcMJTlVA= +github.com/jackc/pgtype v1.14.4 h1:fKuNiCumbKTAIxQwXfB/nsrnkEI6bPJrrSiMKgbJ2j8= +github.com/jackc/pgtype v1.14.4/go.mod h1:aKeozOde08iifGosdJpz9MBZonJOUJxqNpPBcMJTlVA= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= diff --git a/postgres/literal.go b/postgres/literal.go index 26b75d88..e23ee9c1 100644 --- a/postgres/literal.go +++ b/postgres/literal.go @@ -34,47 +34,64 @@ func Int64(value int64) IntegerExpression { return CAST(jet.Int(value)).AS_BIGINT() } -// Uint8 is constructor for 8 bit unsigned integer expressions literals. -func Uint8(value uint8) IntegerExpression { - return CAST(jet.Uint8(value)).AS_SMALLINT() -} - -// Uint16 is constructor for 16 bit unsigned integer expressions literals. -func Uint16(value uint16) IntegerExpression { - return CAST(jet.Uint16(value)).AS_INTEGER() -} - -// Uint32 is constructor for 32 bit unsigned integer expressions literals. -func Uint32(value uint32) IntegerExpression { - return CAST(jet.Uint32(value)).AS_BIGINT() -} - -// Uint64 is constructor for 64 bit unsigned integer expressions literals. -func Uint64(value uint64) IntegerExpression { - return CAST(jet.Uint64(value)).AS_BIGINT() -} - // Float creates new float literal expression var Float = jet.Float -// Float32 is constructor for 32 bit float literals -func Float32(value float32) FloatExpression { +// Real is placeholder constructor for 32-bit float literals +func Real(value float32) FloatExpression { return CAST(jet.Literal(value)).AS_REAL() } -// Float64 is constructor for 64 bit float literals -func Float64(value float64) FloatExpression { +// Double is placeholder constructor for 64-bit float literals +func Double(value float64) FloatExpression { return CAST(jet.Literal(value)).AS_DOUBLE() } // Decimal creates new float literal expression var Decimal = jet.Decimal -// String creates new string literal expression +// String is a parameter constructor for the PostgreSQL text type. Using the `Text` constructor is +// generally preferable. +// +// WARNING: String always applies a `text` type cast, which can be problematic if a parameter is compared +// to a `character` column, as this may prevent index usage. In such cases, consider using the Char +// constructor instead. See also other PostgreSQL-specific constructors: Text, Char, and VarChar. func String(value string) StringExpression { return CAST(jet.String(value)).AS_TEXT() } +// Text is a parameter constructor for the PostgreSQL text type. This constructor also adds an +// explicit placeholder type cast to text in the generated query, such as `$3::text`. +// Example usage: +// +// Text("English") +func Text(value string) StringExpression { + return CAST(jet.Literal(value)).AS_TEXT() +} + +// Char is a parameter constructor for the PostgreSQL character type. This constructor also adds an +// explicit placeholder type cast to text in the generated query, such as `$3::char(30)`. +// Example usage: +// +// Char(20)("English") +func Char(length ...int) func(value string) StringExpression { + return func(value string) StringExpression { + return CAST(StringExp(jet.Literal(value))).AS_CHAR(length...) + } +} + +// VarChar is a parameter constructor for the PostgreSQL character varying type. This constructor +// also adds an explicit placeholder type cast to text in the generated query, such as `$3::varchar(30)`. +// Example usage: +// +// VarChar(20)("English") +// VarChar()("English") +func VarChar(length ...int) func(value string) StringExpression { + return func(value string) StringExpression { + return CAST(StringExp(jet.Literal(value))).AS_VARCHAR(length...) + } +} + // Json creates new json literal expression func Json(value interface{}) StringExpression { switch value.(type) { diff --git a/postgres/literal_test.go b/postgres/literal_test.go index 9fef0556..a50ea8fd 100644 --- a/postgres/literal_test.go +++ b/postgres/literal_test.go @@ -34,32 +34,21 @@ func TestInt64(t *testing.T) { assertSerialize(t, Int64(val), `$1::bigint`, val) } -func TestUint8(t *testing.T) { - val := uint8(math.MaxUint8) - assertSerialize(t, Uint8(val), `$1::smallint`, val) -} - -func TestUint16(t *testing.T) { - val := uint16(math.MaxUint16) - assertSerialize(t, Uint16(val), `$1::integer`, val) -} - -func TestUint32(t *testing.T) { - val := uint32(math.MaxUint32) - assertSerialize(t, Uint32(val), `$1::bigint`, val) -} - -func TestUint64(t *testing.T) { - val := uint64(math.MaxUint64) - assertSerialize(t, Uint64(val), `$1::bigint`, val) -} - func TestFloat(t *testing.T) { assertSerialize(t, Float(12.34), `$1`, float64(12.34)) + + assertSerialize(t, Real(12.34), `$1::real`, float32(12.34)) + assertSerialize(t, Double(12.34), `$1::double precision`, float64(12.34)) } func TestString(t *testing.T) { assertSerialize(t, String("Some text"), `$1::text`, "Some text") + + assertSerialize(t, Text("Some text"), `$1::text`, "Some text") + assertSerialize(t, Char(20)("John Doe"), `$1::char(20)`, "John Doe") + assertSerialize(t, Char()("John Doe"), `$1::char`, "John Doe") + assertSerialize(t, VarChar(20)("John Doe"), `$1::varchar(20)`, "John Doe") + assertSerialize(t, VarChar()("John Doe"), `$1::varchar`, "John Doe") } func TestBytea(t *testing.T) { diff --git a/postgres/values.go b/postgres/values.go index 28d17cd1..8d38ed39 100644 --- a/postgres/values.go +++ b/postgres/values.go @@ -12,8 +12,8 @@ type values struct { // Example usage: // // VALUES( -// WRAP(Int32(204), Float32(1.21)), -// WRAP(Int32(207), Float32(1.02)), +// WRAP(Int32(204), Real(1.21)), +// WRAP(Int32(207), Real(1.02)), // ) func VALUES(rows ...RowExpression) values { return values{Values: jet.Values(rows)} diff --git a/tests/postgres/alltypes_test.go b/tests/postgres/alltypes_test.go index d6cdfcef..6c3755a2 100644 --- a/tests/postgres/alltypes_test.go +++ b/tests/postgres/alltypes_test.go @@ -462,15 +462,15 @@ func TestStringOperators(t *testing.T) { query := AllTypes.SELECT( AllTypes.Text.EQ(AllTypes.Char), - AllTypes.Text.EQ(String("Text")), + AllTypes.Text.EQ(Text("Text")), AllTypes.Text.NOT_EQ(AllTypes.VarCharPtr), - AllTypes.Text.NOT_EQ(String("Text")), + AllTypes.Text.NOT_EQ(Text("Text")), AllTypes.Text.GT(AllTypes.Text), - AllTypes.Text.GT(String("Text")), + AllTypes.Text.GT(Text("Text")), AllTypes.Text.GT_EQ(AllTypes.TextPtr), - AllTypes.Text.GT_EQ(String("Text")), + AllTypes.Text.GT_EQ(Text("Text")), AllTypes.Text.LT(AllTypes.Char), - AllTypes.Text.LT(String("Text")), + AllTypes.Text.LT(Text("Text")), AllTypes.Text.LT_EQ(AllTypes.VarChar), AllTypes.Text.LT_EQ(String("Text")), AllTypes.Text.BETWEEN(String("min"), String("max")), @@ -490,13 +490,13 @@ func TestStringOperators(t *testing.T) { OCTET_LENGTH(AllTypes.Text), OCTET_LENGTH(String("length")), LOWER(AllTypes.VarCharPtr), - LOWER(String("length")), + LOWER(Char(4)("length")), UPPER(AllTypes.Char), - UPPER(String("upper")), + UPPER(VarChar()("upper")), BTRIM(AllTypes.VarChar), - BTRIM(String("btrim")), + BTRIM(Char()("btrim")), BTRIM(AllTypes.VarChar, String("AA")), - BTRIM(String("btrim"), String("AA")), + BTRIM(VarChar(11)("btrim"), String("AA")), LTRIM(AllTypes.VarChar), LTRIM(String("ltrim")), LTRIM(AllTypes.VarChar, String("A")), @@ -533,7 +533,7 @@ func TestStringOperators(t *testing.T) { TO_HEX(AllTypes.IntegerPtr), ) - dest := []struct{}{} + var dest []struct{} err := query.Query(db, &dest) require.NoError(t, err) @@ -630,9 +630,9 @@ func TestFloatOperators(t *testing.T) { AllTypes.Numeric.BETWEEN(Float(1.34), AllTypes.Decimal).AS("between"), AllTypes.Numeric.NOT_BETWEEN(AllTypes.Decimal.MUL(Float(3)), Float(100.12)).AS("not_between"), - TRUNC(AllTypes.Decimal.ADD(AllTypes.Decimal), Uint8(2)).AS("add1"), + TRUNC(AllTypes.Decimal.ADD(AllTypes.Decimal), Int8(2)).AS("add1"), TRUNC(AllTypes.Decimal.ADD(Float(11.22)), Int8(2)).AS("add2"), - TRUNC(AllTypes.Decimal.SUB(AllTypes.DecimalPtr), Uint16(2)).AS("sub1"), + TRUNC(AllTypes.Decimal.SUB(AllTypes.DecimalPtr), Int32(2)).AS("sub1"), TRUNC(AllTypes.Decimal.SUB(Float(11.22)), Int16(2)).AS("sub2"), TRUNC(AllTypes.Decimal.MUL(AllTypes.DecimalPtr), Int16(2)).AS("mul1"), TRUNC(AllTypes.Decimal.MUL(Float(11.22)), Int32(2)).AS("mul2"), @@ -736,13 +736,13 @@ func TestIntegerOperators(t *testing.T) { AllTypes.Integer.BETWEEN(Int(11), Int(200)).AS("between"), AllTypes.Integer.NOT_BETWEEN(Int(66), Int(77)).AS("not_between"), AllTypes.BigInt.LT(AllTypes.BigIntPtr).AS("lt1"), - AllTypes.BigInt.LT(Uint8(65)).AS("lt2"), + AllTypes.BigInt.LT(Int16(65)).AS("lt2"), AllTypes.BigInt.LT_EQ(AllTypes.BigIntPtr).AS("lte1"), - AllTypes.BigInt.LT_EQ(Uint16(65)).AS("lte2"), + AllTypes.BigInt.LT_EQ(Int32(65)).AS("lte2"), AllTypes.BigInt.GT(AllTypes.BigIntPtr).AS("gt1"), - AllTypes.BigInt.GT(Uint32(65)).AS("gt2"), + AllTypes.BigInt.GT(Int64(65)).AS("gt2"), AllTypes.BigInt.GT_EQ(AllTypes.BigIntPtr).AS("gte1"), - AllTypes.BigInt.GT_EQ(Uint64(65)).AS("gte2"), + AllTypes.BigInt.GT_EQ(Int64(65)).AS("gte2"), AllTypes.BigInt.ADD(AllTypes.BigInt).AS("add1"), AllTypes.BigInt.ADD(Int(11)).AS("add2"), @@ -1111,8 +1111,8 @@ func TestRowExpression(t *testing.T) { nowAddHour := time.Now().Add(time.Hour) stmt := SELECT( - ROW(Int32(1), Float32(11.22), String("john")).AS("row"), - WRAP(Int64(1), Float64(11.22), String("john")).AS("wrap"), + ROW(Int32(1), Real(11.22), Text("john")).AS("row"), + WRAP(Int64(1), Double(11.22), VarChar(10)("john")).AS("wrap"), ROW(Bool(false), DateT(now)).EQ(ROW(Bool(true), DateT(now))), WRAP(Bool(false), DateT(now)).NOT_EQ(WRAP(Bool(true), DateT(now))), @@ -1131,7 +1131,7 @@ func TestRowExpression(t *testing.T) { testutils.AssertStatementSql(t, stmt, ` SELECT ROW($1::integer, $2::real, $3::text) AS "row", - ($4::bigint, $5::double precision, $6::text) AS "wrap", + ($4::bigint, $5::double precision, $6::varchar(10)) AS "wrap", ROW($7::boolean, $8::date) = ROW($9::boolean, $10::date), ($11::boolean, $12::date) != ($13::boolean, $14::date), ROW($15::time without time zone) IS DISTINCT FROM (row(NOW()::time)), diff --git a/tests/postgres/select_test.go b/tests/postgres/select_test.go index 8bc816e0..6ecc1984 100644 --- a/tests/postgres/select_test.go +++ b/tests/postgres/select_test.go @@ -660,8 +660,8 @@ func TestSelectExecution1(t *testing.T) { ). WHERE( OR( - City.City.EQ(String("London")), - City.City.EQ(String("York")), + City.City.EQ(Text("London")), + City.City.EQ(Text("York")), ), ). ORDER_BY( @@ -741,7 +741,7 @@ func TestSelectExecution2(t *testing.T) { Customer.CustomerID.AS("my_customer.id"), Customer.LastName.AS("my_customer.last_name"), ). - WHERE(City.City.EQ(String("London")).OR(City.City.EQ(String("York")))). + WHERE(City.City.EQ(VarChar()("London")).OR(City.City.EQ(VarChar()("York")))). ORDER_BY(City.CityID, Address.AddressID, Customer.CustomerID) testutils.AssertDebugStatementSql(t, stmt, ` @@ -754,7 +754,7 @@ SELECT city.city_id AS "my_city.id", FROM dvds.city INNER JOIN dvds.address ON (address.city_id = city.city_id) INNER JOIN dvds.customer ON (customer.address_id = address.address_id) -WHERE (city.city = 'London'::text) OR (city.city = 'York'::text) +WHERE (city.city = 'London'::varchar) OR (city.city = 'York'::varchar) ORDER BY city.city_id, address.address_id, customer.customer_id; `, "London", "York") @@ -798,7 +798,7 @@ func TestSelectExecution3(t *testing.T) { Address.AddressID.AS("address_id"), Address.Address.AS("address_line"), ). - WHERE(City.City.EQ(String("London")).OR(City.City.EQ(String("York")))). + WHERE(City.City.EQ(VarChar(20)("London")).OR(City.City.EQ(VarChar(20)("York")))). ORDER_BY(City.CityID, Address.AddressID, Customer.CustomerID) testutils.AssertDebugStatementSql(t, stmt, ` @@ -811,7 +811,7 @@ SELECT city.city_id AS "city_id", FROM dvds.city INNER JOIN dvds.address ON (address.city_id = city.city_id) INNER JOIN dvds.customer ON (customer.address_id = address.address_id) -WHERE (city.city = 'London'::text) OR (city.city = 'York'::text) +WHERE (city.city = 'London'::varchar(20)) OR (city.city = 'York'::varchar(20)) ORDER BY city.city_id, address.address_id, customer.customer_id; `, "London", "York") @@ -1866,7 +1866,7 @@ SELECT customer.customer_id AS "customer.customer_id", FROM dvds.payment INNER JOIN dvds.customer ON (customer.customer_id = payment.customer_id) GROUP BY customer.customer_id -HAVING SUM(payment.amount) > 125.6 +HAVING SUM(payment.amount) > 125::real ORDER BY customer.customer_id, SUM(payment.amount) ASC; ` query := SELECT( @@ -1885,14 +1885,14 @@ ORDER BY customer.customer_id, SUM(payment.amount) ASC; ).GROUP_BY( Customer.CustomerID, ).HAVING( - SUMf(Payment.Amount).GT(Float(125.6)), + SUMf(Payment.Amount).GT(Real(125)), ).ORDER_BY( Customer.CustomerID, SUMf(Payment.Amount).ASC(), ) //fmt.Println(query.DebugSql()) - testutils.AssertDebugStatementSql(t, query, expectedSQL, float64(125.6)) + testutils.AssertDebugStatementSql(t, query, expectedSQL, float32(125)) var dest []struct { model.Customer @@ -2378,14 +2378,14 @@ func TestSelectUnion(t *testing.T) { SELECT payment.payment_id AS "payment.payment_id", payment.amount AS "payment.amount" FROM dvds.payment - WHERE payment.amount <= 100 + WHERE payment.amount <= 100::double precision ) UNION ALL ( SELECT payment.payment_id AS "payment.payment_id", payment.amount AS "payment.amount" FROM dvds.payment - WHERE payment.amount >= 200 + WHERE payment.amount >= 200::double precision ) ORDER BY "payment.payment_id" ASC, "payment.amount" DESC LIMIT 10 @@ -2394,10 +2394,10 @@ OFFSET 20; query := UNION_ALL( Payment. SELECT(Payment.PaymentID.AS("payment.payment_id"), Payment.Amount). - WHERE(Payment.Amount.LT_EQ(Float(100))), + WHERE(Payment.Amount.LT_EQ(Double(100))), Payment. SELECT(Payment.PaymentID, Payment.Amount). - WHERE(Payment.Amount.GT_EQ(Float(200))), + WHERE(Payment.Amount.GT_EQ(Double(200))), ).ORDER_BY( IntegerColumn("payment.payment_id").ASC(), Payment.Amount.DESC(), @@ -2729,7 +2729,7 @@ FROM dvds.actor INNER JOIN dvds.language ON (language.language_id = film.language_id) INNER JOIN dvds.film_category ON (film_category.film_id = film.film_id) INNER JOIN dvds.category ON (category.category_id = film_category.category_id) -WHERE ((language.name = 'English'::text) AND (category.name != 'Action'::text)) AND (film.length > 180) +WHERE ((language.name = 'English'::char(20)) AND (category.name != 'Action'::text)) AND (film.length > 180::integer) ORDER BY actor.actor_id ASC, film.film_id ASC; ` @@ -2746,15 +2746,15 @@ ORDER BY actor.actor_id ASC, film.film_id ASC; INNER_JOIN(FilmCategory, FilmCategory.FilmID.EQ(Film.FilmID)). INNER_JOIN(Category, Category.CategoryID.EQ(FilmCategory.CategoryID)), ).WHERE( - Language.Name.EQ(String("English")). // note that every column has type. - AND(Category.Name.NOT_EQ(String("Action"))). // String column Language.Name and Category.Name can be compared only with string expression - AND(Film.Length.GT(Int(180))), // Film.Length is integer column and can be compared only with integer expression + Language.Name.EQ(Char(20)("English")). // note that every column has type. + AND(Category.Name.NOT_EQ(Text("Action"))). // String column Language.Name and Category.Name can be compared only with string expression + AND(Film.Length.GT(Int32(180))), // Film.Length is integer column and can be compared only with integer expression ).ORDER_BY( Actor.ActorID.ASC(), Film.FilmID.ASC(), ) - testutils.AssertDebugStatementSql(t, stmt, expectedSQL, "English", "Action", int64(180)) + testutils.AssertDebugStatementSql(t, stmt, expectedSQL, "English", "Action", int32(180)) var dest []struct { model.Actor @@ -3162,7 +3162,7 @@ func TestSelectLateral(t *testing.T) { ).FROM( Language, ).WHERE( - Language.Name.NOT_IN(String("spanish")). + Language.Name.NOT_IN(Char(20)("Spanish"), Char(20)("Catalan")). AND(Film.LanguageID.EQ(Language.LanguageID)), ), ).AS("films") @@ -3191,7 +3191,7 @@ FROM dvds.film language.name AS "language.name", language.last_update AS "language.last_update" FROM dvds.language - WHERE (language.name NOT IN ('spanish'::text)) AND (film.language_id = language.language_id) + WHERE (language.name NOT IN ('Spanish'::char(20), 'Catalan'::char(20))) AND (film.language_id = language.language_id) ) AS films WHERE film.film_id = 1 ORDER BY film.film_id @@ -3236,7 +3236,7 @@ FROM dvds.film, language.name AS "language.name", language.last_update AS "language.last_update" FROM dvds.language - WHERE (language.name NOT IN ('spanish'::text)) AND (film.language_id = language.language_id) + WHERE (language.name NOT IN ('Spanish'::char(20), 'Catalan'::char(20))) AND (film.language_id = language.language_id) ) AS films WHERE film.film_id = 1 ORDER BY film.film_id @@ -3787,9 +3787,9 @@ func TestSelectConditionalFunctions(t *testing.T) { Film.SELECT(Film.FilmID).WHERE(Film.RentalDuration.GT(Int(100))), ).AS("exists"), CASE(Film.Length.GT(Int(120))). - WHEN(Bool(true)).THEN(String("long film")). - ELSE(String("short film")).AS("case"), - COALESCE(Film.Description, String("none")).AS("coalesce"), + WHEN(Bool(true)).THEN(Text("long film")). + ELSE(Text("short film")).AS("case"), + COALESCE(Film.Description, Text("none")).AS("coalesce"), NULLIF(Film.ReleaseYear, Int(200)).AS("null_if"), GREATEST(Film.RentalDuration, Int(4), Int(5)).AS("greatest"), LEAST(Film.RentalDuration, Int(7), Int(6)).AS("least"), diff --git a/tests/postgres/values_test.go b/tests/postgres/values_test.go index ce26276b..bdb631c8 100644 --- a/tests/postgres/values_test.go +++ b/tests/postgres/values_test.go @@ -15,9 +15,9 @@ import ( func TestVALUES(t *testing.T) { values := VALUES( - WRAP(Int32(1), Int32(2), Float32(4.666), Bool(false), String("txt")), - WRAP(Int32(11).ADD(Int32(2)), Int32(22), Float32(33.222), Bool(true), String("png")), - WRAP(Int32(11), Int32(22), Float32(33.222), Bool(true), NULL), + WRAP(Int32(1), Int32(2), Real(4.666), Bool(false), String("txt")), + WRAP(Int32(11).ADD(Int32(2)), Int32(22), Real(33.222), Bool(true), String("png")), + WRAP(Int32(11), Int32(22), Real(33.222), Bool(true), NULL), ).AS("values_table") stmt := SELECT( @@ -86,11 +86,11 @@ func TestVALUES_Join(t *testing.T) { lastUpdate := Timestamp(2007, time.February, 11, 12, 0, 0) filmValues := VALUES( - WRAP(String("Chamber Italian"), Int64(117), Int32(2005), Float32(5.82), lastUpdate), - WRAP(String("Grosse Wonderful"), Int64(49), Int32(2004), Float32(6.242), lastUpdate.ADD(INTERVAL(1, HOUR))), - WRAP(String("Airport Pollock"), Int64(54), Int32(2001), Float32(7.22), NULL), - WRAP(String("Bright Encounters"), Int64(73), Int32(2002), Float32(8.25), NULL), - WRAP(String("Academy Dinosaur"), Int64(83), Int32(2010), Float32(9.22), lastUpdate.SUB(INTERVAL(2, MINUTE))), + WRAP(String("Chamber Italian"), Int64(117), Int32(2005), Real(5.82), lastUpdate), + WRAP(String("Grosse Wonderful"), Int64(49), Int32(2004), Real(6.242), lastUpdate.ADD(INTERVAL(1, HOUR))), + WRAP(String("Airport Pollock"), Int64(54), Int32(2001), Real(7.22), NULL), + WRAP(String("Bright Encounters"), Int64(73), Int32(2002), Real(8.25), NULL), + WRAP(String("Academy Dinosaur"), Int64(83), Int32(2010), Real(9.22), lastUpdate.SUB(INTERVAL(2, MINUTE))), ).AS("film_values", title, IntegerColumn("length"), releaseYear, rentalRate, TimestampColumn("update_date")) @@ -216,10 +216,10 @@ func TestVALUES_CTE_Update(t *testing.T) { stmt := WITH( paymentsToUpdate.AS( VALUES( - WRAP(Int32(20564), Float32(1.21)), - WRAP(Int32(20567), Float32(1.02)), - WRAP(Int32(20570), Float32(1.34)), - WRAP(Int32(20573), Float32(1.72)), + WRAP(Int32(20564), Real(1.21)), + WRAP(Int32(20567), Real(1.02)), + WRAP(Int32(20570), Real(1.34)), + WRAP(Int32(20573), Real(1.72)), ), ), )(