Add PostgreSQL-specific character type constructors: Text, Char, and VarChar.

This commit is contained in:
go-jet 2024-11-01 12:34:46 +01:00
parent 4f0832b0e7
commit 2183af42f4
10 changed files with 152 additions and 144 deletions

View file

@ -175,9 +175,9 @@ stmt := SELECT(
INNER_JOIN(FilmCategory, FilmCategory.FilmID.EQ(Film.FilmID)). INNER_JOIN(FilmCategory, FilmCategory.FilmID.EQ(Film.FilmID)).
INNER_JOIN(Category, Category.CategoryID.EQ(FilmCategory.CategoryID)), INNER_JOIN(Category, Category.CategoryID.EQ(FilmCategory.CategoryID)),
).WHERE( ).WHERE(
Language.Name.EQ(String("English")). Language.Name.EQ(Char(20)("English")).
AND(Category.Name.NOT_EQ(String("Action"))). AND(Category.Name.NOT_EQ(Text("Action"))).
AND(Film.Length.GT(Int(180))), AND(Film.Length.GT(Int32(180))),
).ORDER_BY( ).ORDER_BY(
Actor.ActorID.ASC(), Actor.ActorID.ASC(),
Film.FilmID.ASC(), Film.FilmID.ASC(),
@ -228,7 +228,7 @@ FROM dvds.actor
INNER JOIN dvds.language ON (language.language_id = film.language_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.film_category ON (film_category.film_id = film.film_id)
INNER JOIN dvds.category ON (category.category_id = film_category.category_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) 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; ORDER BY actor.actor_id ASC, film.film_id ASC;
``` ```
```sh ```sh
@ -277,7 +277,7 @@ FROM dvds.actor
INNER JOIN dvds.language ON (language.language_id = film.language_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.film_category ON (film_category.film_id = film.film_id)
INNER JOIN dvds.category ON (category.category_id = film_category.category_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; ORDER BY actor.actor_id ASC, film.film_id ASC;
``` ```
</details> </details>
@ -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. 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: Let's return to quick start example, and take closer look at a line:
```go ```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 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. 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. 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, 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. 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 ## Dependencies
At the moment Jet dependence only of: At the moment Jet dependence only of:

View file

@ -46,8 +46,8 @@ func main() {
INNER_JOIN(FilmCategory, FilmCategory.FilmID.EQ(Film.FilmID)). INNER_JOIN(FilmCategory, FilmCategory.FilmID.EQ(Film.FilmID)).
INNER_JOIN(Category, Category.CategoryID.EQ(FilmCategory.CategoryID)), INNER_JOIN(Category, Category.CategoryID.EQ(FilmCategory.CategoryID)),
).WHERE( ).WHERE(
Language.Name.EQ(String("English")). Language.Name.EQ(Char(20)("English")).
AND(Category.Name.NOT_EQ(String("Action"))). AND(Category.Name.NOT_EQ(Text("Action"))).
AND(Film.Length.GT(Int(180))), AND(Film.Length.GT(Int(180))),
).ORDER_BY( ).ORDER_BY(
Actor.ActorID.ASC(), Actor.ActorID.ASC(),

8
go.mod
View file

@ -1,19 +1,21 @@
module github.com/go-jet/jet/v2 module github.com/go-jet/jet/v2
go 1.20 go 1.21
// used by jet generator
require ( require (
github.com/go-sql-driver/mysql v1.8.1 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/google/uuid v1.6.0
github.com/jackc/pgconn v1.14.3 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/jackc/pgx/v4 v4.18.3
github.com/lib/pq v1.10.9 github.com/lib/pq v1.10.9
github.com/mattn/go-sqlite3 v1.14.24 github.com/mattn/go-sqlite3 v1.14.24
) )
// used in tests
require ( require (
github.com/google/go-cmp v0.6.0
github.com/pkg/profile v1.7.0 github.com/pkg/profile v1.7.0
github.com/shopspring/decimal v1.4.0 github.com/shopspring/decimal v1.4.0
github.com/stretchr/testify v1.9.0 github.com/stretchr/testify v1.9.0

4
go.sum
View file

@ -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 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.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.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
github.com/jackc/pgtype v1.14.3 h1:h6W9cPuHsRWQFTWUZMAKMgG5jSwQI0Zurzdvlx3Plus= github.com/jackc/pgtype v1.14.4 h1:fKuNiCumbKTAIxQwXfB/nsrnkEI6bPJrrSiMKgbJ2j8=
github.com/jackc/pgtype v1.14.3/go.mod h1:aKeozOde08iifGosdJpz9MBZonJOUJxqNpPBcMJTlVA= 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-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-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= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=

View file

@ -34,47 +34,64 @@ func Int64(value int64) IntegerExpression {
return CAST(jet.Int(value)).AS_BIGINT() 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 // Float creates new float literal expression
var Float = jet.Float var Float = jet.Float
// Float32 is constructor for 32 bit float literals // Real is placeholder constructor for 32-bit float literals
func Float32(value float32) FloatExpression { func Real(value float32) FloatExpression {
return CAST(jet.Literal(value)).AS_REAL() return CAST(jet.Literal(value)).AS_REAL()
} }
// Float64 is constructor for 64 bit float literals // Double is placeholder constructor for 64-bit float literals
func Float64(value float64) FloatExpression { func Double(value float64) FloatExpression {
return CAST(jet.Literal(value)).AS_DOUBLE() return CAST(jet.Literal(value)).AS_DOUBLE()
} }
// Decimal creates new float literal expression // Decimal creates new float literal expression
var Decimal = jet.Decimal 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 { func String(value string) StringExpression {
return CAST(jet.String(value)).AS_TEXT() 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 // Json creates new json literal expression
func Json(value interface{}) StringExpression { func Json(value interface{}) StringExpression {
switch value.(type) { switch value.(type) {

View file

@ -34,32 +34,21 @@ func TestInt64(t *testing.T) {
assertSerialize(t, Int64(val), `$1::bigint`, val) 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) { func TestFloat(t *testing.T) {
assertSerialize(t, Float(12.34), `$1`, float64(12.34)) 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) { func TestString(t *testing.T) {
assertSerialize(t, String("Some text"), `$1::text`, "Some text") 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) { func TestBytea(t *testing.T) {

View file

@ -12,8 +12,8 @@ type values struct {
// Example usage: // Example usage:
// //
// VALUES( // VALUES(
// WRAP(Int32(204), Float32(1.21)), // WRAP(Int32(204), Real(1.21)),
// WRAP(Int32(207), Float32(1.02)), // WRAP(Int32(207), Real(1.02)),
// ) // )
func VALUES(rows ...RowExpression) values { func VALUES(rows ...RowExpression) values {
return values{Values: jet.Values(rows)} return values{Values: jet.Values(rows)}

View file

@ -462,15 +462,15 @@ func TestStringOperators(t *testing.T) {
query := AllTypes.SELECT( query := AllTypes.SELECT(
AllTypes.Text.EQ(AllTypes.Char), 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(AllTypes.VarCharPtr),
AllTypes.Text.NOT_EQ(String("Text")), AllTypes.Text.NOT_EQ(Text("Text")),
AllTypes.Text.GT(AllTypes.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(AllTypes.TextPtr),
AllTypes.Text.GT_EQ(String("Text")), AllTypes.Text.GT_EQ(Text("Text")),
AllTypes.Text.LT(AllTypes.Char), 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(AllTypes.VarChar),
AllTypes.Text.LT_EQ(String("Text")), AllTypes.Text.LT_EQ(String("Text")),
AllTypes.Text.BETWEEN(String("min"), String("max")), AllTypes.Text.BETWEEN(String("min"), String("max")),
@ -490,13 +490,13 @@ func TestStringOperators(t *testing.T) {
OCTET_LENGTH(AllTypes.Text), OCTET_LENGTH(AllTypes.Text),
OCTET_LENGTH(String("length")), OCTET_LENGTH(String("length")),
LOWER(AllTypes.VarCharPtr), LOWER(AllTypes.VarCharPtr),
LOWER(String("length")), LOWER(Char(4)("length")),
UPPER(AllTypes.Char), UPPER(AllTypes.Char),
UPPER(String("upper")), UPPER(VarChar()("upper")),
BTRIM(AllTypes.VarChar), BTRIM(AllTypes.VarChar),
BTRIM(String("btrim")), BTRIM(Char()("btrim")),
BTRIM(AllTypes.VarChar, String("AA")), BTRIM(AllTypes.VarChar, String("AA")),
BTRIM(String("btrim"), String("AA")), BTRIM(VarChar(11)("btrim"), String("AA")),
LTRIM(AllTypes.VarChar), LTRIM(AllTypes.VarChar),
LTRIM(String("ltrim")), LTRIM(String("ltrim")),
LTRIM(AllTypes.VarChar, String("A")), LTRIM(AllTypes.VarChar, String("A")),
@ -533,7 +533,7 @@ func TestStringOperators(t *testing.T) {
TO_HEX(AllTypes.IntegerPtr), TO_HEX(AllTypes.IntegerPtr),
) )
dest := []struct{}{} var dest []struct{}
err := query.Query(db, &dest) err := query.Query(db, &dest)
require.NoError(t, err) 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.BETWEEN(Float(1.34), AllTypes.Decimal).AS("between"),
AllTypes.Numeric.NOT_BETWEEN(AllTypes.Decimal.MUL(Float(3)), Float(100.12)).AS("not_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.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.SUB(Float(11.22)), Int16(2)).AS("sub2"),
TRUNC(AllTypes.Decimal.MUL(AllTypes.DecimalPtr), Int16(2)).AS("mul1"), TRUNC(AllTypes.Decimal.MUL(AllTypes.DecimalPtr), Int16(2)).AS("mul1"),
TRUNC(AllTypes.Decimal.MUL(Float(11.22)), Int32(2)).AS("mul2"), 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.BETWEEN(Int(11), Int(200)).AS("between"),
AllTypes.Integer.NOT_BETWEEN(Int(66), Int(77)).AS("not_between"), AllTypes.Integer.NOT_BETWEEN(Int(66), Int(77)).AS("not_between"),
AllTypes.BigInt.LT(AllTypes.BigIntPtr).AS("lt1"), 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(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(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(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(AllTypes.BigInt).AS("add1"),
AllTypes.BigInt.ADD(Int(11)).AS("add2"), AllTypes.BigInt.ADD(Int(11)).AS("add2"),
@ -1111,8 +1111,8 @@ func TestRowExpression(t *testing.T) {
nowAddHour := time.Now().Add(time.Hour) nowAddHour := time.Now().Add(time.Hour)
stmt := SELECT( stmt := SELECT(
ROW(Int32(1), Float32(11.22), String("john")).AS("row"), ROW(Int32(1), Real(11.22), Text("john")).AS("row"),
WRAP(Int64(1), Float64(11.22), String("john")).AS("wrap"), WRAP(Int64(1), Double(11.22), VarChar(10)("john")).AS("wrap"),
ROW(Bool(false), DateT(now)).EQ(ROW(Bool(true), DateT(now))), ROW(Bool(false), DateT(now)).EQ(ROW(Bool(true), DateT(now))),
WRAP(Bool(false), DateT(now)).NOT_EQ(WRAP(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, ` testutils.AssertStatementSql(t, stmt, `
SELECT ROW($1::integer, $2::real, $3::text) AS "row", 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), ROW($7::boolean, $8::date) = ROW($9::boolean, $10::date),
($11::boolean, $12::date) != ($13::boolean, $14::date), ($11::boolean, $12::date) != ($13::boolean, $14::date),
ROW($15::time without time zone) IS DISTINCT FROM (row(NOW()::time)), ROW($15::time without time zone) IS DISTINCT FROM (row(NOW()::time)),

View file

@ -660,8 +660,8 @@ func TestSelectExecution1(t *testing.T) {
). ).
WHERE( WHERE(
OR( OR(
City.City.EQ(String("London")), City.City.EQ(Text("London")),
City.City.EQ(String("York")), City.City.EQ(Text("York")),
), ),
). ).
ORDER_BY( ORDER_BY(
@ -741,7 +741,7 @@ func TestSelectExecution2(t *testing.T) {
Customer.CustomerID.AS("my_customer.id"), Customer.CustomerID.AS("my_customer.id"),
Customer.LastName.AS("my_customer.last_name"), 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) ORDER_BY(City.CityID, Address.AddressID, Customer.CustomerID)
testutils.AssertDebugStatementSql(t, stmt, ` testutils.AssertDebugStatementSql(t, stmt, `
@ -754,7 +754,7 @@ SELECT city.city_id AS "my_city.id",
FROM dvds.city FROM dvds.city
INNER JOIN dvds.address ON (address.city_id = city.city_id) INNER JOIN dvds.address ON (address.city_id = city.city_id)
INNER JOIN dvds.customer ON (customer.address_id = address.address_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; ORDER BY city.city_id, address.address_id, customer.customer_id;
`, "London", "York") `, "London", "York")
@ -798,7 +798,7 @@ func TestSelectExecution3(t *testing.T) {
Address.AddressID.AS("address_id"), Address.AddressID.AS("address_id"),
Address.Address.AS("address_line"), 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) ORDER_BY(City.CityID, Address.AddressID, Customer.CustomerID)
testutils.AssertDebugStatementSql(t, stmt, ` testutils.AssertDebugStatementSql(t, stmt, `
@ -811,7 +811,7 @@ SELECT city.city_id AS "city_id",
FROM dvds.city FROM dvds.city
INNER JOIN dvds.address ON (address.city_id = city.city_id) INNER JOIN dvds.address ON (address.city_id = city.city_id)
INNER JOIN dvds.customer ON (customer.address_id = address.address_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; ORDER BY city.city_id, address.address_id, customer.customer_id;
`, "London", "York") `, "London", "York")
@ -1866,7 +1866,7 @@ SELECT customer.customer_id AS "customer.customer_id",
FROM dvds.payment FROM dvds.payment
INNER JOIN dvds.customer ON (customer.customer_id = payment.customer_id) INNER JOIN dvds.customer ON (customer.customer_id = payment.customer_id)
GROUP BY customer.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; ORDER BY customer.customer_id, SUM(payment.amount) ASC;
` `
query := SELECT( query := SELECT(
@ -1885,14 +1885,14 @@ ORDER BY customer.customer_id, SUM(payment.amount) ASC;
).GROUP_BY( ).GROUP_BY(
Customer.CustomerID, Customer.CustomerID,
).HAVING( ).HAVING(
SUMf(Payment.Amount).GT(Float(125.6)), SUMf(Payment.Amount).GT(Real(125)),
).ORDER_BY( ).ORDER_BY(
Customer.CustomerID, SUMf(Payment.Amount).ASC(), Customer.CustomerID, SUMf(Payment.Amount).ASC(),
) )
//fmt.Println(query.DebugSql()) //fmt.Println(query.DebugSql())
testutils.AssertDebugStatementSql(t, query, expectedSQL, float64(125.6)) testutils.AssertDebugStatementSql(t, query, expectedSQL, float32(125))
var dest []struct { var dest []struct {
model.Customer model.Customer
@ -2378,14 +2378,14 @@ func TestSelectUnion(t *testing.T) {
SELECT payment.payment_id AS "payment.payment_id", SELECT payment.payment_id AS "payment.payment_id",
payment.amount AS "payment.amount" payment.amount AS "payment.amount"
FROM dvds.payment FROM dvds.payment
WHERE payment.amount <= 100 WHERE payment.amount <= 100::double precision
) )
UNION ALL UNION ALL
( (
SELECT payment.payment_id AS "payment.payment_id", SELECT payment.payment_id AS "payment.payment_id",
payment.amount AS "payment.amount" payment.amount AS "payment.amount"
FROM dvds.payment FROM dvds.payment
WHERE payment.amount >= 200 WHERE payment.amount >= 200::double precision
) )
ORDER BY "payment.payment_id" ASC, "payment.amount" DESC ORDER BY "payment.payment_id" ASC, "payment.amount" DESC
LIMIT 10 LIMIT 10
@ -2394,10 +2394,10 @@ OFFSET 20;
query := UNION_ALL( query := UNION_ALL(
Payment. Payment.
SELECT(Payment.PaymentID.AS("payment.payment_id"), Payment.Amount). SELECT(Payment.PaymentID.AS("payment.payment_id"), Payment.Amount).
WHERE(Payment.Amount.LT_EQ(Float(100))), WHERE(Payment.Amount.LT_EQ(Double(100))),
Payment. Payment.
SELECT(Payment.PaymentID, Payment.Amount). SELECT(Payment.PaymentID, Payment.Amount).
WHERE(Payment.Amount.GT_EQ(Float(200))), WHERE(Payment.Amount.GT_EQ(Double(200))),
).ORDER_BY( ).ORDER_BY(
IntegerColumn("payment.payment_id").ASC(), IntegerColumn("payment.payment_id").ASC(),
Payment.Amount.DESC(), Payment.Amount.DESC(),
@ -2729,7 +2729,7 @@ FROM dvds.actor
INNER JOIN dvds.language ON (language.language_id = film.language_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.film_category ON (film_category.film_id = film.film_id)
INNER JOIN dvds.category ON (category.category_id = film_category.category_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; 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(FilmCategory, FilmCategory.FilmID.EQ(Film.FilmID)).
INNER_JOIN(Category, Category.CategoryID.EQ(FilmCategory.CategoryID)), INNER_JOIN(Category, Category.CategoryID.EQ(FilmCategory.CategoryID)),
).WHERE( ).WHERE(
Language.Name.EQ(String("English")). // note that every column has type. Language.Name.EQ(Char(20)("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(Category.Name.NOT_EQ(Text("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 AND(Film.Length.GT(Int32(180))), // Film.Length is integer column and can be compared only with integer expression
).ORDER_BY( ).ORDER_BY(
Actor.ActorID.ASC(), Actor.ActorID.ASC(),
Film.FilmID.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 { var dest []struct {
model.Actor model.Actor
@ -3162,7 +3162,7 @@ func TestSelectLateral(t *testing.T) {
).FROM( ).FROM(
Language, Language,
).WHERE( ).WHERE(
Language.Name.NOT_IN(String("spanish")). Language.Name.NOT_IN(Char(20)("Spanish"), Char(20)("Catalan")).
AND(Film.LanguageID.EQ(Language.LanguageID)), AND(Film.LanguageID.EQ(Language.LanguageID)),
), ),
).AS("films") ).AS("films")
@ -3191,7 +3191,7 @@ FROM dvds.film
language.name AS "language.name", language.name AS "language.name",
language.last_update AS "language.last_update" language.last_update AS "language.last_update"
FROM dvds.language 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 ) AS films
WHERE film.film_id = 1 WHERE film.film_id = 1
ORDER BY film.film_id ORDER BY film.film_id
@ -3236,7 +3236,7 @@ FROM dvds.film,
language.name AS "language.name", language.name AS "language.name",
language.last_update AS "language.last_update" language.last_update AS "language.last_update"
FROM dvds.language 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 ) AS films
WHERE film.film_id = 1 WHERE film.film_id = 1
ORDER BY film.film_id ORDER BY film.film_id
@ -3787,9 +3787,9 @@ func TestSelectConditionalFunctions(t *testing.T) {
Film.SELECT(Film.FilmID).WHERE(Film.RentalDuration.GT(Int(100))), Film.SELECT(Film.FilmID).WHERE(Film.RentalDuration.GT(Int(100))),
).AS("exists"), ).AS("exists"),
CASE(Film.Length.GT(Int(120))). CASE(Film.Length.GT(Int(120))).
WHEN(Bool(true)).THEN(String("long film")). WHEN(Bool(true)).THEN(Text("long film")).
ELSE(String("short film")).AS("case"), ELSE(Text("short film")).AS("case"),
COALESCE(Film.Description, String("none")).AS("coalesce"), COALESCE(Film.Description, Text("none")).AS("coalesce"),
NULLIF(Film.ReleaseYear, Int(200)).AS("null_if"), NULLIF(Film.ReleaseYear, Int(200)).AS("null_if"),
GREATEST(Film.RentalDuration, Int(4), Int(5)).AS("greatest"), GREATEST(Film.RentalDuration, Int(4), Int(5)).AS("greatest"),
LEAST(Film.RentalDuration, Int(7), Int(6)).AS("least"), LEAST(Film.RentalDuration, Int(7), Int(6)).AS("least"),

View file

@ -15,9 +15,9 @@ import (
func TestVALUES(t *testing.T) { func TestVALUES(t *testing.T) {
values := VALUES( values := VALUES(
WRAP(Int32(1), Int32(2), Float32(4.666), Bool(false), String("txt")), WRAP(Int32(1), Int32(2), Real(4.666), Bool(false), String("txt")),
WRAP(Int32(11).ADD(Int32(2)), Int32(22), Float32(33.222), Bool(true), String("png")), WRAP(Int32(11).ADD(Int32(2)), Int32(22), Real(33.222), Bool(true), String("png")),
WRAP(Int32(11), Int32(22), Float32(33.222), Bool(true), NULL), WRAP(Int32(11), Int32(22), Real(33.222), Bool(true), NULL),
).AS("values_table") ).AS("values_table")
stmt := SELECT( stmt := SELECT(
@ -86,11 +86,11 @@ func TestVALUES_Join(t *testing.T) {
lastUpdate := Timestamp(2007, time.February, 11, 12, 0, 0) lastUpdate := Timestamp(2007, time.February, 11, 12, 0, 0)
filmValues := VALUES( filmValues := VALUES(
WRAP(String("Chamber Italian"), Int64(117), Int32(2005), Float32(5.82), lastUpdate), WRAP(String("Chamber Italian"), Int64(117), Int32(2005), Real(5.82), lastUpdate),
WRAP(String("Grosse Wonderful"), Int64(49), Int32(2004), Float32(6.242), lastUpdate.ADD(INTERVAL(1, HOUR))), WRAP(String("Grosse Wonderful"), Int64(49), Int32(2004), Real(6.242), lastUpdate.ADD(INTERVAL(1, HOUR))),
WRAP(String("Airport Pollock"), Int64(54), Int32(2001), Float32(7.22), NULL), WRAP(String("Airport Pollock"), Int64(54), Int32(2001), Real(7.22), NULL),
WRAP(String("Bright Encounters"), Int64(73), Int32(2002), Float32(8.25), NULL), WRAP(String("Bright Encounters"), Int64(73), Int32(2002), Real(8.25), NULL),
WRAP(String("Academy Dinosaur"), Int64(83), Int32(2010), Float32(9.22), lastUpdate.SUB(INTERVAL(2, MINUTE))), WRAP(String("Academy Dinosaur"), Int64(83), Int32(2010), Real(9.22), lastUpdate.SUB(INTERVAL(2, MINUTE))),
).AS("film_values", ).AS("film_values",
title, IntegerColumn("length"), releaseYear, rentalRate, TimestampColumn("update_date")) title, IntegerColumn("length"), releaseYear, rentalRate, TimestampColumn("update_date"))
@ -216,10 +216,10 @@ func TestVALUES_CTE_Update(t *testing.T) {
stmt := WITH( stmt := WITH(
paymentsToUpdate.AS( paymentsToUpdate.AS(
VALUES( VALUES(
WRAP(Int32(20564), Float32(1.21)), WRAP(Int32(20564), Real(1.21)),
WRAP(Int32(20567), Float32(1.02)), WRAP(Int32(20567), Real(1.02)),
WRAP(Int32(20570), Float32(1.34)), WRAP(Int32(20570), Real(1.34)),
WRAP(Int32(20573), Float32(1.72)), WRAP(Int32(20573), Real(1.72)),
), ),
), ),
)( )(