Tests folder structure reorganisation.
This commit is contained in:
parent
d0533f73fb
commit
6bf9c32c07
19 changed files with 22 additions and 24 deletions
717
tests/postgres/all_types_test.go
Normal file
717
tests/postgres/all_types_test.go
Normal file
|
|
@ -0,0 +1,717 @@
|
|||
package postgres
|
||||
|
||||
import (
|
||||
. "github.com/go-jet/jet"
|
||||
"github.com/go-jet/jet/internal/testutils"
|
||||
"github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/model"
|
||||
. "github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/table"
|
||||
"github.com/google/uuid"
|
||||
"gotest.tools/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAllTypesSelect(t *testing.T) {
|
||||
dest := []model.AllTypes{}
|
||||
|
||||
err := AllTypes.SELECT(AllTypes.AllColumns).Query(db, &dest)
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.DeepEqual(t, dest[0], allTypesRow0)
|
||||
assert.DeepEqual(t, dest[1], allTypesRow1)
|
||||
}
|
||||
|
||||
func TestAllTypesInsertModel(t *testing.T) {
|
||||
query := AllTypes.INSERT(AllTypes.AllColumns).
|
||||
MODEL(allTypesRow0).
|
||||
MODEL(&allTypesRow1).
|
||||
RETURNING(AllTypes.AllColumns)
|
||||
|
||||
dest := []model.AllTypes{}
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(dest), 2)
|
||||
assert.DeepEqual(t, dest[0], allTypesRow0)
|
||||
assert.DeepEqual(t, dest[1], allTypesRow1)
|
||||
}
|
||||
|
||||
func TestAllTypesInsertQuery(t *testing.T) {
|
||||
query := AllTypes.INSERT(AllTypes.AllColumns).
|
||||
QUERY(
|
||||
AllTypes.
|
||||
SELECT(AllTypes.AllColumns).
|
||||
LIMIT(2),
|
||||
).
|
||||
RETURNING(AllTypes.AllColumns)
|
||||
|
||||
dest := []model.AllTypes{}
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(dest), 2)
|
||||
assert.DeepEqual(t, dest[0], allTypesRow0)
|
||||
assert.DeepEqual(t, dest[1], allTypesRow1)
|
||||
}
|
||||
|
||||
func TestExpressionOperators(t *testing.T) {
|
||||
query := AllTypes.SELECT(
|
||||
AllTypes.Integer.IS_NULL(),
|
||||
AllTypes.Timestamp.IS_NOT_NULL(),
|
||||
AllTypes.SmallintPtr.IN(Int(11), Int(22), NULL),
|
||||
AllTypes.SmallintPtr.IN(AllTypes.SELECT(AllTypes.IntegerPtr)),
|
||||
AllTypes.SmallintPtr.NOT_IN(Int(11), Int(22), NULL),
|
||||
AllTypes.SmallintPtr.NOT_IN(AllTypes.SELECT(AllTypes.IntegerPtr)),
|
||||
|
||||
CAST(String("TRUE")).AS_BOOL(),
|
||||
CAST(String("111")).AS_SMALLINT(),
|
||||
CAST(String("111")).AS_INTEGER(),
|
||||
CAST(String("111")).AS_BIGINT(),
|
||||
CAST(String("11.23")).AS_NUMERIC(30, 10),
|
||||
CAST(String("11.23")).AS_NUMERIC(30),
|
||||
CAST(String("11.23")).AS_REAL(),
|
||||
CAST(String("11.23")).AS_DOUBLE(),
|
||||
CAST(Int(234)).AS_TEXT(),
|
||||
CAST(String("1/8/1999")).AS_DATE(),
|
||||
CAST(String("04:05:06.789")).AS_TIME(),
|
||||
CAST(String("04:05:06 PST")).AS_TIMEZ(),
|
||||
CAST(String("1999-01-08 04:05:06")).AS_TIMESTAMP(),
|
||||
CAST(String("January 8 04:05:06 1999 PST")).AS_TIMESTAMPZ(),
|
||||
|
||||
TO_CHAR(AllTypes.Timestamp, String("HH12:MI:SS")),
|
||||
TO_CHAR(AllTypes.Integer, String("999")),
|
||||
TO_CHAR(AllTypes.DoublePrecision, String("999D9")),
|
||||
TO_CHAR(AllTypes.Numeric, String("999D99S")),
|
||||
|
||||
TO_DATE(String("05 Dec 2000"), String("DD Mon YYYY")),
|
||||
TO_NUMBER(String("12,454"), String("99G999D9S")),
|
||||
TO_TIMESTAMP(String("05 Dec 2000"), String("DD Mon YYYY")),
|
||||
|
||||
COALESCE(AllTypes.IntegerPtr, AllTypes.SmallintPtr, NULL, Int(11)),
|
||||
NULLIF(AllTypes.Text, String("(none)")),
|
||||
GREATEST(AllTypes.Numeric, AllTypes.NumericPtr),
|
||||
LEAST(AllTypes.Numeric, AllTypes.NumericPtr),
|
||||
|
||||
RAW("current_database()"),
|
||||
)
|
||||
|
||||
//fmt.Println(query.DebugSql())
|
||||
|
||||
err := query.Query(db, &struct{}{})
|
||||
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
func TestStringOperators(t *testing.T) {
|
||||
query := AllTypes.SELECT(
|
||||
AllTypes.Text.EQ(AllTypes.Character),
|
||||
AllTypes.Text.EQ(String("Text")),
|
||||
AllTypes.Text.NOT_EQ(AllTypes.CharacterVaryingPtr),
|
||||
AllTypes.Text.NOT_EQ(String("Text")),
|
||||
AllTypes.Text.GT(AllTypes.Text),
|
||||
AllTypes.Text.GT(String("Text")),
|
||||
AllTypes.Text.GT_EQ(AllTypes.TextPtr),
|
||||
AllTypes.Text.GT_EQ(String("Text")),
|
||||
AllTypes.Text.LT(AllTypes.Character),
|
||||
AllTypes.Text.LT(String("Text")),
|
||||
AllTypes.Text.LT_EQ(AllTypes.CharacterVaryingPtr),
|
||||
AllTypes.Text.LT_EQ(String("Text")),
|
||||
AllTypes.Text.CONCAT(String("text2")),
|
||||
AllTypes.Text.CONCAT(Int(11)),
|
||||
AllTypes.Text.LIKE(String("abc")),
|
||||
AllTypes.Text.NOT_LIKE(String("_b_")),
|
||||
AllTypes.Text.SIMILAR_TO(String("%(b|d)%")),
|
||||
AllTypes.Text.NOT_SIMILAR_TO(String("(b|c)%")),
|
||||
|
||||
BIT_LENGTH(AllTypes.Text),
|
||||
CHAR_LENGTH(AllTypes.Character),
|
||||
OCTET_LENGTH(AllTypes.Text),
|
||||
LOWER(AllTypes.CharacterVaryingPtr),
|
||||
UPPER(AllTypes.Character),
|
||||
BTRIM(AllTypes.CharacterVarying),
|
||||
BTRIM(AllTypes.CharacterVarying, String("AA")),
|
||||
LTRIM(AllTypes.CharacterVarying),
|
||||
LTRIM(AllTypes.CharacterVarying, String("A")),
|
||||
RTRIM(AllTypes.CharacterVarying),
|
||||
RTRIM(AllTypes.CharacterVarying, String("B")),
|
||||
CHR(Int(65)),
|
||||
//CONCAT(String("string1"), Int(1), Float(11.12)),
|
||||
//CONCAT_WS(String("string1"), Int(1), Float(11.12)),
|
||||
CONVERT(String("text_in_utf8"), String("UTF8"), String("LATIN1")),
|
||||
CONVERT_FROM(String("text_in_utf8"), String("UTF8")),
|
||||
CONVERT_TO(String("text_in_utf8"), String("UTF8")),
|
||||
ENCODE(String("123\000\001"), String("base64")),
|
||||
DECODE(String("MTIzAAE="), String("base64")),
|
||||
//FORMAT(String("Hello %s, %1$s"), String("World")),
|
||||
INITCAP(String("hi THOMAS")),
|
||||
LEFT(String("abcde"), Int(2)),
|
||||
RIGHT(String("abcde"), Int(2)),
|
||||
LENGTH(String("jose")),
|
||||
LENGTH(String("jose"), String("UTF8")),
|
||||
LPAD(String("Hi"), Int(5)),
|
||||
LPAD(String("Hi"), Int(5), String("xy")),
|
||||
RPAD(String("Hi"), Int(5)),
|
||||
RPAD(String("Hi"), Int(5), String("xy")),
|
||||
MD5(AllTypes.CharacterVarying),
|
||||
REPEAT(AllTypes.Text, Int(33)),
|
||||
REPLACE(AllTypes.Character, String("BA"), String("AB")),
|
||||
REVERSE(AllTypes.CharacterVarying),
|
||||
STRPOS(AllTypes.Text, String("A")),
|
||||
SUBSTR(AllTypes.CharacterPtr, Int(3)),
|
||||
SUBSTR(AllTypes.CharacterPtr, Int(3), Int(2)),
|
||||
TO_HEX(AllTypes.IntegerPtr),
|
||||
)
|
||||
|
||||
//_, args, _ := query.Sql()
|
||||
|
||||
//fmt.Println(query.Sql())
|
||||
//fmt.Println(args[15])
|
||||
//fmt.Println(query.DebugSql())
|
||||
|
||||
err := query.Query(db, &struct{}{})
|
||||
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
func TestBoolOperators(t *testing.T) {
|
||||
query := AllTypes.SELECT(
|
||||
AllTypes.Boolean.EQ(AllTypes.BooleanPtr).AS("EQ1"),
|
||||
AllTypes.Boolean.EQ(Bool(true)).AS("EQ2"),
|
||||
AllTypes.Boolean.NOT_EQ(AllTypes.BooleanPtr).AS("NEq1"),
|
||||
AllTypes.Boolean.NOT_EQ(Bool(false)).AS("NEq2"),
|
||||
AllTypes.Boolean.IS_DISTINCT_FROM(AllTypes.BooleanPtr).AS("distinct1"),
|
||||
AllTypes.Boolean.IS_DISTINCT_FROM(Bool(true)).AS("distinct2"),
|
||||
AllTypes.Boolean.IS_NOT_DISTINCT_FROM(AllTypes.BooleanPtr).AS("not_distinct_1"),
|
||||
AllTypes.Boolean.IS_NOT_DISTINCT_FROM(Bool(true)).AS("NOTDISTINCT2"),
|
||||
AllTypes.Boolean.IS_TRUE().AS("ISTRUE"),
|
||||
AllTypes.Boolean.IS_NOT_TRUE().AS("isnottrue"),
|
||||
AllTypes.Boolean.IS_FALSE().AS("is_False"),
|
||||
AllTypes.Boolean.IS_NOT_FALSE().AS("is not false"),
|
||||
AllTypes.Boolean.IS_UNKNOWN().AS("is unknown"),
|
||||
AllTypes.Boolean.IS_NOT_UNKNOWN().AS("is_not_unknown"),
|
||||
|
||||
AllTypes.Boolean.AND(AllTypes.Boolean).EQ(AllTypes.Boolean.AND(AllTypes.Boolean)).AS("complex1"),
|
||||
AllTypes.Boolean.OR(AllTypes.Boolean).EQ(AllTypes.Boolean.AND(AllTypes.Boolean)).AS("complex2"),
|
||||
).LIMIT(2)
|
||||
|
||||
//fmt.Println(query.Sql())
|
||||
|
||||
testutils.AssertStatementSql(t, query, `
|
||||
SELECT (all_types.boolean = all_types.boolean_ptr) AS "EQ1",
|
||||
(all_types.boolean = $1) AS "EQ2",
|
||||
(all_types.boolean != all_types.boolean_ptr) AS "NEq1",
|
||||
(all_types.boolean != $2) AS "NEq2",
|
||||
(all_types.boolean IS DISTINCT FROM all_types.boolean_ptr) AS "distinct1",
|
||||
(all_types.boolean IS DISTINCT FROM $3) AS "distinct2",
|
||||
(all_types.boolean IS NOT DISTINCT FROM all_types.boolean_ptr) AS "not_distinct_1",
|
||||
(all_types.boolean IS NOT DISTINCT FROM $4) AS "NOTDISTINCT2",
|
||||
all_types.boolean IS TRUE AS "ISTRUE",
|
||||
all_types.boolean IS NOT TRUE AS "isnottrue",
|
||||
all_types.boolean IS FALSE AS "is_False",
|
||||
all_types.boolean IS NOT FALSE AS "is not false",
|
||||
all_types.boolean IS UNKNOWN AS "is unknown",
|
||||
all_types.boolean IS NOT UNKNOWN AS "is_not_unknown",
|
||||
((all_types.boolean AND all_types.boolean) = (all_types.boolean AND all_types.boolean)) AS "complex1",
|
||||
((all_types.boolean OR all_types.boolean) = (all_types.boolean AND all_types.boolean)) AS "complex2"
|
||||
FROM test_sample.all_types
|
||||
LIMIT $5;
|
||||
`, true, false, true, true, int64(2))
|
||||
|
||||
var dest []struct {
|
||||
Eq1 *bool
|
||||
Eq2 *bool
|
||||
NEq1 *bool
|
||||
NEq2 *bool
|
||||
Distinct1 *bool
|
||||
Distinct2 *bool
|
||||
NotDistinct1 *bool
|
||||
NotDistinct2 *bool
|
||||
IsTrue *bool
|
||||
IsNotTrue *bool
|
||||
IsFalse *bool
|
||||
IsNotFalse *bool
|
||||
IsUnknown *bool
|
||||
IsNotUnknown *bool
|
||||
|
||||
Complex1 *bool
|
||||
Complex2 *bool
|
||||
}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
|
||||
testutils.AssertJSONFile(t, "./testdata/common/bool_operators.json", dest)
|
||||
}
|
||||
|
||||
func TestFloatOperators(t *testing.T) {
|
||||
query := AllTypes.SELECT(
|
||||
AllTypes.Numeric.EQ(AllTypes.Numeric),
|
||||
AllTypes.Decimal.EQ(Float(12)),
|
||||
AllTypes.Real.EQ(Float(12.12)),
|
||||
AllTypes.Numeric.IS_DISTINCT_FROM(AllTypes.Numeric),
|
||||
AllTypes.Decimal.IS_DISTINCT_FROM(Float(12)),
|
||||
AllTypes.Real.IS_DISTINCT_FROM(Float(12.12)),
|
||||
AllTypes.Numeric.IS_NOT_DISTINCT_FROM(AllTypes.Numeric),
|
||||
AllTypes.Decimal.IS_NOT_DISTINCT_FROM(Float(12)),
|
||||
AllTypes.Real.IS_NOT_DISTINCT_FROM(Float(12.12)),
|
||||
//AllTypes.Numeric.LT(AllTypes.Integer),
|
||||
AllTypes.Numeric.LT(Float(124)),
|
||||
AllTypes.Numeric.LT(Float(34.56)),
|
||||
//AllTypes.Numeric.GT(AllTypes.Smallint),
|
||||
AllTypes.Numeric.GT(Float(124)),
|
||||
AllTypes.Numeric.GT(Float(34.56)),
|
||||
|
||||
AllTypes.Real.ADD(AllTypes.RealPtr),
|
||||
AllTypes.Real.ADD(Float(11.22)),
|
||||
AllTypes.Real.SUB(AllTypes.RealPtr),
|
||||
AllTypes.Real.SUB(Float(11.22)),
|
||||
AllTypes.Real.MUL(AllTypes.RealPtr),
|
||||
AllTypes.Real.MUL(Float(11.22)),
|
||||
AllTypes.Real.DIV(AllTypes.RealPtr),
|
||||
AllTypes.Real.DIV(Float(11.22)),
|
||||
AllTypes.Decimal.MOD(AllTypes.Decimal),
|
||||
AllTypes.Decimal.MOD(Float(11.22)),
|
||||
AllTypes.Real.POW(AllTypes.RealPtr),
|
||||
AllTypes.Real.POW(Float(11.22)),
|
||||
|
||||
ABSf(AllTypes.Real),
|
||||
SQRT(AllTypes.Real),
|
||||
CBRT(AllTypes.Real),
|
||||
CEIL(AllTypes.Real),
|
||||
FLOOR(AllTypes.Real),
|
||||
ROUND(AllTypes.Decimal),
|
||||
ROUND(AllTypes.Decimal, AllTypes.Integer).AS("round"),
|
||||
SIGN(AllTypes.Real),
|
||||
TRUNC(AllTypes.Decimal),
|
||||
TRUNC(AllTypes.Decimal, Int(1)),
|
||||
)
|
||||
|
||||
//fmt.Println(query.DebugSql())
|
||||
|
||||
err := query.Query(db, &struct{}{})
|
||||
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
func TestIntegerOperators(t *testing.T) {
|
||||
query := AllTypes.SELECT(
|
||||
AllTypes.Integer.EQ(AllTypes.IntegerPtr),
|
||||
AllTypes.Bigint.EQ(Int(12)),
|
||||
//AllTypes.Smallint.NOT_EQ(AllTypes.Real),
|
||||
AllTypes.Integer.NOT_EQ(AllTypes.IntegerPtr),
|
||||
AllTypes.Bigint.NOT_EQ(Int(12)),
|
||||
AllTypes.Integer.LT(AllTypes.IntegerPtr),
|
||||
AllTypes.Bigint.LT(Int(65)),
|
||||
//AllTypes.Smallint.LT_EQ(AllTypes.Numeric),
|
||||
AllTypes.Integer.LT_EQ(AllTypes.IntegerPtr),
|
||||
AllTypes.Bigint.LT_EQ(Int(65)),
|
||||
//AllTypes.Smallint.GT_EQ(AllTypes.Numeric),
|
||||
AllTypes.Integer.GT(AllTypes.IntegerPtr),
|
||||
AllTypes.Bigint.GT(Int(65)),
|
||||
AllTypes.Integer.GT_EQ(AllTypes.IntegerPtr),
|
||||
AllTypes.Bigint.GT_EQ(Int(65)),
|
||||
|
||||
AllTypes.Integer.ADD(AllTypes.Integer),
|
||||
AllTypes.Integer.ADD(Int(11)),
|
||||
AllTypes.Integer.SUB(AllTypes.Integer),
|
||||
AllTypes.Integer.SUB(Int(11)),
|
||||
AllTypes.Integer.MUL(AllTypes.Integer),
|
||||
AllTypes.Integer.MUL(Int(11)),
|
||||
AllTypes.Integer.DIV(AllTypes.Integer),
|
||||
AllTypes.Integer.DIV(Int(11)),
|
||||
AllTypes.Integer.MOD(AllTypes.Integer),
|
||||
AllTypes.Integer.MOD(Int(11)),
|
||||
AllTypes.Integer.POW(AllTypes.Smallint),
|
||||
AllTypes.Integer.POW(Int(11)),
|
||||
AllTypes.Integer.BIT_AND(AllTypes.Smallint),
|
||||
AllTypes.Integer.BIT_OR(AllTypes.Smallint),
|
||||
AllTypes.Integer.BIT_XOR(Int(11)),
|
||||
BIT_NOT(AllTypes.Integer),
|
||||
AllTypes.Integer.BIT_SHIFT_LEFT(AllTypes.Smallint),
|
||||
AllTypes.Integer.BIT_SHIFT_LEFT(Int(11)),
|
||||
AllTypes.Integer.BIT_SHIFT_RIGHT(AllTypes.Smallint),
|
||||
AllTypes.Integer.BIT_SHIFT_RIGHT(Int(11)),
|
||||
|
||||
ABSi(AllTypes.Integer),
|
||||
SQRT(AllTypes.Integer),
|
||||
CBRT(AllTypes.Integer),
|
||||
)
|
||||
|
||||
//fmt.Println(query.DebugSql())
|
||||
|
||||
err := query.Query(db, &struct{}{})
|
||||
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
func TestTimeOperators(t *testing.T) {
|
||||
query := AllTypes.SELECT(
|
||||
AllTypes.Time.EQ(AllTypes.Time),
|
||||
AllTypes.Time.EQ(Time(23, 6, 6, 1)),
|
||||
AllTypes.Timez.EQ(AllTypes.TimezPtr),
|
||||
AllTypes.Timez.EQ(Timez(23, 6, 6, 222, +200)),
|
||||
AllTypes.Timestamp.EQ(AllTypes.TimestampPtr),
|
||||
AllTypes.Timestamp.EQ(Timestamp(2010, 10, 21, 15, 30, 12, 333)),
|
||||
AllTypes.Timestampz.EQ(AllTypes.TimestampzPtr),
|
||||
AllTypes.Timestampz.EQ(Timestampz(2010, 10, 21, 15, 30, 12, 444, 0)),
|
||||
AllTypes.Date.EQ(AllTypes.DatePtr),
|
||||
AllTypes.Date.EQ(Date(2010, 12, 3)),
|
||||
|
||||
AllTypes.Time.NOT_EQ(AllTypes.Time),
|
||||
AllTypes.Time.NOT_EQ(Time(23, 6, 6, 10)),
|
||||
AllTypes.Timez.NOT_EQ(AllTypes.TimezPtr),
|
||||
AllTypes.Timez.NOT_EQ(Timez(23, 6, 6, 555, +200)),
|
||||
AllTypes.Timestamp.NOT_EQ(AllTypes.TimestampPtr),
|
||||
AllTypes.Timestamp.NOT_EQ(Timestamp(2010, 10, 21, 15, 30, 12, 666)),
|
||||
AllTypes.Timestampz.NOT_EQ(AllTypes.TimestampzPtr),
|
||||
AllTypes.Timestampz.NOT_EQ(Timestampz(2010, 10, 21, 15, 30, 12, 777, 0)),
|
||||
AllTypes.Date.NOT_EQ(AllTypes.DatePtr),
|
||||
AllTypes.Date.NOT_EQ(Date(2010, 12, 3)),
|
||||
|
||||
AllTypes.Time.IS_DISTINCT_FROM(AllTypes.Time),
|
||||
AllTypes.Time.IS_DISTINCT_FROM(Time(23, 6, 6, 100)),
|
||||
|
||||
AllTypes.Time.IS_NOT_DISTINCT_FROM(AllTypes.Time),
|
||||
AllTypes.Time.IS_NOT_DISTINCT_FROM(Time(23, 6, 6, 200)),
|
||||
|
||||
AllTypes.Time.LT(AllTypes.Time),
|
||||
AllTypes.Time.LT(Time(23, 6, 6, 22)),
|
||||
|
||||
AllTypes.Time.LT_EQ(AllTypes.Time),
|
||||
AllTypes.Time.LT_EQ(Time(23, 6, 6, 33)),
|
||||
|
||||
AllTypes.Time.GT(AllTypes.Time),
|
||||
AllTypes.Time.GT(Time(23, 6, 6, 0)),
|
||||
|
||||
AllTypes.Time.GT_EQ(AllTypes.Time),
|
||||
AllTypes.Time.GT_EQ(Time(23, 6, 6, 1)),
|
||||
|
||||
CURRENT_DATE(),
|
||||
CURRENT_TIME(),
|
||||
CURRENT_TIME(2),
|
||||
CURRENT_TIMESTAMP(),
|
||||
CURRENT_TIMESTAMP(1),
|
||||
LOCALTIME(),
|
||||
LOCALTIME(11),
|
||||
LOCALTIMESTAMP(),
|
||||
LOCALTIMESTAMP(4),
|
||||
NOW(),
|
||||
)
|
||||
|
||||
//fmt.Println(query.DebugSql())
|
||||
|
||||
err := query.Query(db, &struct{}{})
|
||||
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
func TestSubQueryColumnReference(t *testing.T) {
|
||||
|
||||
type expected struct {
|
||||
sql string
|
||||
args []interface{}
|
||||
}
|
||||
|
||||
subQueries := map[SelectTable]expected{}
|
||||
|
||||
selectSubQuery := AllTypes.SELECT(
|
||||
AllTypes.Boolean,
|
||||
AllTypes.Integer,
|
||||
AllTypes.Real,
|
||||
AllTypes.Text,
|
||||
AllTypes.Time,
|
||||
AllTypes.Timez,
|
||||
AllTypes.Timestamp,
|
||||
AllTypes.Timestampz,
|
||||
AllTypes.Date,
|
||||
AllTypes.Bytea.AS("aliasedColumn"),
|
||||
).
|
||||
LIMIT(2).
|
||||
AsTable("subQuery")
|
||||
|
||||
var selectexpectedSQL = ` (
|
||||
SELECT all_types.boolean AS "all_types.boolean",
|
||||
all_types.integer AS "all_types.integer",
|
||||
all_types.real AS "all_types.real",
|
||||
all_types.text AS "all_types.text",
|
||||
all_types.time AS "all_types.time",
|
||||
all_types.timez AS "all_types.timez",
|
||||
all_types.timestamp AS "all_types.timestamp",
|
||||
all_types.timestampz AS "all_types.timestampz",
|
||||
all_types.date AS "all_types.date",
|
||||
all_types.bytea AS "aliasedColumn"
|
||||
FROM test_sample.all_types
|
||||
LIMIT 2
|
||||
) AS "subQuery"`
|
||||
|
||||
unionSubQuery :=
|
||||
UNION_ALL(
|
||||
AllTypes.SELECT(
|
||||
AllTypes.Boolean,
|
||||
AllTypes.Integer,
|
||||
AllTypes.Real,
|
||||
AllTypes.Text,
|
||||
AllTypes.Time,
|
||||
AllTypes.Timez,
|
||||
AllTypes.Timestamp,
|
||||
AllTypes.Timestampz,
|
||||
AllTypes.Date,
|
||||
AllTypes.Bytea.AS("aliasedColumn"),
|
||||
).
|
||||
LIMIT(1),
|
||||
AllTypes.SELECT(
|
||||
AllTypes.Boolean,
|
||||
AllTypes.Integer,
|
||||
AllTypes.Real,
|
||||
AllTypes.Text,
|
||||
AllTypes.Time,
|
||||
AllTypes.Timez,
|
||||
AllTypes.Timestamp,
|
||||
AllTypes.Timestampz,
|
||||
AllTypes.Date,
|
||||
AllTypes.Bytea.AS("aliasedColumn"),
|
||||
).
|
||||
LIMIT(1).OFFSET(1),
|
||||
).
|
||||
AsTable("subQuery")
|
||||
|
||||
unionexpectedSQL := `
|
||||
(
|
||||
(
|
||||
SELECT all_types.boolean AS "all_types.boolean",
|
||||
all_types.integer AS "all_types.integer",
|
||||
all_types.real AS "all_types.real",
|
||||
all_types.text AS "all_types.text",
|
||||
all_types.time AS "all_types.time",
|
||||
all_types.timez AS "all_types.timez",
|
||||
all_types.timestamp AS "all_types.timestamp",
|
||||
all_types.timestampz AS "all_types.timestampz",
|
||||
all_types.date AS "all_types.date",
|
||||
all_types.bytea AS "aliasedColumn"
|
||||
FROM test_sample.all_types
|
||||
LIMIT 1
|
||||
)
|
||||
UNION ALL
|
||||
(
|
||||
SELECT all_types.boolean AS "all_types.boolean",
|
||||
all_types.integer AS "all_types.integer",
|
||||
all_types.real AS "all_types.real",
|
||||
all_types.text AS "all_types.text",
|
||||
all_types.time AS "all_types.time",
|
||||
all_types.timez AS "all_types.timez",
|
||||
all_types.timestamp AS "all_types.timestamp",
|
||||
all_types.timestampz AS "all_types.timestampz",
|
||||
all_types.date AS "all_types.date",
|
||||
all_types.bytea AS "aliasedColumn"
|
||||
FROM test_sample.all_types
|
||||
LIMIT 1
|
||||
OFFSET 1
|
||||
)
|
||||
) AS "subQuery"`
|
||||
|
||||
subQueries[unionSubQuery] = expected{sql: unionexpectedSQL, args: []interface{}{int64(1), int64(1), int64(1)}}
|
||||
subQueries[selectSubQuery] = expected{sql: selectexpectedSQL, args: []interface{}{int64(2)}}
|
||||
|
||||
for subQuery, expected := range subQueries {
|
||||
boolColumn := AllTypes.Boolean.From(subQuery)
|
||||
intColumn := AllTypes.Integer.From(subQuery)
|
||||
floatColumn := AllTypes.Real.From(subQuery)
|
||||
stringColumn := AllTypes.Text.From(subQuery)
|
||||
timeColumn := AllTypes.Time.From(subQuery)
|
||||
timezColumn := AllTypes.Timez.From(subQuery)
|
||||
timestampColumn := AllTypes.Timestamp.From(subQuery)
|
||||
timestampzColumn := AllTypes.Timestampz.From(subQuery)
|
||||
dateColumn := AllTypes.Date.From(subQuery)
|
||||
aliasedColumn := StringColumn("aliasedColumn").From(subQuery)
|
||||
|
||||
stmt1 := SELECT(
|
||||
boolColumn,
|
||||
intColumn,
|
||||
floatColumn,
|
||||
stringColumn,
|
||||
timeColumn,
|
||||
timezColumn,
|
||||
timestampColumn,
|
||||
timestampzColumn,
|
||||
dateColumn,
|
||||
aliasedColumn,
|
||||
).
|
||||
FROM(subQuery)
|
||||
|
||||
var expectedSQL = `
|
||||
SELECT "subQuery"."all_types.boolean" AS "all_types.boolean",
|
||||
"subQuery"."all_types.integer" AS "all_types.integer",
|
||||
"subQuery"."all_types.real" AS "all_types.real",
|
||||
"subQuery"."all_types.text" AS "all_types.text",
|
||||
"subQuery"."all_types.time" AS "all_types.time",
|
||||
"subQuery"."all_types.timez" AS "all_types.timez",
|
||||
"subQuery"."all_types.timestamp" AS "all_types.timestamp",
|
||||
"subQuery"."all_types.timestampz" AS "all_types.timestampz",
|
||||
"subQuery"."all_types.date" AS "all_types.date",
|
||||
"subQuery"."aliasedColumn" AS "aliasedColumn"
|
||||
FROM`
|
||||
|
||||
testutils.AssertDebugStatementSql(t, stmt1, expectedSQL+expected.sql+";\n", expected.args...)
|
||||
|
||||
dest1 := []model.AllTypes{}
|
||||
err := stmt1.Query(db, &dest1)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(dest1), 2)
|
||||
assert.Equal(t, dest1[0].Boolean, allTypesRow0.Boolean)
|
||||
assert.Equal(t, dest1[0].Integer, allTypesRow0.Integer)
|
||||
assert.Equal(t, dest1[0].Real, allTypesRow0.Real)
|
||||
assert.Equal(t, dest1[0].Text, allTypesRow0.Text)
|
||||
assert.DeepEqual(t, dest1[0].Time, allTypesRow0.Time)
|
||||
assert.DeepEqual(t, dest1[0].Timez, allTypesRow0.Timez)
|
||||
assert.DeepEqual(t, dest1[0].Timestamp, allTypesRow0.Timestamp)
|
||||
assert.DeepEqual(t, dest1[0].Timestampz, allTypesRow0.Timestampz)
|
||||
assert.DeepEqual(t, dest1[0].Date, allTypesRow0.Date)
|
||||
|
||||
stmt2 := SELECT(
|
||||
subQuery.AllColumns(),
|
||||
).
|
||||
FROM(subQuery)
|
||||
|
||||
//fmt.Println(stmt2.DebugSql())
|
||||
|
||||
testutils.AssertDebugStatementSql(t, stmt2, expectedSQL+expected.sql+";\n", expected.args...)
|
||||
|
||||
dest2 := []model.AllTypes{}
|
||||
err = stmt2.Query(db, &dest2)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, dest1, dest2)
|
||||
}
|
||||
}
|
||||
|
||||
var allTypesRow0 = model.AllTypes{
|
||||
SmallintPtr: Int16Ptr(1),
|
||||
Smallint: 1,
|
||||
IntegerPtr: Int32Ptr(300),
|
||||
Integer: 300,
|
||||
BigintPtr: Int64Ptr(50000),
|
||||
Bigint: 5000,
|
||||
DecimalPtr: Float64Ptr(11.44),
|
||||
Decimal: 11.44,
|
||||
NumericPtr: Float64Ptr(55.77),
|
||||
Numeric: 55.77,
|
||||
RealPtr: Float32Ptr(99.1),
|
||||
Real: 99.1,
|
||||
DoublePrecisionPtr: Float64Ptr(11111111.22),
|
||||
DoublePrecision: 11111111.22,
|
||||
Smallserial: 1,
|
||||
Serial: 1,
|
||||
Bigserial: 1,
|
||||
//MoneyPtr: nil,
|
||||
//Money:
|
||||
CharacterVaryingPtr: StringPtr("ABBA"),
|
||||
CharacterVarying: "ABBA",
|
||||
CharacterPtr: StringPtr("JOHN "),
|
||||
Character: "JOHN ",
|
||||
TextPtr: StringPtr("Some text"),
|
||||
Text: "Some text",
|
||||
ByteaPtr: ByteArrayPtr([]byte("bytea")),
|
||||
Bytea: []byte("bytea"),
|
||||
TimestampzPtr: TimestampWithTimeZone("1999-01-08 13:05:06 +0100 CET", 0),
|
||||
Timestampz: *TimestampWithTimeZone("1999-01-08 13:05:06 +0100 CET", 0),
|
||||
TimestampPtr: testutils.TimestampWithoutTimeZone("1999-01-08 04:05:06", 0),
|
||||
Timestamp: *testutils.TimestampWithoutTimeZone("1999-01-08 04:05:06", 0),
|
||||
DatePtr: testutils.TimestampWithoutTimeZone("1999-01-08 00:00:00", 0),
|
||||
Date: *testutils.TimestampWithoutTimeZone("1999-01-08 00:00:00", 0),
|
||||
TimezPtr: TimeWithTimeZone("04:05:06 -0800"),
|
||||
Timez: *TimeWithTimeZone("04:05:06 -0800"),
|
||||
TimePtr: TimeWithoutTimeZone("04:05:06"),
|
||||
Time: *TimeWithoutTimeZone("04:05:06"),
|
||||
IntervalPtr: StringPtr("3 days 04:05:06"),
|
||||
Interval: "3 days 04:05:06",
|
||||
BooleanPtr: BoolPtr(true),
|
||||
Boolean: false,
|
||||
PointPtr: StringPtr("(2,3)"),
|
||||
BitPtr: StringPtr("101"),
|
||||
Bit: "101",
|
||||
BitVaryingPtr: StringPtr("101111"),
|
||||
BitVarying: "101111",
|
||||
TsvectorPtr: StringPtr("'supernova':1"),
|
||||
Tsvector: "'supernova':1",
|
||||
UUIDPtr: UUIDPtr("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11"),
|
||||
UUID: uuid.MustParse("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11"),
|
||||
XMLPtr: StringPtr("<Sub>abc</Sub>"),
|
||||
XML: "<Sub>abc</Sub>",
|
||||
JSONPtr: StringPtr(`{"a": 1, "b": 3}`),
|
||||
JSON: `{"a": 1, "b": 3}`,
|
||||
JsonbPtr: StringPtr(`{"a": 1, "b": 3}`),
|
||||
Jsonb: `{"a": 1, "b": 3}`,
|
||||
IntegerArrayPtr: StringPtr("{1,2,3}"),
|
||||
IntegerArray: "{1,2,3}",
|
||||
TextArrayPtr: StringPtr("{breakfast,consulting}"),
|
||||
TextArray: "{breakfast,consulting}",
|
||||
JsonbArray: `{"{\"a\": 1, \"b\": 2}","{\"a\": 3, \"b\": 4}"}`,
|
||||
TextMultiDimArrayPtr: StringPtr("{{meeting,lunch},{training,presentation}}"),
|
||||
TextMultiDimArray: "{{meeting,lunch},{training,presentation}}",
|
||||
}
|
||||
|
||||
var allTypesRow1 = model.AllTypes{
|
||||
SmallintPtr: nil,
|
||||
Smallint: 1,
|
||||
IntegerPtr: nil,
|
||||
Integer: 300,
|
||||
BigintPtr: nil,
|
||||
Bigint: 5000,
|
||||
DecimalPtr: nil,
|
||||
Decimal: 11.44,
|
||||
NumericPtr: nil,
|
||||
Numeric: 55.77,
|
||||
RealPtr: nil,
|
||||
Real: 99.1,
|
||||
DoublePrecisionPtr: nil,
|
||||
DoublePrecision: 11111111.22,
|
||||
Smallserial: 2,
|
||||
Serial: 2,
|
||||
Bigserial: 2,
|
||||
//MoneyPtr: nil,
|
||||
//Money:
|
||||
CharacterVaryingPtr: nil,
|
||||
CharacterVarying: "ABBA",
|
||||
CharacterPtr: nil,
|
||||
Character: "JOHN ",
|
||||
TextPtr: nil,
|
||||
Text: "Some text",
|
||||
ByteaPtr: nil,
|
||||
Bytea: []byte("bytea"),
|
||||
TimestampzPtr: nil,
|
||||
Timestampz: *TimestampWithTimeZone("1999-01-08 13:05:06 +0100 CET", 0),
|
||||
TimestampPtr: nil,
|
||||
Timestamp: *testutils.TimestampWithoutTimeZone("1999-01-08 04:05:06", 0),
|
||||
DatePtr: nil,
|
||||
Date: *testutils.TimestampWithoutTimeZone("1999-01-08 00:00:00", 0),
|
||||
TimezPtr: nil,
|
||||
Timez: *TimeWithTimeZone("04:05:06 -0800"),
|
||||
TimePtr: nil,
|
||||
Time: *TimeWithoutTimeZone("04:05:06"),
|
||||
IntervalPtr: nil,
|
||||
Interval: "3 days 04:05:06",
|
||||
BooleanPtr: nil,
|
||||
Boolean: false,
|
||||
PointPtr: nil,
|
||||
BitPtr: nil,
|
||||
Bit: "101",
|
||||
BitVaryingPtr: nil,
|
||||
BitVarying: "101111",
|
||||
TsvectorPtr: nil,
|
||||
Tsvector: "'supernova':1",
|
||||
UUIDPtr: nil,
|
||||
UUID: uuid.MustParse("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11"),
|
||||
XMLPtr: nil,
|
||||
XML: "<Sub>abc</Sub>",
|
||||
JSONPtr: nil,
|
||||
JSON: `{"a": 1, "b": 3}`,
|
||||
JsonbPtr: nil,
|
||||
Jsonb: `{"a": 1, "b": 3}`,
|
||||
IntegerArrayPtr: nil,
|
||||
IntegerArray: "{1,2,3}",
|
||||
TextArrayPtr: nil,
|
||||
TextArray: "{breakfast,consulting}",
|
||||
JsonbArray: `{"{\"a\": 1, \"b\": 2}","{\"a\": 3, \"b\": 4}"}`,
|
||||
TextMultiDimArrayPtr: nil,
|
||||
TextMultiDimArray: "{{meeting,lunch},{training,presentation}}",
|
||||
}
|
||||
350
tests/postgres/chinook_db_test.go
Normal file
350
tests/postgres/chinook_db_test.go
Normal file
|
|
@ -0,0 +1,350 @@
|
|||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
. "github.com/go-jet/jet"
|
||||
"github.com/go-jet/jet/internal/testutils"
|
||||
"github.com/go-jet/jet/tests/.gentestdata/jetdb/chinook/model"
|
||||
. "github.com/go-jet/jet/tests/.gentestdata/jetdb/chinook/table"
|
||||
"gotest.tools/assert"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestSelect(t *testing.T) {
|
||||
stmt := Album.
|
||||
SELECT(Album.AllColumns).
|
||||
ORDER_BY(Album.AlbumId.ASC())
|
||||
|
||||
testutils.AssertDebugStatementSql(t, stmt, `
|
||||
SELECT "Album"."AlbumId" AS "Album.AlbumId",
|
||||
"Album"."Title" AS "Album.Title",
|
||||
"Album"."ArtistId" AS "Album.ArtistId"
|
||||
FROM chinook."Album"
|
||||
ORDER BY "Album"."AlbumId" ASC;
|
||||
`)
|
||||
dest := []model.Album{}
|
||||
|
||||
err := stmt.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(dest), 347)
|
||||
assert.DeepEqual(t, dest[0], album1)
|
||||
assert.DeepEqual(t, dest[1], album2)
|
||||
assert.DeepEqual(t, dest[len(dest)-1], album347)
|
||||
}
|
||||
|
||||
func TestJoinEverything(t *testing.T) {
|
||||
|
||||
manager := Employee.AS("Manager")
|
||||
|
||||
stmt := Artist.
|
||||
LEFT_JOIN(Album, Artist.ArtistId.EQ(Album.ArtistId)).
|
||||
LEFT_JOIN(Track, Track.AlbumId.EQ(Album.AlbumId)).
|
||||
LEFT_JOIN(Genre, Genre.GenreId.EQ(Track.GenreId)).
|
||||
LEFT_JOIN(MediaType, MediaType.MediaTypeId.EQ(Track.MediaTypeId)).
|
||||
LEFT_JOIN(PlaylistTrack, PlaylistTrack.TrackId.EQ(Track.TrackId)).
|
||||
LEFT_JOIN(Playlist, Playlist.PlaylistId.EQ(PlaylistTrack.PlaylistId)).
|
||||
LEFT_JOIN(InvoiceLine, InvoiceLine.TrackId.EQ(Track.TrackId)).
|
||||
LEFT_JOIN(Invoice, Invoice.InvoiceId.EQ(InvoiceLine.InvoiceId)).
|
||||
LEFT_JOIN(Customer, Customer.CustomerId.EQ(Invoice.CustomerId)).
|
||||
LEFT_JOIN(Employee, Employee.EmployeeId.EQ(Customer.SupportRepId)).
|
||||
LEFT_JOIN(manager, manager.EmployeeId.EQ(Employee.ReportsTo)).
|
||||
SELECT(
|
||||
Artist.AllColumns,
|
||||
Album.AllColumns,
|
||||
Track.AllColumns,
|
||||
Genre.AllColumns,
|
||||
MediaType.AllColumns,
|
||||
PlaylistTrack.AllColumns,
|
||||
Playlist.AllColumns,
|
||||
Invoice.AllColumns,
|
||||
Customer.AllColumns,
|
||||
Employee.AllColumns,
|
||||
manager.AllColumns,
|
||||
).
|
||||
ORDER_BY(Artist.ArtistId, Album.AlbumId, Track.TrackId,
|
||||
Genre.GenreId, MediaType.MediaTypeId, Playlist.PlaylistId,
|
||||
Invoice.InvoiceId, Customer.CustomerId)
|
||||
|
||||
var dest []struct { //list of all artist
|
||||
model.Artist
|
||||
|
||||
Albums []struct { // list of albums per artist
|
||||
model.Album
|
||||
|
||||
Tracks []struct { // list of tracks per album
|
||||
model.Track
|
||||
|
||||
Genre model.Genre // track genre
|
||||
MediaType model.MediaType // track media type
|
||||
|
||||
Playlists []model.Playlist // list of playlist where track is used
|
||||
|
||||
Invoices []struct { // list of invoices where track occurs
|
||||
model.Invoice
|
||||
|
||||
Customer struct { // customer data for invoice
|
||||
model.Customer
|
||||
|
||||
Employee *struct { // employee data for customer if exists
|
||||
model.Employee
|
||||
|
||||
Manager *model.Employee `alias:"Manager"`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err := stmt.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(dest), 275)
|
||||
testutils.AssertJSONFile(t, "./postgres/testdata/joined_everything.json", dest)
|
||||
}
|
||||
|
||||
func TestSelfJoin(t *testing.T) {
|
||||
var dest []struct {
|
||||
model.Employee
|
||||
|
||||
Manager *model.Employee `alias:"Manager.*"`
|
||||
}
|
||||
|
||||
manager := Employee.AS("Manager")
|
||||
|
||||
stmt := Employee.
|
||||
LEFT_JOIN(manager, Employee.ReportsTo.EQ(manager.EmployeeId)).
|
||||
SELECT(
|
||||
Employee.EmployeeId,
|
||||
Employee.FirstName,
|
||||
Employee.LastName,
|
||||
manager.EmployeeId,
|
||||
manager.FirstName,
|
||||
manager.LastName,
|
||||
).
|
||||
ORDER_BY(Employee.EmployeeId)
|
||||
|
||||
testutils.AssertDebugStatementSql(t, stmt, `
|
||||
SELECT "Employee"."EmployeeId" AS "Employee.EmployeeId",
|
||||
"Employee"."FirstName" AS "Employee.FirstName",
|
||||
"Employee"."LastName" AS "Employee.LastName",
|
||||
"Manager"."EmployeeId" AS "Manager.EmployeeId",
|
||||
"Manager"."FirstName" AS "Manager.FirstName",
|
||||
"Manager"."LastName" AS "Manager.LastName"
|
||||
FROM chinook."Employee"
|
||||
LEFT JOIN chinook."Employee" AS "Manager" ON ("Employee"."ReportsTo" = "Manager"."EmployeeId")
|
||||
ORDER BY "Employee"."EmployeeId";
|
||||
`)
|
||||
|
||||
err := stmt.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(dest), 8)
|
||||
testutils.AssertJSON(t, dest[0:2], `
|
||||
[
|
||||
{
|
||||
"EmployeeId": 1,
|
||||
"LastName": "Adams",
|
||||
"FirstName": "Andrew",
|
||||
"Title": null,
|
||||
"ReportsTo": null,
|
||||
"BirthDate": null,
|
||||
"HireDate": null,
|
||||
"Address": null,
|
||||
"City": null,
|
||||
"State": null,
|
||||
"Country": null,
|
||||
"PostalCode": null,
|
||||
"Phone": null,
|
||||
"Fax": null,
|
||||
"Email": null,
|
||||
"Manager": null
|
||||
},
|
||||
{
|
||||
"EmployeeId": 2,
|
||||
"LastName": "Edwards",
|
||||
"FirstName": "Nancy",
|
||||
"Title": null,
|
||||
"ReportsTo": null,
|
||||
"BirthDate": null,
|
||||
"HireDate": null,
|
||||
"Address": null,
|
||||
"City": null,
|
||||
"State": null,
|
||||
"Country": null,
|
||||
"PostalCode": null,
|
||||
"Phone": null,
|
||||
"Fax": null,
|
||||
"Email": null,
|
||||
"Manager": {
|
||||
"EmployeeId": 1,
|
||||
"LastName": "Adams",
|
||||
"FirstName": "Andrew",
|
||||
"Title": null,
|
||||
"ReportsTo": null,
|
||||
"BirthDate": null,
|
||||
"HireDate": null,
|
||||
"Address": null,
|
||||
"City": null,
|
||||
"State": null,
|
||||
"Country": null,
|
||||
"PostalCode": null,
|
||||
"Phone": null,
|
||||
"Fax": null,
|
||||
"Email": null
|
||||
}
|
||||
}
|
||||
]
|
||||
`)
|
||||
|
||||
}
|
||||
|
||||
func TestUnionForQuotedNames(t *testing.T) {
|
||||
|
||||
stmt := UNION_ALL(
|
||||
Album.SELECT(Album.AllColumns).WHERE(Album.AlbumId.EQ(Int(1))),
|
||||
Album.SELECT(Album.AllColumns).WHERE(Album.AlbumId.EQ(Int(2))),
|
||||
).
|
||||
ORDER_BY(Album.AlbumId)
|
||||
|
||||
//fmt.Println(stmt.DebugSql())
|
||||
testutils.AssertDebugStatementSql(t, stmt, `
|
||||
(
|
||||
(
|
||||
SELECT "Album"."AlbumId" AS "Album.AlbumId",
|
||||
"Album"."Title" AS "Album.Title",
|
||||
"Album"."ArtistId" AS "Album.ArtistId"
|
||||
FROM chinook."Album"
|
||||
WHERE "Album"."AlbumId" = 1
|
||||
)
|
||||
UNION ALL
|
||||
(
|
||||
SELECT "Album"."AlbumId" AS "Album.AlbumId",
|
||||
"Album"."Title" AS "Album.Title",
|
||||
"Album"."ArtistId" AS "Album.ArtistId"
|
||||
FROM chinook."Album"
|
||||
WHERE "Album"."AlbumId" = 2
|
||||
)
|
||||
)
|
||||
ORDER BY "Album.AlbumId";
|
||||
`, int64(1), int64(2))
|
||||
|
||||
dest := []model.Album{}
|
||||
|
||||
err := stmt.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Equal(t, len(dest), 2)
|
||||
assert.DeepEqual(t, dest[0], album1)
|
||||
assert.DeepEqual(t, dest[1], album2)
|
||||
}
|
||||
|
||||
func TestQueryWithContext(t *testing.T) {
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
|
||||
defer cancel()
|
||||
|
||||
dest := []model.Album{}
|
||||
|
||||
err := Album.
|
||||
CROSS_JOIN(Track).
|
||||
CROSS_JOIN(InvoiceLine).
|
||||
SELECT(Album.AllColumns, Track.AllColumns, InvoiceLine.AllColumns).
|
||||
QueryContext(ctx, db, &dest)
|
||||
|
||||
assert.Error(t, err, "context deadline exceeded")
|
||||
}
|
||||
|
||||
func TestExecWithContext(t *testing.T) {
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
|
||||
defer cancel()
|
||||
|
||||
_, err := Album.
|
||||
CROSS_JOIN(Track).
|
||||
CROSS_JOIN(InvoiceLine).
|
||||
SELECT(Album.AllColumns, Track.AllColumns, InvoiceLine.AllColumns).
|
||||
ExecContext(ctx, db)
|
||||
|
||||
assert.Error(t, err, "pq: canceling statement due to user request")
|
||||
}
|
||||
|
||||
func TestSubQueriesForQuotedNames(t *testing.T) {
|
||||
first10Artist := Artist.
|
||||
SELECT(Artist.AllColumns).
|
||||
ORDER_BY(Artist.ArtistId).
|
||||
LIMIT(10).
|
||||
AsTable("first10Artist")
|
||||
|
||||
artistID := Artist.ArtistId.From(first10Artist)
|
||||
|
||||
first10Albums := Album.
|
||||
SELECT(Album.AllColumns).
|
||||
ORDER_BY(Album.AlbumId).
|
||||
LIMIT(10).
|
||||
AsTable("first10Albums")
|
||||
|
||||
albumArtistID := Album.ArtistId.From(first10Albums)
|
||||
|
||||
stmt := first10Artist.
|
||||
INNER_JOIN(first10Albums, artistID.EQ(albumArtistID)).
|
||||
SELECT(first10Artist.AllColumns(), first10Albums.AllColumns()).
|
||||
ORDER_BY(artistID)
|
||||
|
||||
testutils.AssertDebugStatementSql(t, stmt, `
|
||||
SELECT "first10Artist"."Artist.ArtistId" AS "Artist.ArtistId",
|
||||
"first10Artist"."Artist.Name" AS "Artist.Name",
|
||||
"first10Albums"."Album.AlbumId" AS "Album.AlbumId",
|
||||
"first10Albums"."Album.Title" AS "Album.Title",
|
||||
"first10Albums"."Album.ArtistId" AS "Album.ArtistId"
|
||||
FROM (
|
||||
SELECT "Artist"."ArtistId" AS "Artist.ArtistId",
|
||||
"Artist"."Name" AS "Artist.Name"
|
||||
FROM chinook."Artist"
|
||||
ORDER BY "Artist"."ArtistId"
|
||||
LIMIT 10
|
||||
) AS "first10Artist"
|
||||
INNER JOIN (
|
||||
SELECT "Album"."AlbumId" AS "Album.AlbumId",
|
||||
"Album"."Title" AS "Album.Title",
|
||||
"Album"."ArtistId" AS "Album.ArtistId"
|
||||
FROM chinook."Album"
|
||||
ORDER BY "Album"."AlbumId"
|
||||
LIMIT 10
|
||||
) AS "first10Albums" ON ("first10Artist"."Artist.ArtistId" = "first10Albums"."Album.ArtistId")
|
||||
ORDER BY "first10Artist"."Artist.ArtistId";
|
||||
`, int64(10), int64(10))
|
||||
|
||||
var dest []struct {
|
||||
model.Artist
|
||||
|
||||
Album []model.Album
|
||||
}
|
||||
|
||||
err := stmt.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
|
||||
//spew.Dump(dest)
|
||||
}
|
||||
|
||||
var album1 = model.Album{
|
||||
AlbumId: 1,
|
||||
Title: "For Those About To Rock We Salute You",
|
||||
ArtistId: 1,
|
||||
}
|
||||
|
||||
var album2 = model.Album{
|
||||
AlbumId: 2,
|
||||
Title: "Balls to the Wall",
|
||||
ArtistId: 2,
|
||||
}
|
||||
|
||||
var album347 = model.Album{
|
||||
AlbumId: 347,
|
||||
Title: "Koyaanisqatsi (Soundtrack from the Motion Picture)",
|
||||
ArtistId: 275,
|
||||
}
|
||||
100
tests/postgres/delete_test.go
Normal file
100
tests/postgres/delete_test.go
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
. "github.com/go-jet/jet"
|
||||
"github.com/go-jet/jet/internal/testutils"
|
||||
"github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/model"
|
||||
. "github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/table"
|
||||
"gotest.tools/assert"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestDeleteWithWhere(t *testing.T) {
|
||||
initForDeleteTest(t)
|
||||
|
||||
var expectedSQL = `
|
||||
DELETE FROM test_sample.link
|
||||
WHERE link.name IN ('Gmail', 'Outlook');
|
||||
`
|
||||
deleteStmt := Link.
|
||||
DELETE().
|
||||
WHERE(Link.Name.IN(String("Gmail"), String("Outlook")))
|
||||
|
||||
testutils.AssertDebugStatementSql(t, deleteStmt, expectedSQL, "Gmail", "Outlook")
|
||||
assertExec(t, deleteStmt, 2)
|
||||
}
|
||||
|
||||
func TestDeleteWithWhereAndReturning(t *testing.T) {
|
||||
initForDeleteTest(t)
|
||||
|
||||
var expectedSQL = `
|
||||
DELETE FROM test_sample.link
|
||||
WHERE link.name IN ('Gmail', 'Outlook')
|
||||
RETURNING link.id AS "link.id",
|
||||
link.url AS "link.url",
|
||||
link.name AS "link.name",
|
||||
link.description AS "link.description";
|
||||
`
|
||||
deleteStmt := Link.
|
||||
DELETE().
|
||||
WHERE(Link.Name.IN(String("Gmail"), String("Outlook"))).
|
||||
RETURNING(Link.AllColumns)
|
||||
|
||||
testutils.AssertDebugStatementSql(t, deleteStmt, expectedSQL, "Gmail", "Outlook")
|
||||
|
||||
dest := []model.Link{}
|
||||
|
||||
err := deleteStmt.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Equal(t, len(dest), 2)
|
||||
assert.DeepEqual(t, dest[0].Name, "Gmail")
|
||||
assert.DeepEqual(t, dest[1].Name, "Outlook")
|
||||
}
|
||||
|
||||
func initForDeleteTest(t *testing.T) {
|
||||
cleanUpLinkTable(t)
|
||||
stmt := Link.INSERT(Link.URL, Link.Name, Link.Description).
|
||||
VALUES("www.gmail.com", "Gmail", "Email service developed by Google").
|
||||
VALUES("www.outlook.live.com", "Outlook", "Email service developed by Microsoft")
|
||||
|
||||
assertExec(t, stmt, 2)
|
||||
}
|
||||
|
||||
func TestDeleteQueryContext(t *testing.T) {
|
||||
initForDeleteTest(t)
|
||||
|
||||
deleteStmt := Link.
|
||||
DELETE().
|
||||
WHERE(Link.Name.IN(String("Gmail"), String("Outlook")))
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Microsecond)
|
||||
defer cancel()
|
||||
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
dest := []model.Link{}
|
||||
err := deleteStmt.QueryContext(ctx, db, &dest)
|
||||
|
||||
assert.Error(t, err, "context deadline exceeded")
|
||||
}
|
||||
|
||||
func TestDeleteExecContext(t *testing.T) {
|
||||
initForDeleteTest(t)
|
||||
|
||||
deleteStmt := Link.
|
||||
DELETE().
|
||||
WHERE(Link.Name.IN(String("Gmail"), String("Outlook")))
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Microsecond)
|
||||
defer cancel()
|
||||
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
_, err := deleteStmt.ExecContext(ctx, db)
|
||||
|
||||
assert.Error(t, err, "context deadline exceeded")
|
||||
}
|
||||
284
tests/postgres/insert_test.go
Normal file
284
tests/postgres/insert_test.go
Normal file
|
|
@ -0,0 +1,284 @@
|
|||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
. "github.com/go-jet/jet"
|
||||
"github.com/go-jet/jet/internal/testutils"
|
||||
"github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/model"
|
||||
. "github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/table"
|
||||
"gotest.tools/assert"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestInsertValues(t *testing.T) {
|
||||
cleanUpLinkTable(t)
|
||||
|
||||
var expectedSQL = `
|
||||
INSERT INTO test_sample.link (id, url, name, description) VALUES
|
||||
(100, 'http://www.postgresqltutorial.com', 'PostgreSQL Tutorial', DEFAULT),
|
||||
(101, 'http://www.google.com', 'Google', DEFAULT),
|
||||
(102, 'http://www.yahoo.com', 'Yahoo', NULL)
|
||||
RETURNING link.id AS "link.id",
|
||||
link.url AS "link.url",
|
||||
link.name AS "link.name",
|
||||
link.description AS "link.description";
|
||||
`
|
||||
|
||||
insertQuery := Link.INSERT(Link.ID, Link.URL, Link.Name, Link.Description).
|
||||
VALUES(100, "http://www.postgresqltutorial.com", "PostgreSQL Tutorial", DEFAULT).
|
||||
VALUES(101, "http://www.google.com", "Google", DEFAULT).
|
||||
VALUES(102, "http://www.yahoo.com", "Yahoo", nil).
|
||||
RETURNING(Link.AllColumns)
|
||||
|
||||
testutils.AssertDebugStatementSql(t, insertQuery, expectedSQL,
|
||||
100, "http://www.postgresqltutorial.com", "PostgreSQL Tutorial",
|
||||
101, "http://www.google.com", "Google",
|
||||
102, "http://www.yahoo.com", "Yahoo", nil)
|
||||
|
||||
insertedLinks := []model.Link{}
|
||||
|
||||
err := insertQuery.Query(db, &insertedLinks)
|
||||
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Equal(t, len(insertedLinks), 3)
|
||||
|
||||
assert.DeepEqual(t, insertedLinks[0], model.Link{
|
||||
ID: 100,
|
||||
URL: "http://www.postgresqltutorial.com",
|
||||
Name: "PostgreSQL Tutorial",
|
||||
})
|
||||
|
||||
assert.DeepEqual(t, insertedLinks[1], model.Link{
|
||||
ID: 101,
|
||||
URL: "http://www.google.com",
|
||||
Name: "Google",
|
||||
})
|
||||
|
||||
assert.DeepEqual(t, insertedLinks[2], model.Link{
|
||||
ID: 102,
|
||||
URL: "http://www.yahoo.com",
|
||||
Name: "Yahoo",
|
||||
})
|
||||
|
||||
allLinks := []model.Link{}
|
||||
|
||||
err = Link.SELECT(Link.AllColumns).
|
||||
WHERE(Link.ID.GT_EQ(Int(100))).
|
||||
ORDER_BY(Link.ID).
|
||||
Query(db, &allLinks)
|
||||
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.DeepEqual(t, insertedLinks, allLinks)
|
||||
}
|
||||
|
||||
func TestInsertEmptyColumnList(t *testing.T) {
|
||||
cleanUpLinkTable(t)
|
||||
|
||||
expectedSQL := `
|
||||
INSERT INTO test_sample.link VALUES
|
||||
(100, 'http://www.postgresqltutorial.com', 'PostgreSQL Tutorial', DEFAULT);
|
||||
`
|
||||
|
||||
stmt := Link.INSERT().
|
||||
VALUES(100, "http://www.postgresqltutorial.com", "PostgreSQL Tutorial", DEFAULT)
|
||||
|
||||
testutils.AssertDebugStatementSql(t, stmt, expectedSQL,
|
||||
100, "http://www.postgresqltutorial.com", "PostgreSQL Tutorial")
|
||||
|
||||
assertExec(t, stmt, 1)
|
||||
}
|
||||
|
||||
func TestInsertModelObject(t *testing.T) {
|
||||
cleanUpLinkTable(t)
|
||||
var expectedSQL = `
|
||||
INSERT INTO test_sample.link (url, name) VALUES
|
||||
('http://www.duckduckgo.com', 'Duck Duck go');
|
||||
`
|
||||
|
||||
linkData := model.Link{
|
||||
URL: "http://www.duckduckgo.com",
|
||||
Name: "Duck Duck go",
|
||||
}
|
||||
|
||||
query := Link.
|
||||
INSERT(Link.URL, Link.Name).
|
||||
MODEL(linkData)
|
||||
|
||||
testutils.AssertDebugStatementSql(t, query, expectedSQL, "http://www.duckduckgo.com", "Duck Duck go")
|
||||
|
||||
assertExec(t, query, 1)
|
||||
}
|
||||
|
||||
func TestInsertModelObjectEmptyColumnList(t *testing.T) {
|
||||
cleanUpLinkTable(t)
|
||||
var expectedSQL = `
|
||||
INSERT INTO test_sample.link VALUES
|
||||
(1000, 'http://www.duckduckgo.com', 'Duck Duck go', NULL);
|
||||
`
|
||||
|
||||
linkData := model.Link{
|
||||
ID: 1000,
|
||||
URL: "http://www.duckduckgo.com",
|
||||
Name: "Duck Duck go",
|
||||
}
|
||||
|
||||
query := Link.
|
||||
INSERT().
|
||||
MODEL(linkData)
|
||||
|
||||
testutils.AssertDebugStatementSql(t, query, expectedSQL, int32(1000), "http://www.duckduckgo.com", "Duck Duck go", nil)
|
||||
|
||||
assertExec(t, query, 1)
|
||||
}
|
||||
|
||||
func TestInsertModelsObject(t *testing.T) {
|
||||
expectedSQL := `
|
||||
INSERT INTO test_sample.link (url, name) VALUES
|
||||
('http://www.postgresqltutorial.com', 'PostgreSQL Tutorial'),
|
||||
('http://www.google.com', 'Google'),
|
||||
('http://www.yahoo.com', 'Yahoo');
|
||||
`
|
||||
|
||||
tutorial := model.Link{
|
||||
URL: "http://www.postgresqltutorial.com",
|
||||
Name: "PostgreSQL Tutorial",
|
||||
}
|
||||
|
||||
google := model.Link{
|
||||
URL: "http://www.google.com",
|
||||
Name: "Google",
|
||||
}
|
||||
|
||||
yahoo := model.Link{
|
||||
URL: "http://www.yahoo.com",
|
||||
Name: "Yahoo",
|
||||
}
|
||||
|
||||
stmt := Link.
|
||||
INSERT(Link.URL, Link.Name).
|
||||
MODELS([]model.Link{tutorial, google, yahoo})
|
||||
|
||||
testutils.AssertDebugStatementSql(t, stmt, expectedSQL,
|
||||
"http://www.postgresqltutorial.com", "PostgreSQL Tutorial",
|
||||
"http://www.google.com", "Google",
|
||||
"http://www.yahoo.com", "Yahoo")
|
||||
|
||||
assertExec(t, stmt, 3)
|
||||
}
|
||||
|
||||
func TestInsertUsingMutableColumns(t *testing.T) {
|
||||
var expectedSQL = `
|
||||
INSERT INTO test_sample.link (url, name, description) VALUES
|
||||
('http://www.postgresqltutorial.com', 'PostgreSQL Tutorial', DEFAULT),
|
||||
('http://www.google.com', 'Google', NULL),
|
||||
('http://www.google.com', 'Google', NULL),
|
||||
('http://www.yahoo.com', 'Yahoo', NULL);
|
||||
`
|
||||
|
||||
google := model.Link{
|
||||
URL: "http://www.google.com",
|
||||
Name: "Google",
|
||||
}
|
||||
|
||||
yahoo := model.Link{
|
||||
URL: "http://www.yahoo.com",
|
||||
Name: "Yahoo",
|
||||
}
|
||||
|
||||
stmt := Link.
|
||||
INSERT(Link.MutableColumns).
|
||||
VALUES("http://www.postgresqltutorial.com", "PostgreSQL Tutorial", DEFAULT).
|
||||
MODEL(google).
|
||||
MODELS([]model.Link{google, yahoo})
|
||||
|
||||
testutils.AssertDebugStatementSql(t, stmt, expectedSQL,
|
||||
"http://www.postgresqltutorial.com", "PostgreSQL Tutorial",
|
||||
"http://www.google.com", "Google", nil,
|
||||
"http://www.google.com", "Google", nil,
|
||||
"http://www.yahoo.com", "Yahoo", nil)
|
||||
|
||||
assertExec(t, stmt, 4)
|
||||
}
|
||||
|
||||
func TestInsertQuery(t *testing.T) {
|
||||
_, err := Link.DELETE().
|
||||
WHERE(Link.ID.NOT_EQ(Int(0)).AND(Link.Name.EQ(String("Youtube")))).
|
||||
Exec(db)
|
||||
assert.NilError(t, err)
|
||||
|
||||
var expectedSQL = `
|
||||
INSERT INTO test_sample.link (url, name) (
|
||||
SELECT link.url AS "link.url",
|
||||
link.name AS "link.name"
|
||||
FROM test_sample.link
|
||||
WHERE link.id = 0
|
||||
)
|
||||
RETURNING link.id AS "link.id",
|
||||
link.url AS "link.url",
|
||||
link.name AS "link.name",
|
||||
link.description AS "link.description";
|
||||
`
|
||||
|
||||
query := Link.
|
||||
INSERT(Link.URL, Link.Name).
|
||||
QUERY(
|
||||
SELECT(Link.URL, Link.Name).
|
||||
FROM(Link).
|
||||
WHERE(Link.ID.EQ(Int(0))),
|
||||
).
|
||||
RETURNING(Link.AllColumns)
|
||||
|
||||
testutils.AssertDebugStatementSql(t, query, expectedSQL, int64(0))
|
||||
|
||||
dest := []model.Link{}
|
||||
|
||||
err = query.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
|
||||
youtubeLinks := []model.Link{}
|
||||
err = Link.
|
||||
SELECT(Link.AllColumns).
|
||||
WHERE(Link.Name.EQ(String("Youtube"))).
|
||||
Query(db, &youtubeLinks)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(youtubeLinks), 2)
|
||||
}
|
||||
|
||||
func TestInsertWithQueryContext(t *testing.T) {
|
||||
cleanUpLinkTable(t)
|
||||
|
||||
stmt := Link.INSERT().
|
||||
VALUES(1100, "http://www.postgresqltutorial.com", "PostgreSQL Tutorial", DEFAULT).
|
||||
RETURNING(Link.AllColumns)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Microsecond)
|
||||
defer cancel()
|
||||
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
dest := []model.Link{}
|
||||
err := stmt.QueryContext(ctx, db, &dest)
|
||||
|
||||
assert.Error(t, err, "context deadline exceeded")
|
||||
}
|
||||
|
||||
func TestInsertWithExecContext(t *testing.T) {
|
||||
cleanUpLinkTable(t)
|
||||
|
||||
stmt := Link.INSERT().
|
||||
VALUES(100, "http://www.postgresqltutorial.com", "PostgreSQL Tutorial", DEFAULT)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Microsecond)
|
||||
defer cancel()
|
||||
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
_, err := stmt.ExecContext(ctx, db)
|
||||
|
||||
assert.Error(t, err, "context deadline exceeded")
|
||||
}
|
||||
74
tests/postgres/lock_test.go
Normal file
74
tests/postgres/lock_test.go
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/go-jet/jet/internal/testutils"
|
||||
"gotest.tools/assert"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
. "github.com/go-jet/jet"
|
||||
. "github.com/go-jet/jet/tests/.gentestdata/jetdb/dvds/table"
|
||||
)
|
||||
|
||||
func TestLockTable(t *testing.T) {
|
||||
expectedSQL := `
|
||||
LOCK TABLE dvds.address IN`
|
||||
|
||||
var testData = []TableLockMode{
|
||||
LOCK_ACCESS_SHARE,
|
||||
LOCK_ROW_SHARE,
|
||||
LOCK_ROW_EXCLUSIVE,
|
||||
LOCK_SHARE_UPDATE_EXCLUSIVE,
|
||||
LOCK_SHARE,
|
||||
LOCK_SHARE_ROW_EXCLUSIVE,
|
||||
LOCK_EXCLUSIVE,
|
||||
LOCK_ACCESS_EXCLUSIVE,
|
||||
}
|
||||
|
||||
for _, lockMode := range testData {
|
||||
query := Address.LOCK().IN(lockMode)
|
||||
|
||||
testutils.AssertDebugStatementSql(t, query, expectedSQL+" "+string(lockMode)+" MODE;\n")
|
||||
|
||||
tx, _ := db.Begin()
|
||||
|
||||
_, err := query.Exec(tx)
|
||||
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = tx.Rollback()
|
||||
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
for _, lockMode := range testData {
|
||||
query := Address.LOCK().IN(lockMode).NOWAIT()
|
||||
|
||||
testutils.AssertDebugStatementSql(t, query, expectedSQL+" "+string(lockMode)+" MODE NOWAIT;\n")
|
||||
|
||||
tx, _ := db.Begin()
|
||||
|
||||
_, err := query.Exec(tx)
|
||||
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = tx.Rollback()
|
||||
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLockExecContext(t *testing.T) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Microsecond)
|
||||
defer cancel()
|
||||
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
tx, _ := db.Begin()
|
||||
defer tx.Rollback()
|
||||
|
||||
_, err := Address.LOCK().IN(LOCK_ACCESS_SHARE).ExecContext(ctx, tx)
|
||||
|
||||
assert.Error(t, err, "context deadline exceeded")
|
||||
}
|
||||
251
tests/postgres/main_test.go
Normal file
251
tests/postgres/main_test.go
Normal file
|
|
@ -0,0 +1,251 @@
|
|||
package postgres
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"database/sql"
|
||||
"github.com/go-jet/jet/generator/postgres"
|
||||
"github.com/go-jet/jet/tests/.gentestdata/jetdb/dvds/model"
|
||||
"github.com/go-jet/jet/tests/dbconfig"
|
||||
_ "github.com/lib/pq"
|
||||
"github.com/pkg/profile"
|
||||
"gotest.tools/assert"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var db *sql.DB
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
defer profile.Start().Stop()
|
||||
|
||||
var err error
|
||||
db, err = sql.Open("postgres", dbconfig.PostgresConnectString)
|
||||
if err != nil {
|
||||
panic("Failed to connect to test db")
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
ret := m.Run()
|
||||
|
||||
os.Exit(ret)
|
||||
}
|
||||
|
||||
func TestGeneratedModel(t *testing.T) {
|
||||
|
||||
actor := model.Actor{}
|
||||
|
||||
assert.Equal(t, reflect.TypeOf(actor.ActorID).String(), "int32")
|
||||
actorIDField, ok := reflect.TypeOf(actor).FieldByName("ActorID")
|
||||
assert.Assert(t, ok)
|
||||
assert.Equal(t, actorIDField.Tag.Get("sql"), "primary_key")
|
||||
assert.Equal(t, reflect.TypeOf(actor.FirstName).String(), "string")
|
||||
assert.Equal(t, reflect.TypeOf(actor.LastName).String(), "string")
|
||||
assert.Equal(t, reflect.TypeOf(actor.LastUpdate).String(), "time.Time")
|
||||
|
||||
filmActor := model.FilmActor{}
|
||||
|
||||
assert.Equal(t, reflect.TypeOf(filmActor.FilmID).String(), "int16")
|
||||
filmIDField, ok := reflect.TypeOf(filmActor).FieldByName("FilmID")
|
||||
assert.Assert(t, ok)
|
||||
assert.Equal(t, filmIDField.Tag.Get("sql"), "primary_key")
|
||||
|
||||
assert.Equal(t, reflect.TypeOf(filmActor.ActorID).String(), "int16")
|
||||
actorIDField, ok = reflect.TypeOf(filmActor).FieldByName("ActorID")
|
||||
assert.Assert(t, ok)
|
||||
assert.Equal(t, filmIDField.Tag.Get("sql"), "primary_key")
|
||||
|
||||
staff := model.Staff{}
|
||||
|
||||
assert.Equal(t, reflect.TypeOf(staff.Email).String(), "*string")
|
||||
assert.Equal(t, reflect.TypeOf(staff.Picture).String(), "*[]uint8")
|
||||
}
|
||||
|
||||
const genTestDir2 = "./.gentestdata2"
|
||||
|
||||
func TestCmdGenerator(t *testing.T) {
|
||||
err := os.RemoveAll(genTestDir2)
|
||||
assert.NilError(t, err)
|
||||
|
||||
cmd := exec.Command("jet", "-dbname=jetdb", "-host=localhost", "-port=5432",
|
||||
"-user=jet", "-password=jet", "-schema=dvds", "-path="+genTestDir2)
|
||||
|
||||
err = cmd.Run()
|
||||
assert.NilError(t, err)
|
||||
|
||||
assertGeneratedFiles(t)
|
||||
|
||||
err = os.RemoveAll(genTestDir2)
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
func TestGenerator(t *testing.T) {
|
||||
|
||||
err := os.RemoveAll(genTestDir2)
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = postgres.Generate(genTestDir2, postgres.DBConnection{
|
||||
Host: dbconfig.Host,
|
||||
Port: dbconfig.Port,
|
||||
User: dbconfig.User,
|
||||
Password: dbconfig.Password,
|
||||
SslMode: "disable",
|
||||
Params: "",
|
||||
|
||||
DBName: dbconfig.DBName,
|
||||
SchemaName: "dvds",
|
||||
})
|
||||
|
||||
assert.NilError(t, err)
|
||||
|
||||
assertGeneratedFiles(t)
|
||||
|
||||
err = os.RemoveAll(genTestDir2)
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
func assertGeneratedFiles(t *testing.T) {
|
||||
// Table SQL Builder files
|
||||
tableSQLBuilderFiles, err := ioutil.ReadDir("./.gentestdata2/jetdb/dvds/table")
|
||||
assert.NilError(t, err)
|
||||
|
||||
assertFileNameEqual(t, tableSQLBuilderFiles, "actor.go", "address.go", "category.go", "city.go", "country.go",
|
||||
"customer.go", "film.go", "film_actor.go", "film_category.go", "inventory.go", "language.go",
|
||||
"payment.go", "rental.go", "staff.go", "store.go")
|
||||
|
||||
assertFileContent(t, "./.gentestdata2/jetdb/dvds/table/actor.go", "\npackage table", actorSQLBuilderFile)
|
||||
|
||||
// Enums SQL Builder files
|
||||
enumFiles, err := ioutil.ReadDir("./.gentestdata2/jetdb/dvds/enum")
|
||||
assert.NilError(t, err)
|
||||
|
||||
assertFileNameEqual(t, enumFiles, "mpaa_rating.go")
|
||||
assertFileContent(t, "./.gentestdata2/jetdb/dvds/enum/mpaa_rating.go", "\npackage enum", mpaaRatingEnumFile)
|
||||
|
||||
// Model files
|
||||
modelFiles, err := ioutil.ReadDir("./.gentestdata2/jetdb/dvds/model")
|
||||
assert.NilError(t, err)
|
||||
|
||||
assertFileNameEqual(t, modelFiles, "actor.go", "address.go", "category.go", "city.go", "country.go",
|
||||
"customer.go", "film.go", "film_actor.go", "film_category.go", "inventory.go", "language.go",
|
||||
"payment.go", "rental.go", "staff.go", "store.go", "mpaa_rating.go")
|
||||
|
||||
assertFileContent(t, "./.gentestdata2/jetdb/dvds/model/actor.go", "\npackage model", actorModelFile)
|
||||
}
|
||||
|
||||
func assertFileContent(t *testing.T, filePath string, contentBegin string, expectedContent string) {
|
||||
enumFileData, err := ioutil.ReadFile(filePath)
|
||||
|
||||
assert.NilError(t, err)
|
||||
|
||||
beginIndex := bytes.Index(enumFileData, []byte(contentBegin))
|
||||
|
||||
//fmt.Println("-"+string(enumFileData[beginIndex:])+"-")
|
||||
|
||||
assert.DeepEqual(t, string(enumFileData[beginIndex:]), expectedContent)
|
||||
}
|
||||
|
||||
func assertFileNameEqual(t *testing.T, fileInfos []os.FileInfo, fileNames ...string) {
|
||||
|
||||
fileNamesMap := map[string]bool{}
|
||||
|
||||
for _, fileInfo := range fileInfos {
|
||||
fileNamesMap[fileInfo.Name()] = true
|
||||
}
|
||||
|
||||
for _, fileName := range fileNames {
|
||||
assert.Assert(t, fileNamesMap[fileName], fileName+" does not exist.")
|
||||
}
|
||||
}
|
||||
|
||||
var mpaaRatingEnumFile = `
|
||||
package enum
|
||||
|
||||
import "github.com/go-jet/jet"
|
||||
|
||||
var MpaaRating = &struct {
|
||||
G jet.StringExpression
|
||||
Pg jet.StringExpression
|
||||
Pg13 jet.StringExpression
|
||||
R jet.StringExpression
|
||||
Nc17 jet.StringExpression
|
||||
}{
|
||||
G: jet.NewEnumValue("G"),
|
||||
Pg: jet.NewEnumValue("PG"),
|
||||
Pg13: jet.NewEnumValue("PG-13"),
|
||||
R: jet.NewEnumValue("R"),
|
||||
Nc17: jet.NewEnumValue("NC-17"),
|
||||
}
|
||||
`
|
||||
|
||||
var actorSQLBuilderFile = `
|
||||
package table
|
||||
|
||||
import (
|
||||
"github.com/go-jet/jet"
|
||||
"github.com/go-jet/jet/postgres"
|
||||
)
|
||||
|
||||
var Actor = newActorTable()
|
||||
|
||||
type ActorTable struct {
|
||||
jet.Table
|
||||
|
||||
//Columns
|
||||
ActorID postgres.ColumnInteger
|
||||
FirstName postgres.ColumnString
|
||||
LastName postgres.ColumnString
|
||||
LastUpdate postgres.ColumnTimestamp
|
||||
|
||||
AllColumns jet.ColumnList
|
||||
MutableColumns jet.ColumnList
|
||||
}
|
||||
|
||||
// creates new ActorTable with assigned alias
|
||||
func (a *ActorTable) AS(alias string) *ActorTable {
|
||||
aliasTable := newActorTable()
|
||||
|
||||
aliasTable.Table.AS(alias)
|
||||
|
||||
return aliasTable
|
||||
}
|
||||
|
||||
func newActorTable() *ActorTable {
|
||||
var (
|
||||
ActorIDColumn = postgres.IntegerColumn("actor_id")
|
||||
FirstNameColumn = postgres.StringColumn("first_name")
|
||||
LastNameColumn = postgres.StringColumn("last_name")
|
||||
LastUpdateColumn = postgres.TimestampColumn("last_update")
|
||||
)
|
||||
|
||||
return &ActorTable{
|
||||
Table: jet.NewTable(jet.PostgreSQL, "dvds", "actor", ActorIDColumn, FirstNameColumn, LastNameColumn, LastUpdateColumn),
|
||||
|
||||
//Columns
|
||||
ActorID: ActorIDColumn,
|
||||
FirstName: FirstNameColumn,
|
||||
LastName: LastNameColumn,
|
||||
LastUpdate: LastUpdateColumn,
|
||||
|
||||
AllColumns: jet.ColumnList{ActorIDColumn, FirstNameColumn, LastNameColumn, LastUpdateColumn},
|
||||
MutableColumns: jet.ColumnList{FirstNameColumn, LastNameColumn, LastUpdateColumn},
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
var actorModelFile = `
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type Actor struct {
|
||||
ActorID int32 ` + "`sql:\"primary_key\"`" + `
|
||||
FirstName string
|
||||
LastName string
|
||||
LastUpdate time.Time
|
||||
}
|
||||
`
|
||||
66
tests/postgres/northwind_test.go
Normal file
66
tests/postgres/northwind_test.go
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
package postgres
|
||||
|
||||
import (
|
||||
"github.com/go-jet/jet/internal/testutils"
|
||||
"github.com/go-jet/jet/tests/.gentestdata/jetdb/northwind/model"
|
||||
. "github.com/go-jet/jet/tests/.gentestdata/jetdb/northwind/table"
|
||||
"gotest.tools/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNorthwindJoinEverything(t *testing.T) {
|
||||
|
||||
stmt := Customers.
|
||||
LEFT_JOIN(CustomerCustomerDemo, Customers.CustomerID.EQ(CustomerCustomerDemo.CustomerID)).
|
||||
LEFT_JOIN(CustomerDemographics, CustomerCustomerDemo.CustomerTypeID.EQ(CustomerDemographics.CustomerTypeID)).
|
||||
LEFT_JOIN(Orders, Orders.CustomerID.EQ(Customers.CustomerID)).
|
||||
LEFT_JOIN(Shippers, Orders.ShipVia.EQ(Shippers.ShipperID)).
|
||||
LEFT_JOIN(OrderDetails, Orders.OrderID.EQ(OrderDetails.OrderID)).
|
||||
LEFT_JOIN(Products, OrderDetails.ProductID.EQ(Products.ProductID)).
|
||||
LEFT_JOIN(Categories, Products.CategoryID.EQ(Categories.CategoryID)).
|
||||
LEFT_JOIN(Suppliers, Products.SupplierID.EQ(Suppliers.SupplierID)).
|
||||
LEFT_JOIN(Employees, Orders.EmployeeID.EQ(Employees.EmployeeID)).
|
||||
LEFT_JOIN(EmployeeTerritories, EmployeeTerritories.EmployeeID.EQ(Employees.EmployeeID)).
|
||||
LEFT_JOIN(Territories, EmployeeTerritories.TerritoryID.EQ(Territories.TerritoryID)).
|
||||
LEFT_JOIN(Region, Territories.RegionID.EQ(Region.RegionID)).
|
||||
SELECT(
|
||||
Customers.AllColumns,
|
||||
CustomerDemographics.AllColumns,
|
||||
Orders.AllColumns,
|
||||
Shippers.AllColumns,
|
||||
OrderDetails.AllColumns,
|
||||
Products.AllColumns,
|
||||
Categories.AllColumns,
|
||||
Suppliers.AllColumns,
|
||||
).
|
||||
ORDER_BY(Customers.CustomerID, Orders.OrderID, Products.ProductID)
|
||||
|
||||
var dest []struct {
|
||||
model.Customers
|
||||
|
||||
Demographics model.CustomerDemographics
|
||||
|
||||
Orders []struct {
|
||||
model.Orders
|
||||
|
||||
Shipper model.Shippers
|
||||
|
||||
Details struct {
|
||||
model.OrderDetails
|
||||
|
||||
Products []struct {
|
||||
model.Products
|
||||
|
||||
Category model.Categories
|
||||
Supplier model.Suppliers
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err := stmt.Query(db, &dest)
|
||||
assert.NilError(t, err)
|
||||
|
||||
//jsonSave("./testdata/northwind-all.json", dest)
|
||||
testutils.AssertJSONFile(t, "./postgres/testdata/northwind-all.json", dest)
|
||||
}
|
||||
182
tests/postgres/sample_test.go
Normal file
182
tests/postgres/sample_test.go
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
package postgres
|
||||
|
||||
import (
|
||||
. "github.com/go-jet/jet"
|
||||
"github.com/go-jet/jet/internal/testutils"
|
||||
"github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/model"
|
||||
. "github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/table"
|
||||
"github.com/google/uuid"
|
||||
"gotest.tools/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestUUIDType(t *testing.T) {
|
||||
query := AllTypes.
|
||||
SELECT(AllTypes.UUID, AllTypes.UUIDPtr).
|
||||
WHERE(AllTypes.UUID.EQ(String("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11")))
|
||||
|
||||
testutils.AssertDebugStatementSql(t, query, `
|
||||
SELECT all_types.uuid AS "all_types.uuid",
|
||||
all_types.uuid_ptr AS "all_types.uuid_ptr"
|
||||
FROM test_sample.all_types
|
||||
WHERE all_types.uuid = 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11';
|
||||
`, "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11")
|
||||
|
||||
result := model.AllTypes{}
|
||||
|
||||
err := query.Query(db, &result)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, result.UUID, uuid.MustParse("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11"))
|
||||
assert.DeepEqual(t, result.UUIDPtr, UUIDPtr("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11"))
|
||||
}
|
||||
|
||||
func TestEnumType(t *testing.T) {
|
||||
query := Person.
|
||||
SELECT(Person.AllColumns)
|
||||
|
||||
testutils.AssertDebugStatementSql(t, query, `
|
||||
SELECT person.person_id AS "person.person_id",
|
||||
person.first_name AS "person.first_name",
|
||||
person.last_name AS "person.last_name",
|
||||
person."Mood" AS "person.Mood"
|
||||
FROM test_sample.person;
|
||||
`)
|
||||
|
||||
result := []model.Person{}
|
||||
|
||||
err := query.Query(db, &result)
|
||||
|
||||
assert.NilError(t, err)
|
||||
testutils.AssertJSON(t, result, `
|
||||
[
|
||||
{
|
||||
"PersonID": "b68dbff4-a87d-11e9-a7f2-98ded00c39c6",
|
||||
"FirstName": "Sad",
|
||||
"LastName": "John",
|
||||
"Mood": "sad"
|
||||
},
|
||||
{
|
||||
"PersonID": "b68dbff5-a87d-11e9-a7f2-98ded00c39c7",
|
||||
"FirstName": "Ok",
|
||||
"LastName": "John",
|
||||
"Mood": "ok"
|
||||
},
|
||||
{
|
||||
"PersonID": "b68dbff6-a87d-11e9-a7f2-98ded00c39c8",
|
||||
"FirstName": "Ok",
|
||||
"LastName": "John",
|
||||
"Mood": "ok"
|
||||
}
|
||||
]
|
||||
`)
|
||||
}
|
||||
|
||||
func TestSelecSelfJoin1(t *testing.T) {
|
||||
|
||||
var expectedSQL = `
|
||||
SELECT employee.employee_id AS "employee.employee_id",
|
||||
employee.first_name AS "employee.first_name",
|
||||
employee.last_name AS "employee.last_name",
|
||||
employee.employment_date AS "employee.employment_date",
|
||||
employee.manager_id AS "employee.manager_id",
|
||||
manager.employee_id AS "manager.employee_id",
|
||||
manager.first_name AS "manager.first_name",
|
||||
manager.last_name AS "manager.last_name",
|
||||
manager.employment_date AS "manager.employment_date",
|
||||
manager.manager_id AS "manager.manager_id"
|
||||
FROM test_sample.employee
|
||||
LEFT JOIN test_sample.employee AS manager ON (manager.employee_id = employee.manager_id)
|
||||
ORDER BY employee.employee_id;
|
||||
`
|
||||
|
||||
manager := Employee.AS("manager")
|
||||
query := Employee.
|
||||
LEFT_JOIN(manager, manager.EmployeeID.EQ(Employee.ManagerID)).
|
||||
SELECT(
|
||||
Employee.AllColumns,
|
||||
manager.AllColumns,
|
||||
).
|
||||
ORDER_BY(Employee.EmployeeID)
|
||||
|
||||
testutils.AssertDebugStatementSql(t, query, expectedSQL)
|
||||
|
||||
type Manager model.Employee
|
||||
|
||||
var dest []struct {
|
||||
model.Employee
|
||||
|
||||
Manager *Manager
|
||||
}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(dest), 8)
|
||||
assert.DeepEqual(t, dest[0].Employee, model.Employee{
|
||||
EmployeeID: 1,
|
||||
FirstName: "Windy",
|
||||
LastName: "Hays",
|
||||
EmploymentDate: TimestampWithTimeZone("1999-01-08 04:05:06.1 +0100 CET", 1),
|
||||
ManagerID: nil,
|
||||
})
|
||||
|
||||
assert.Assert(t, dest[0].Manager == nil)
|
||||
|
||||
assert.DeepEqual(t, dest[7].Employee, model.Employee{
|
||||
EmployeeID: 8,
|
||||
FirstName: "Salley",
|
||||
LastName: "Lester",
|
||||
EmploymentDate: TimestampWithTimeZone("1999-01-08 04:05:06 +0100 CET", 1),
|
||||
ManagerID: Int32Ptr(3),
|
||||
})
|
||||
}
|
||||
|
||||
func TestWierdNamesTable(t *testing.T) {
|
||||
stmt := WeirdNamesTable.SELECT(WeirdNamesTable.AllColumns)
|
||||
|
||||
testutils.AssertDebugStatementSql(t, stmt, `
|
||||
SELECT "WEIRD NAMES TABLE".weird_column_name1 AS "WEIRD NAMES TABLE.weird_column_name1",
|
||||
"WEIRD NAMES TABLE"."Weird_Column_Name2" AS "WEIRD NAMES TABLE.Weird_Column_Name2",
|
||||
"WEIRD NAMES TABLE"."wEiRd_cOluMn_nAmE3" AS "WEIRD NAMES TABLE.wEiRd_cOluMn_nAmE3",
|
||||
"WEIRD NAMES TABLE"."WeIrd_CoLuMN_Name4" AS "WEIRD NAMES TABLE.WeIrd_CoLuMN_Name4",
|
||||
"WEIRD NAMES TABLE"."WEIRD_COLUMN_NAME5" AS "WEIRD NAMES TABLE.WEIRD_COLUMN_NAME5",
|
||||
"WEIRD NAMES TABLE"."WeirdColumnName6" AS "WEIRD NAMES TABLE.WeirdColumnName6",
|
||||
"WEIRD NAMES TABLE"."weirdColumnName7" AS "WEIRD NAMES TABLE.weirdColumnName7",
|
||||
"WEIRD NAMES TABLE".weirdcolumnname8 AS "WEIRD NAMES TABLE.weirdcolumnname8",
|
||||
"WEIRD NAMES TABLE"."weird col name9" AS "WEIRD NAMES TABLE.weird col name9",
|
||||
"WEIRD NAMES TABLE"."wEiRd cOlu nAmE10" AS "WEIRD NAMES TABLE.wEiRd cOlu nAmE10",
|
||||
"WEIRD NAMES TABLE"."WEIRD COLU NAME11" AS "WEIRD NAMES TABLE.WEIRD COLU NAME11",
|
||||
"WEIRD NAMES TABLE"."Weird Colu Name12" AS "WEIRD NAMES TABLE.Weird Colu Name12",
|
||||
"WEIRD NAMES TABLE"."weird-col-name13" AS "WEIRD NAMES TABLE.weird-col-name13",
|
||||
"WEIRD NAMES TABLE"."wEiRd-cOlu-nAmE14" AS "WEIRD NAMES TABLE.wEiRd-cOlu-nAmE14",
|
||||
"WEIRD NAMES TABLE"."WEIRD-COLU-NAME15" AS "WEIRD NAMES TABLE.WEIRD-COLU-NAME15",
|
||||
"WEIRD NAMES TABLE"."Weird-Colu-Name16" AS "WEIRD NAMES TABLE.Weird-Colu-Name16"
|
||||
FROM test_sample."WEIRD NAMES TABLE";
|
||||
`)
|
||||
|
||||
dest := []model.WeirdNamesTable{}
|
||||
|
||||
err := stmt.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Equal(t, len(dest), 1)
|
||||
assert.DeepEqual(t, dest[0], model.WeirdNamesTable{
|
||||
WeirdColumnName1: "Doe",
|
||||
WeirdColumnName2: "Doe",
|
||||
WeirdColumnName3: "Doe",
|
||||
WeirdColumnName4: "Doe",
|
||||
WeirdColumnName5: "Doe",
|
||||
WeirdColumnName6: "Doe",
|
||||
WeirdColumnName7: "Doe",
|
||||
Weirdcolumnname8: StringPtr("Doe"),
|
||||
WeirdColName9: "Doe",
|
||||
WeirdColuName10: "Doe",
|
||||
WeirdColuName11: "Doe",
|
||||
WeirdColuName12: "Doe",
|
||||
WeirdColName13: "Doe",
|
||||
WeirdColuName14: "Doe",
|
||||
WeirdColuName15: "Doe",
|
||||
WeirdColuName16: "Doe",
|
||||
})
|
||||
}
|
||||
799
tests/postgres/scan_test.go
Normal file
799
tests/postgres/scan_test.go
Normal file
|
|
@ -0,0 +1,799 @@
|
|||
package postgres
|
||||
|
||||
import (
|
||||
. "github.com/go-jet/jet"
|
||||
"github.com/go-jet/jet/internal/testutils"
|
||||
"github.com/go-jet/jet/tests/.gentestdata/jetdb/dvds/model"
|
||||
. "github.com/go-jet/jet/tests/.gentestdata/jetdb/dvds/table"
|
||||
"github.com/google/uuid"
|
||||
"gotest.tools/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var query = Inventory.
|
||||
SELECT(Inventory.AllColumns).
|
||||
LIMIT(1).
|
||||
ORDER_BY(Inventory.InventoryID)
|
||||
|
||||
func TestScanToInvalidDestination(t *testing.T) {
|
||||
|
||||
t.Run("nil dest", func(t *testing.T) {
|
||||
err := query.Query(db, nil)
|
||||
|
||||
assert.Error(t, err, "jet: Destination is nil")
|
||||
})
|
||||
|
||||
t.Run("struct dest", func(t *testing.T) {
|
||||
err := query.Query(db, struct{}{})
|
||||
|
||||
assert.Error(t, err, "jet: Destination has to be a pointer to slice or pointer to struct")
|
||||
})
|
||||
|
||||
t.Run("slice dest", func(t *testing.T) {
|
||||
err := query.Query(db, []struct{}{})
|
||||
|
||||
assert.Error(t, err, "jet: Destination has to be a pointer to slice or pointer to struct")
|
||||
})
|
||||
|
||||
t.Run("slice of pointers to pointer dest", func(t *testing.T) {
|
||||
err := query.Query(db, []**struct{}{})
|
||||
|
||||
assert.Error(t, err, "jet: Destination has to be a pointer to slice or pointer to struct")
|
||||
})
|
||||
|
||||
t.Run("map dest", func(t *testing.T) {
|
||||
err := query.Query(db, []map[string]string{})
|
||||
|
||||
assert.Error(t, err, "jet: Destination has to be a pointer to slice or pointer to struct")
|
||||
})
|
||||
}
|
||||
|
||||
func TestScanToValidDestination(t *testing.T) {
|
||||
t.Run("pointer to struct", func(t *testing.T) {
|
||||
err := query.Query(db, &struct{}{})
|
||||
|
||||
assert.NilError(t, err)
|
||||
})
|
||||
|
||||
t.Run("pointer to slice", func(t *testing.T) {
|
||||
err := query.Query(db, &[]struct{}{})
|
||||
|
||||
assert.NilError(t, err)
|
||||
})
|
||||
|
||||
t.Run("pointer to slice of pointer to structs", func(t *testing.T) {
|
||||
err := query.Query(db, &[]*struct{}{})
|
||||
|
||||
assert.NilError(t, err)
|
||||
})
|
||||
|
||||
t.Run("pointer to slice of strings", func(t *testing.T) {
|
||||
err := query.Query(db, &[]int32{})
|
||||
|
||||
assert.NilError(t, err)
|
||||
})
|
||||
|
||||
t.Run("pointer to slice of strings", func(t *testing.T) {
|
||||
err := query.Query(db, &[]*int32{})
|
||||
|
||||
assert.NilError(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestScanToStruct(t *testing.T) {
|
||||
query := Inventory.
|
||||
SELECT(Inventory.AllColumns).
|
||||
ORDER_BY(Inventory.InventoryID)
|
||||
|
||||
t.Run("one struct", func(t *testing.T) {
|
||||
dest := model.Inventory{}
|
||||
err := query.LIMIT(1).Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, inventory1, dest)
|
||||
})
|
||||
|
||||
t.Run("multiple structs, just first one used", func(t *testing.T) {
|
||||
dest := model.Inventory{}
|
||||
err := query.LIMIT(10).Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, inventory1, dest)
|
||||
})
|
||||
|
||||
t.Run("one struct", func(t *testing.T) {
|
||||
dest := struct {
|
||||
model.Inventory
|
||||
}{}
|
||||
err := query.LIMIT(1).Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, inventory1, dest.Inventory)
|
||||
})
|
||||
|
||||
t.Run("one struct", func(t *testing.T) {
|
||||
dest := struct {
|
||||
*model.Inventory
|
||||
}{}
|
||||
err := query.LIMIT(1).Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, inventory1, *dest.Inventory)
|
||||
})
|
||||
|
||||
t.Run("invalid dest", func(t *testing.T) {
|
||||
dest := struct {
|
||||
Inventory **model.Inventory
|
||||
}{}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.Error(t, err, "jet: Unsupported dest type: Inventory **model.Inventory")
|
||||
})
|
||||
|
||||
t.Run("invalid dest 2", func(t *testing.T) {
|
||||
dest := struct {
|
||||
Inventory ***model.Inventory
|
||||
}{}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.Error(t, err, "jet: Unsupported dest type: Inventory ***model.Inventory")
|
||||
})
|
||||
|
||||
t.Run("custom struct", func(t *testing.T) {
|
||||
type Inventory struct {
|
||||
InventoryID *int32 `sql:"primary_key"`
|
||||
FilmID int16
|
||||
StoreID *int16
|
||||
}
|
||||
|
||||
dest := Inventory{}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Equal(t, *dest.InventoryID, int32(1))
|
||||
assert.Equal(t, dest.FilmID, int16(1))
|
||||
assert.Equal(t, *dest.StoreID, int16(1))
|
||||
})
|
||||
|
||||
t.Run("type convert int32 to int", func(t *testing.T) {
|
||||
type Inventory struct {
|
||||
InventoryID int
|
||||
FilmID string
|
||||
}
|
||||
|
||||
dest := Inventory{}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
})
|
||||
|
||||
t.Run("type mismatch scanner type", func(t *testing.T) {
|
||||
type Inventory struct {
|
||||
InventoryID uuid.UUID
|
||||
FilmID string
|
||||
}
|
||||
|
||||
dest := Inventory{}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.Error(t, err, `Scan: unable to scan type int32 into UUID, at struct field: InventoryID uuid.UUID of type postgres.Inventory. `)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestScanToNestedStruct(t *testing.T) {
|
||||
query := Inventory.
|
||||
INNER_JOIN(Film, Inventory.FilmID.EQ(Film.FilmID)).
|
||||
INNER_JOIN(Store, Inventory.StoreID.EQ(Store.StoreID)).
|
||||
SELECT(Inventory.AllColumns, Film.AllColumns, Store.AllColumns).
|
||||
WHERE(Inventory.InventoryID.EQ(Int(1)))
|
||||
|
||||
t.Run("embedded structs", func(t *testing.T) {
|
||||
dest := struct {
|
||||
model.Inventory
|
||||
model.Film
|
||||
model.Store
|
||||
}{}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, dest.Inventory, inventory1)
|
||||
assert.DeepEqual(t, dest.Film, film1)
|
||||
assert.DeepEqual(t, dest.Store, store1)
|
||||
})
|
||||
|
||||
t.Run("embedded pointer structs", func(t *testing.T) {
|
||||
dest := struct {
|
||||
*model.Inventory
|
||||
*model.Film
|
||||
*model.Store
|
||||
}{}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, *dest.Inventory, inventory1)
|
||||
assert.DeepEqual(t, *dest.Film, film1)
|
||||
assert.DeepEqual(t, *dest.Store, store1)
|
||||
})
|
||||
|
||||
t.Run("embedded unused structs", func(t *testing.T) {
|
||||
dest := struct {
|
||||
model.Inventory
|
||||
model.Actor //unused
|
||||
}{}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, dest.Inventory, inventory1)
|
||||
assert.DeepEqual(t, dest.Actor, model.Actor{})
|
||||
})
|
||||
|
||||
t.Run("embedded unused pointer structs", func(t *testing.T) {
|
||||
dest := struct {
|
||||
model.Inventory
|
||||
*model.Actor //unused
|
||||
}{}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, dest.Inventory, inventory1)
|
||||
assert.DeepEqual(t, dest.Actor, (*model.Actor)(nil))
|
||||
})
|
||||
|
||||
t.Run("embedded unused pointer structs", func(t *testing.T) {
|
||||
dest := struct {
|
||||
model.Inventory
|
||||
Actor *model.Actor //unused
|
||||
}{}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, dest.Inventory, inventory1)
|
||||
assert.DeepEqual(t, dest.Actor, (*model.Actor)(nil))
|
||||
})
|
||||
|
||||
t.Run("embedded pointer to selected column", func(t *testing.T) {
|
||||
query := Inventory.
|
||||
INNER_JOIN(Film, Inventory.FilmID.EQ(Film.FilmID)).
|
||||
INNER_JOIN(Store, Inventory.StoreID.EQ(Store.StoreID)).
|
||||
SELECT(Inventory.AllColumns, Film.AllColumns, Store.AllColumns, String("").AS("actor.first_name")).
|
||||
WHERE(Inventory.InventoryID.EQ(Int(1)))
|
||||
|
||||
dest := struct {
|
||||
model.Inventory
|
||||
Actor *model.Actor //unused
|
||||
}{}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, dest.Inventory, inventory1)
|
||||
assert.Assert(t, dest.Actor != nil)
|
||||
})
|
||||
|
||||
t.Run("struct embedded unused pointer", func(t *testing.T) {
|
||||
dest := struct {
|
||||
model.Inventory
|
||||
Actor *struct {
|
||||
model.Actor
|
||||
} //unused
|
||||
}{}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, dest.Inventory, inventory1)
|
||||
assert.DeepEqual(t, dest.Actor, (*struct{ model.Actor })(nil))
|
||||
})
|
||||
|
||||
t.Run("multiple embedded unused pointer", func(t *testing.T) {
|
||||
dest := struct {
|
||||
model.Inventory
|
||||
Actor *struct {
|
||||
model.Actor //unused
|
||||
model.Language //unesed
|
||||
}
|
||||
}{}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, dest.Inventory, inventory1)
|
||||
assert.DeepEqual(t, dest.Actor, (*struct {
|
||||
model.Actor
|
||||
model.Language
|
||||
})(nil))
|
||||
})
|
||||
|
||||
t.Run("field not nil, embedded selected model", func(t *testing.T) {
|
||||
dest := struct {
|
||||
model.Inventory
|
||||
Actor *struct {
|
||||
model.Actor //unselected
|
||||
model.Film //selected
|
||||
}
|
||||
}{}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, dest.Inventory, inventory1)
|
||||
assert.Assert(t, dest.Actor != nil)
|
||||
assert.DeepEqual(t, dest.Actor.Actor, model.Actor{})
|
||||
assert.DeepEqual(t, dest.Actor.Film, film1)
|
||||
})
|
||||
|
||||
t.Run("field not nil, deeply nested selected model", func(t *testing.T) {
|
||||
dest := struct {
|
||||
model.Inventory
|
||||
Actor *struct {
|
||||
model.Actor //unselected
|
||||
Film *struct {
|
||||
*model.Film //selected
|
||||
}
|
||||
}
|
||||
}{}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, dest.Inventory, inventory1)
|
||||
assert.Assert(t, dest.Actor != nil)
|
||||
assert.Assert(t, dest.Actor.Film != nil)
|
||||
assert.DeepEqual(t, dest.Actor.Film.Film, &film1)
|
||||
})
|
||||
|
||||
t.Run("embedded structs", func(t *testing.T) {
|
||||
query := Inventory.
|
||||
INNER_JOIN(Film, Inventory.FilmID.EQ(Film.FilmID)).
|
||||
INNER_JOIN(Store, Inventory.StoreID.EQ(Store.StoreID)).
|
||||
INNER_JOIN(Language, Film.LanguageID.EQ(Language.LanguageID)).
|
||||
SELECT(Inventory.AllColumns, Film.AllColumns, Store.AllColumns, Language.AllColumns).
|
||||
WHERE(Inventory.InventoryID.EQ(Int(1)))
|
||||
|
||||
type Language3 model.Language
|
||||
|
||||
dest := struct {
|
||||
model.Inventory
|
||||
Film struct {
|
||||
model.Film
|
||||
|
||||
Language model.Language
|
||||
Language2 *model.Language `alias:"Language.*"`
|
||||
Language3 *Language3 `alias:"language"`
|
||||
Lang struct {
|
||||
model.Language
|
||||
}
|
||||
Lang2 *struct {
|
||||
model.Language
|
||||
}
|
||||
}
|
||||
Store model.Store
|
||||
}{}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, dest.Inventory, inventory1)
|
||||
assert.DeepEqual(t, dest.Film.Film, film1)
|
||||
assert.DeepEqual(t, dest.Store, store1)
|
||||
assert.DeepEqual(t, dest.Film.Language, language1)
|
||||
assert.DeepEqual(t, dest.Film.Lang.Language, language1)
|
||||
assert.DeepEqual(t, dest.Film.Lang2.Language, language1)
|
||||
assert.DeepEqual(t, dest.Film.Language2, &language1)
|
||||
assert.DeepEqual(t, model.Language(*dest.Film.Language3), language1)
|
||||
})
|
||||
}
|
||||
|
||||
func TestScanToSlice(t *testing.T) {
|
||||
|
||||
t.Run("slice of structs", func(t *testing.T) {
|
||||
query := Inventory.
|
||||
SELECT(Inventory.AllColumns).
|
||||
ORDER_BY(Inventory.InventoryID).
|
||||
LIMIT(10)
|
||||
|
||||
t.Run("slice od inventory", func(t *testing.T) {
|
||||
dest := []model.Inventory{}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(dest), 10)
|
||||
assert.DeepEqual(t, dest[0], inventory1)
|
||||
assert.DeepEqual(t, dest[1], inventory2)
|
||||
})
|
||||
|
||||
t.Run("slice of ints", func(t *testing.T) {
|
||||
var dest []int32
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, dest, []int32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
|
||||
|
||||
})
|
||||
|
||||
t.Run("slice type mismatch ", func(t *testing.T) {
|
||||
var dest []int
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
assert.Error(t, err, `jet: can't append int32 to []int slice `)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("slice of complex structs", func(t *testing.T) {
|
||||
query := Inventory.
|
||||
INNER_JOIN(Film, Inventory.FilmID.EQ(Film.FilmID)).
|
||||
INNER_JOIN(Store, Inventory.StoreID.EQ(Store.StoreID)).
|
||||
SELECT(
|
||||
Inventory.AllColumns,
|
||||
Film.AllColumns,
|
||||
Store.AllColumns,
|
||||
).
|
||||
ORDER_BY(Inventory.InventoryID).
|
||||
LIMIT(10)
|
||||
|
||||
t.Run("struct with slice of ints", func(t *testing.T) {
|
||||
var dest struct {
|
||||
model.Film
|
||||
IDs []int32 `alias:"inventory.inventory_id"`
|
||||
}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, dest.Film, film1)
|
||||
assert.DeepEqual(t, dest.IDs, []int32{1, 2, 3, 4, 5, 6, 7, 8})
|
||||
})
|
||||
|
||||
t.Run("slice of structs with slice of ints", func(t *testing.T) {
|
||||
var dest []struct {
|
||||
model.Film
|
||||
IDs []int32 `alias:"inventory.inventory_id"`
|
||||
}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(dest), 2)
|
||||
assert.DeepEqual(t, dest[0].Film, film1)
|
||||
assert.DeepEqual(t, dest[0].IDs, []int32{1, 2, 3, 4, 5, 6, 7, 8})
|
||||
assert.DeepEqual(t, dest[1].Film, film2)
|
||||
assert.DeepEqual(t, dest[1].IDs, []int32{9, 10})
|
||||
})
|
||||
|
||||
t.Run("slice of structs with slice of pointer to ints", func(t *testing.T) {
|
||||
var dest []struct {
|
||||
model.Film
|
||||
IDs []*int32 `alias:"inventory.inventory_id"`
|
||||
}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(dest), 2)
|
||||
assert.DeepEqual(t, dest[0].Film, film1)
|
||||
assert.DeepEqual(t, dest[0].IDs, []*int32{Int32Ptr(1), Int32Ptr(2), Int32Ptr(3), Int32Ptr(4),
|
||||
Int32Ptr(5), Int32Ptr(6), Int32Ptr(7), Int32Ptr(8)})
|
||||
assert.DeepEqual(t, dest[1].Film, film2)
|
||||
assert.DeepEqual(t, dest[1].IDs, []*int32{Int32Ptr(9), Int32Ptr(10)})
|
||||
})
|
||||
|
||||
t.Run("complex struct 1", func(t *testing.T) {
|
||||
dest := []struct {
|
||||
model.Inventory
|
||||
model.Film
|
||||
model.Store
|
||||
}{}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(dest), 10)
|
||||
assert.DeepEqual(t, dest[0].Inventory, inventory1)
|
||||
assert.DeepEqual(t, dest[0].Film, film1)
|
||||
assert.DeepEqual(t, dest[0].Store, store1)
|
||||
|
||||
assert.DeepEqual(t, dest[1].Inventory, inventory2)
|
||||
})
|
||||
|
||||
t.Run("complex struct 2", func(t *testing.T) {
|
||||
var dest []struct {
|
||||
*model.Inventory
|
||||
model.Film
|
||||
*model.Store
|
||||
}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(dest), 10)
|
||||
assert.DeepEqual(t, dest[0].Inventory, &inventory1)
|
||||
assert.DeepEqual(t, dest[0].Film, film1)
|
||||
assert.DeepEqual(t, dest[0].Store, &store1)
|
||||
|
||||
assert.DeepEqual(t, dest[1].Inventory, &inventory2)
|
||||
})
|
||||
|
||||
t.Run("complex struct 3", func(t *testing.T) {
|
||||
var dest []struct {
|
||||
Inventory model.Inventory
|
||||
Film *model.Film
|
||||
Store struct {
|
||||
*model.Store
|
||||
}
|
||||
}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(dest), 10)
|
||||
assert.DeepEqual(t, dest[0].Inventory, inventory1)
|
||||
assert.DeepEqual(t, dest[0].Film, &film1)
|
||||
assert.DeepEqual(t, dest[0].Store.Store, &store1)
|
||||
|
||||
assert.DeepEqual(t, dest[1].Inventory, inventory2)
|
||||
})
|
||||
|
||||
t.Run("complex struct 4", func(t *testing.T) {
|
||||
var dest []struct {
|
||||
model.Film
|
||||
|
||||
Inventories []struct {
|
||||
model.Inventory
|
||||
model.Store
|
||||
}
|
||||
}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(dest), 2)
|
||||
assert.DeepEqual(t, dest[0].Film, film1)
|
||||
assert.DeepEqual(t, len(dest[0].Inventories), 8)
|
||||
assert.DeepEqual(t, dest[0].Inventories[0].Inventory, inventory1)
|
||||
assert.DeepEqual(t, dest[0].Inventories[0].Store, store1)
|
||||
})
|
||||
|
||||
t.Run("complex struct 5", func(t *testing.T) {
|
||||
var dest []struct {
|
||||
model.Film
|
||||
|
||||
Inventories []struct {
|
||||
model.Inventory
|
||||
|
||||
Rentals *[]model.Rental
|
||||
Rentals2 []model.Rental
|
||||
}
|
||||
}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Equal(t, len(dest), 2)
|
||||
assert.DeepEqual(t, dest[0].Film, film1)
|
||||
assert.Equal(t, len(dest[0].Inventories), 8)
|
||||
assert.DeepEqual(t, dest[0].Inventories[0].Inventory, inventory1)
|
||||
assert.Assert(t, dest[0].Inventories[0].Rentals == nil)
|
||||
assert.Assert(t, dest[0].Inventories[0].Rentals2 == nil)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("slice of complex structs 2", func(t *testing.T) {
|
||||
query := Country.
|
||||
INNER_JOIN(City, City.CountryID.EQ(Country.CountryID)).
|
||||
INNER_JOIN(Address, Address.CityID.EQ(City.CityID)).
|
||||
INNER_JOIN(Customer, Customer.AddressID.EQ(Address.AddressID)).
|
||||
SELECT(Country.AllColumns, City.AllColumns, Address.AllColumns, Customer.AllColumns).
|
||||
ORDER_BY(Country.CountryID.ASC(), City.CityID.ASC(), Address.AddressID.ASC(), Customer.CustomerID.ASC()).
|
||||
LIMIT(1000)
|
||||
|
||||
t.Run("dest1", func(t *testing.T) {
|
||||
var dest []struct {
|
||||
model.Country
|
||||
|
||||
Cities []struct {
|
||||
model.City
|
||||
|
||||
Adresses []struct {
|
||||
model.Address
|
||||
|
||||
Customer model.Customer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(dest), 108)
|
||||
assert.DeepEqual(t, dest[100].Country, countryUk)
|
||||
assert.Equal(t, len(dest[100].Cities), 8)
|
||||
assert.DeepEqual(t, dest[100].Cities[2].City, cityLondon)
|
||||
assert.Equal(t, len(dest[100].Cities[2].Adresses), 2)
|
||||
assert.DeepEqual(t, dest[100].Cities[2].Adresses[0].Address, address256)
|
||||
assert.DeepEqual(t, dest[100].Cities[2].Adresses[0].Customer, customer256)
|
||||
assert.DeepEqual(t, dest[100].Cities[2].Adresses[1].Address, addres517)
|
||||
assert.DeepEqual(t, dest[100].Cities[2].Adresses[1].Customer, customer512)
|
||||
})
|
||||
|
||||
t.Run("dest1", func(t *testing.T) {
|
||||
var dest []*struct {
|
||||
*model.Country
|
||||
|
||||
Cities []*struct {
|
||||
*model.City
|
||||
|
||||
Adresses *[]*struct {
|
||||
*model.Address
|
||||
|
||||
Customer *model.Customer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(dest), 108)
|
||||
assert.DeepEqual(t, dest[100].Country, &countryUk)
|
||||
assert.Equal(t, len(dest[100].Cities), 8)
|
||||
assert.DeepEqual(t, dest[100].Cities[2].City, &cityLondon)
|
||||
assert.Equal(t, len(*dest[100].Cities[2].Adresses), 2)
|
||||
assert.DeepEqual(t, (*dest[100].Cities[2].Adresses)[0].Address, &address256)
|
||||
assert.DeepEqual(t, (*dest[100].Cities[2].Adresses)[0].Customer, &customer256)
|
||||
assert.DeepEqual(t, (*dest[100].Cities[2].Adresses)[1].Address, &addres517)
|
||||
assert.DeepEqual(t, (*dest[100].Cities[2].Adresses)[1].Customer, &customer512)
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
t.Run("dest1", func(t *testing.T) {
|
||||
var dest []*struct {
|
||||
*model.Country
|
||||
|
||||
Cities []**struct {
|
||||
*model.City
|
||||
}
|
||||
}
|
||||
|
||||
err := query.Query(db, &dest)
|
||||
|
||||
assert.Error(t, err, "jet: Unsupported dest type: Cities []**struct { *model.City }")
|
||||
})
|
||||
}
|
||||
|
||||
var address256 = model.Address{
|
||||
AddressID: 256,
|
||||
Address: "1497 Yuzhou Drive",
|
||||
Address2: StringPtr(""),
|
||||
District: "England",
|
||||
CityID: 312,
|
||||
PostalCode: StringPtr("3433"),
|
||||
Phone: "246810237916",
|
||||
LastUpdate: *testutils.TimestampWithoutTimeZone("2006-02-15 09:45:30", 0),
|
||||
}
|
||||
|
||||
var addres517 = model.Address{
|
||||
AddressID: 517,
|
||||
Address: "548 Uruapan Street",
|
||||
Address2: StringPtr(""),
|
||||
District: "Ontario",
|
||||
CityID: 312,
|
||||
PostalCode: StringPtr("35653"),
|
||||
Phone: "879347453467",
|
||||
LastUpdate: *testutils.TimestampWithoutTimeZone("2006-02-15 09:45:30", 0),
|
||||
}
|
||||
|
||||
var customer256 = model.Customer{
|
||||
CustomerID: 252,
|
||||
StoreID: 2,
|
||||
FirstName: "Mattie",
|
||||
LastName: "Hoffman",
|
||||
Email: StringPtr("mattie.hoffman@sakilacustomer.org"),
|
||||
AddressID: 256,
|
||||
Activebool: true,
|
||||
CreateDate: *testutils.TimestampWithoutTimeZone("2006-02-14 00:00:00", 0),
|
||||
LastUpdate: testutils.TimestampWithoutTimeZone("2013-05-26 14:49:45.738", 0),
|
||||
Active: Int32Ptr(1),
|
||||
}
|
||||
|
||||
var customer512 = model.Customer{
|
||||
CustomerID: 512,
|
||||
StoreID: 1,
|
||||
FirstName: "Cecil",
|
||||
LastName: "Vines",
|
||||
Email: StringPtr("cecil.vines@sakilacustomer.org"),
|
||||
AddressID: 517,
|
||||
Activebool: true,
|
||||
CreateDate: *testutils.TimestampWithoutTimeZone("2006-02-14 00:00:00", 0),
|
||||
LastUpdate: testutils.TimestampWithoutTimeZone("2013-05-26 14:49:45.738", 0),
|
||||
Active: Int32Ptr(1),
|
||||
}
|
||||
|
||||
var countryUk = model.Country{
|
||||
CountryID: 102,
|
||||
Country: "United Kingdom",
|
||||
LastUpdate: *testutils.TimestampWithoutTimeZone("2006-02-15 09:44:00", 0),
|
||||
}
|
||||
|
||||
var cityLondon = model.City{
|
||||
CityID: 312,
|
||||
City: "London",
|
||||
CountryID: 102,
|
||||
LastUpdate: *testutils.TimestampWithoutTimeZone("2006-02-15 09:45:25", 0),
|
||||
}
|
||||
|
||||
var inventory1 = model.Inventory{
|
||||
InventoryID: 1,
|
||||
FilmID: 1,
|
||||
StoreID: 1,
|
||||
LastUpdate: *testutils.TimestampWithoutTimeZone("2006-02-15 10:09:17", 0),
|
||||
}
|
||||
|
||||
var inventory2 = model.Inventory{
|
||||
InventoryID: 2,
|
||||
FilmID: 1,
|
||||
StoreID: 1,
|
||||
LastUpdate: *testutils.TimestampWithoutTimeZone("2006-02-15 10:09:17", 0),
|
||||
}
|
||||
|
||||
var film1 = model.Film{
|
||||
FilmID: 1,
|
||||
Title: "Academy Dinosaur",
|
||||
Description: StringPtr("A Epic Drama of a Feminist And a Mad Scientist who must Battle a Teacher in The Canadian Rockies"),
|
||||
ReleaseYear: Int32Ptr(2006),
|
||||
LanguageID: 1,
|
||||
RentalDuration: 6,
|
||||
RentalRate: 0.99,
|
||||
Length: Int16Ptr(86),
|
||||
ReplacementCost: 20.99,
|
||||
Rating: &pgRating,
|
||||
LastUpdate: *testutils.TimestampWithoutTimeZone("2013-05-26 14:50:58.951", 3),
|
||||
SpecialFeatures: StringPtr("{\"Deleted Scenes\",\"Behind the Scenes\"}"),
|
||||
Fulltext: "'academi':1 'battl':15 'canadian':20 'dinosaur':2 'drama':5 'epic':4 'feminist':8 'mad':11 'must':14 'rocki':21 'scientist':12 'teacher':17",
|
||||
}
|
||||
|
||||
var film2 = model.Film{
|
||||
FilmID: 2,
|
||||
Title: "Ace Goldfinger",
|
||||
Description: StringPtr("A Astounding Epistle of a Database Administrator And a Explorer who must Find a Car in Ancient China"),
|
||||
ReleaseYear: Int32Ptr(2006),
|
||||
LanguageID: 1,
|
||||
RentalDuration: 3,
|
||||
RentalRate: 4.99,
|
||||
Length: Int16Ptr(48),
|
||||
ReplacementCost: 12.99,
|
||||
Rating: &gRating,
|
||||
LastUpdate: *testutils.TimestampWithoutTimeZone("2013-05-26 14:50:58.951", 3),
|
||||
SpecialFeatures: StringPtr(`{Trailers,"Deleted Scenes"}`),
|
||||
Fulltext: `'ace':1 'administr':9 'ancient':19 'astound':4 'car':17 'china':20 'databas':8 'epistl':5 'explor':12 'find':15 'goldfing':2 'must':14`,
|
||||
}
|
||||
|
||||
var store1 = model.Store{
|
||||
StoreID: 1,
|
||||
ManagerStaffID: 1,
|
||||
AddressID: 1,
|
||||
LastUpdate: *testutils.TimestampWithoutTimeZone("2006-02-15 09:57:12", 0),
|
||||
}
|
||||
|
||||
var pgRating = model.MpaaRating_Pg
|
||||
var gRating = model.MpaaRating_G
|
||||
|
||||
var language1 = model.Language{
|
||||
LanguageID: 1,
|
||||
Name: "English ",
|
||||
LastUpdate: *testutils.TimestampWithoutTimeZone("2006-02-15 10:02:19", 0),
|
||||
}
|
||||
1541
tests/postgres/select_test.go
Normal file
1541
tests/postgres/select_test.go
Normal file
File diff suppressed because it is too large
Load diff
252320
tests/postgres/testdata/joined_everything.json
vendored
Normal file
252320
tests/postgres/testdata/joined_everything.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
135339
tests/postgres/testdata/northwind-all.json
vendored
Normal file
135339
tests/postgres/testdata/northwind-all.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
6067
tests/postgres/testdata/quick-start-dest.json
vendored
Normal file
6067
tests/postgres/testdata/quick-start-dest.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1769
tests/postgres/testdata/quick-start-dest2.json
vendored
Normal file
1769
tests/postgres/testdata/quick-start-dest2.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
302
tests/postgres/update_test.go
Normal file
302
tests/postgres/update_test.go
Normal file
|
|
@ -0,0 +1,302 @@
|
|||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
. "github.com/go-jet/jet"
|
||||
"github.com/go-jet/jet/internal/testutils"
|
||||
"github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/model"
|
||||
. "github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/table"
|
||||
"gotest.tools/assert"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestUpdateValues(t *testing.T) {
|
||||
setupLinkTableForUpdateTest(t)
|
||||
|
||||
query := Link.
|
||||
UPDATE(Link.Name, Link.URL).
|
||||
SET("Bong", "http://bong.com").
|
||||
WHERE(Link.Name.EQ(String("Bing")))
|
||||
|
||||
var expectedSQL = `
|
||||
UPDATE test_sample.link
|
||||
SET (name, url) = ('Bong', 'http://bong.com')
|
||||
WHERE link.name = 'Bing';
|
||||
`
|
||||
testutils.AssertDebugStatementSql(t, query, expectedSQL, "Bong", "http://bong.com", "Bing")
|
||||
|
||||
assertExec(t, query, 1)
|
||||
|
||||
links := []model.Link{}
|
||||
|
||||
err := Link.
|
||||
SELECT(Link.AllColumns).
|
||||
WHERE(Link.Name.EQ(String("Bong"))).
|
||||
Query(db, &links)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(links), 1)
|
||||
assert.DeepEqual(t, links[0], model.Link{
|
||||
ID: 204,
|
||||
URL: "http://bong.com",
|
||||
Name: "Bong",
|
||||
})
|
||||
}
|
||||
|
||||
func TestUpdateWithSubQueries(t *testing.T) {
|
||||
setupLinkTableForUpdateTest(t)
|
||||
|
||||
query := Link.
|
||||
UPDATE(Link.Name, Link.URL).
|
||||
SET(
|
||||
SELECT(String("Bong")),
|
||||
SELECT(Link.URL).
|
||||
FROM(Link).
|
||||
WHERE(Link.Name.EQ(String("Bing"))),
|
||||
).
|
||||
WHERE(Link.Name.EQ(String("Bing")))
|
||||
|
||||
expectedSQL := `
|
||||
UPDATE test_sample.link
|
||||
SET (name, url) = ((
|
||||
SELECT 'Bong'
|
||||
), (
|
||||
SELECT link.url AS "link.url"
|
||||
FROM test_sample.link
|
||||
WHERE link.name = 'Bing'
|
||||
))
|
||||
WHERE link.name = 'Bing';
|
||||
`
|
||||
|
||||
testutils.AssertDebugStatementSql(t, query, expectedSQL, "Bong", "Bing", "Bing")
|
||||
|
||||
assertExec(t, query, 1)
|
||||
}
|
||||
|
||||
func TestUpdateAndReturning(t *testing.T) {
|
||||
setupLinkTableForUpdateTest(t)
|
||||
|
||||
expectedSQL := `
|
||||
UPDATE test_sample.link
|
||||
SET (name, url) = ('DuckDuckGo', 'http://www.duckduckgo.com')
|
||||
WHERE link.name = 'Ask'
|
||||
RETURNING link.id AS "link.id",
|
||||
link.url AS "link.url",
|
||||
link.name AS "link.name",
|
||||
link.description AS "link.description";
|
||||
`
|
||||
|
||||
stmt := Link.
|
||||
UPDATE(Link.Name, Link.URL).
|
||||
SET("DuckDuckGo", "http://www.duckduckgo.com").
|
||||
WHERE(Link.Name.EQ(String("Ask"))).
|
||||
RETURNING(Link.AllColumns)
|
||||
|
||||
testutils.AssertDebugStatementSql(t, stmt, expectedSQL, "DuckDuckGo", "http://www.duckduckgo.com", "Ask")
|
||||
|
||||
links := []model.Link{}
|
||||
|
||||
err := stmt.Query(db, &links)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(links), 2)
|
||||
assert.Equal(t, links[0].Name, "DuckDuckGo")
|
||||
assert.Equal(t, links[1].Name, "DuckDuckGo")
|
||||
}
|
||||
|
||||
func TestUpdateWithSelect(t *testing.T) {
|
||||
|
||||
stmt := Link.UPDATE(Link.AllColumns).
|
||||
SET(
|
||||
Link.
|
||||
SELECT(Link.AllColumns).
|
||||
WHERE(Link.ID.EQ(Int(0))),
|
||||
).
|
||||
WHERE(Link.ID.EQ(Int(0)))
|
||||
|
||||
expectedSQL := `
|
||||
UPDATE test_sample.link
|
||||
SET (id, url, name, description) = (
|
||||
SELECT link.id AS "link.id",
|
||||
link.url AS "link.url",
|
||||
link.name AS "link.name",
|
||||
link.description AS "link.description"
|
||||
FROM test_sample.link
|
||||
WHERE link.id = 0
|
||||
)
|
||||
WHERE link.id = 0;
|
||||
`
|
||||
testutils.AssertDebugStatementSql(t, stmt, expectedSQL, int64(0), int64(0))
|
||||
|
||||
assertExec(t, stmt, 1)
|
||||
}
|
||||
|
||||
func TestUpdateWithInvalidSelect(t *testing.T) {
|
||||
|
||||
stmt := Link.UPDATE(Link.AllColumns).
|
||||
SET(
|
||||
Link.
|
||||
SELECT(Link.ID, Link.Name).
|
||||
WHERE(Link.ID.EQ(Int(0))),
|
||||
).
|
||||
WHERE(Link.ID.EQ(Int(0)))
|
||||
|
||||
var expectedSQL = `
|
||||
UPDATE test_sample.link
|
||||
SET (id, url, name, description) = (
|
||||
SELECT link.id AS "link.id",
|
||||
link.name AS "link.name"
|
||||
FROM test_sample.link
|
||||
WHERE link.id = 0
|
||||
)
|
||||
WHERE link.id = 0;
|
||||
`
|
||||
testutils.AssertDebugStatementSql(t, stmt, expectedSQL, int64(0), int64(0))
|
||||
|
||||
assertExecErr(t, stmt, "pq: number of columns does not match number of values")
|
||||
}
|
||||
|
||||
func TestUpdateWithModelData(t *testing.T) {
|
||||
setupLinkTableForUpdateTest(t)
|
||||
|
||||
link := model.Link{
|
||||
ID: 201,
|
||||
URL: "http://www.duckduckgo.com",
|
||||
Name: "DuckDuckGo",
|
||||
}
|
||||
|
||||
stmt := Link.
|
||||
UPDATE(Link.AllColumns).
|
||||
MODEL(link).
|
||||
WHERE(Link.ID.EQ(Int(int64(link.ID))))
|
||||
|
||||
expectedSQL := `
|
||||
UPDATE test_sample.link
|
||||
SET (id, url, name, description) = (201, 'http://www.duckduckgo.com', 'DuckDuckGo', NULL)
|
||||
WHERE link.id = 201;
|
||||
`
|
||||
testutils.AssertDebugStatementSql(t, stmt, expectedSQL, int32(201), "http://www.duckduckgo.com", "DuckDuckGo", nil, int64(201))
|
||||
|
||||
assertExec(t, stmt, 1)
|
||||
}
|
||||
|
||||
func TestUpdateWithModelDataAndPredefinedColumnList(t *testing.T) {
|
||||
|
||||
setupLinkTableForUpdateTest(t)
|
||||
|
||||
link := model.Link{
|
||||
ID: 201,
|
||||
URL: "http://www.duckduckgo.com",
|
||||
Name: "DuckDuckGo",
|
||||
}
|
||||
|
||||
updateColumnList := ColumnList{Link.Description, Link.Name, Link.URL}
|
||||
|
||||
stmt := Link.
|
||||
UPDATE(updateColumnList).
|
||||
MODEL(link).
|
||||
WHERE(Link.ID.EQ(Int(int64(link.ID))))
|
||||
|
||||
var expectedSQL = `
|
||||
UPDATE test_sample.link
|
||||
SET (description, name, url) = (NULL, 'DuckDuckGo', 'http://www.duckduckgo.com')
|
||||
WHERE link.id = 201;
|
||||
`
|
||||
testutils.AssertDebugStatementSql(t, stmt, expectedSQL, nil, "DuckDuckGo", "http://www.duckduckgo.com", int64(201))
|
||||
|
||||
assertExec(t, stmt, 1)
|
||||
}
|
||||
|
||||
func TestUpdateWithInvalidModelData(t *testing.T) {
|
||||
defer func() {
|
||||
r := recover()
|
||||
|
||||
assert.Equal(t, r, "missing struct field for column : id")
|
||||
}()
|
||||
|
||||
setupLinkTableForUpdateTest(t)
|
||||
|
||||
link := struct {
|
||||
Ident int
|
||||
URL string
|
||||
Name string
|
||||
Description *string
|
||||
Rel *string
|
||||
}{
|
||||
Ident: 201,
|
||||
URL: "http://www.duckduckgo.com",
|
||||
Name: "DuckDuckGo",
|
||||
}
|
||||
|
||||
stmt := Link.
|
||||
UPDATE(Link.AllColumns).
|
||||
MODEL(link).
|
||||
WHERE(Link.ID.EQ(Int(int64(link.Ident))))
|
||||
|
||||
var expectedSQL = `
|
||||
UPDATE test_sample.link
|
||||
SET (id, url, name, description, rel) = ('http://www.duckduckgo.com', 'DuckDuckGo', NULL, NULL)
|
||||
WHERE link.id = 201;
|
||||
`
|
||||
testutils.AssertDebugStatementSql(t, stmt, expectedSQL, "http://www.duckduckgo.com", "DuckDuckGo", nil, nil, int64(201))
|
||||
|
||||
assertExecErr(t, stmt, "pq: number of columns does not match number of values")
|
||||
}
|
||||
|
||||
func TestUpdateQueryContext(t *testing.T) {
|
||||
setupLinkTableForUpdateTest(t)
|
||||
|
||||
updateStmt := Link.
|
||||
UPDATE(Link.Name, Link.URL).
|
||||
SET("Bong", "http://bong.com").
|
||||
WHERE(Link.Name.EQ(String("Bing")))
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Microsecond)
|
||||
defer cancel()
|
||||
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
dest := []model.Link{}
|
||||
err := updateStmt.QueryContext(ctx, db, &dest)
|
||||
|
||||
assert.Error(t, err, "context deadline exceeded")
|
||||
}
|
||||
|
||||
func TestUpdateExecContext(t *testing.T) {
|
||||
setupLinkTableForUpdateTest(t)
|
||||
|
||||
updateStmt := Link.
|
||||
UPDATE(Link.Name, Link.URL).
|
||||
SET("Bong", "http://bong.com").
|
||||
WHERE(Link.Name.EQ(String("Bing")))
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Microsecond)
|
||||
defer cancel()
|
||||
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
_, err := updateStmt.ExecContext(ctx, db)
|
||||
|
||||
assert.Error(t, err, "context deadline exceeded")
|
||||
}
|
||||
|
||||
func setupLinkTableForUpdateTest(t *testing.T) {
|
||||
|
||||
cleanUpLinkTable(t)
|
||||
|
||||
_, err := Link.INSERT(Link.ID, Link.URL, Link.Name, Link.Description).
|
||||
VALUES(200, "http://www.postgresqltutorial.com", "PostgreSQL Tutorial", DEFAULT).
|
||||
VALUES(201, "http://www.ask.com", "Ask", DEFAULT).
|
||||
VALUES(202, "http://www.ask.com", "Ask", DEFAULT).
|
||||
VALUES(203, "http://www.yahoo.com", "Yahoo", DEFAULT).
|
||||
VALUES(204, "http://www.bing.com", "Bing", DEFAULT).
|
||||
Exec(db)
|
||||
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
func cleanUpLinkTable(t *testing.T) {
|
||||
_, err := Link.DELETE().WHERE(Link.ID.GT(Int(0))).Exec(db)
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
139
tests/postgres/util_test.go
Normal file
139
tests/postgres/util_test.go
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
package postgres
|
||||
|
||||
import (
|
||||
"github.com/go-jet/jet"
|
||||
"github.com/go-jet/jet/internal/testutils"
|
||||
"github.com/go-jet/jet/tests/.gentestdata/jetdb/dvds/model"
|
||||
"github.com/google/uuid"
|
||||
"gotest.tools/assert"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func assertExec(t *testing.T, stmt jet.Statement, rowsAffected int64) {
|
||||
res, err := stmt.Exec(db)
|
||||
|
||||
assert.NilError(t, err)
|
||||
rows, err := res.RowsAffected()
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, rows, rowsAffected)
|
||||
}
|
||||
|
||||
func assertExecErr(t *testing.T, stmt jet.Statement, errorStr string) {
|
||||
_, err := stmt.Exec(db)
|
||||
|
||||
assert.Error(t, err, errorStr)
|
||||
}
|
||||
func BoolPtr(b bool) *bool {
|
||||
return &b
|
||||
}
|
||||
|
||||
func Int16Ptr(i int16) *int16 {
|
||||
return &i
|
||||
}
|
||||
|
||||
func Int32Ptr(i int32) *int32 {
|
||||
return &i
|
||||
}
|
||||
|
||||
func Int64Ptr(i int64) *int64 {
|
||||
return &i
|
||||
}
|
||||
|
||||
func StringPtr(s string) *string {
|
||||
return &s
|
||||
}
|
||||
|
||||
func ByteArrayPtr(arr []byte) *[]byte {
|
||||
return &arr
|
||||
}
|
||||
|
||||
func Float32Ptr(f float32) *float32 {
|
||||
return &f
|
||||
}
|
||||
func Float64Ptr(f float64) *float64 {
|
||||
return &f
|
||||
}
|
||||
|
||||
func UUIDPtr(u string) *uuid.UUID {
|
||||
newUUID := uuid.MustParse(u)
|
||||
|
||||
return &newUUID
|
||||
}
|
||||
|
||||
func TimeWithoutTimeZone(t string) *time.Time {
|
||||
newTime, err := time.Parse("15:04:05", t)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return &newTime
|
||||
}
|
||||
|
||||
func TimeWithTimeZone(t string) *time.Time {
|
||||
newTimez, err := time.Parse("15:04:05 -0700", t)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return &newTimez
|
||||
}
|
||||
|
||||
func TimestampWithTimeZone(t string, precision int) *time.Time {
|
||||
|
||||
precisionStr := ""
|
||||
|
||||
if precision > 0 {
|
||||
precisionStr = "." + strings.Repeat("9", precision)
|
||||
}
|
||||
|
||||
newTime, err := time.Parse("2006-01-02 15:04:05"+precisionStr+" -0700 MST", t)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return &newTime
|
||||
}
|
||||
|
||||
var customer0 = model.Customer{
|
||||
CustomerID: 1,
|
||||
StoreID: 1,
|
||||
FirstName: "Mary",
|
||||
LastName: "Smith",
|
||||
Email: StringPtr("mary.smith@sakilacustomer.org"),
|
||||
AddressID: 5,
|
||||
Activebool: true,
|
||||
CreateDate: *testutils.TimestampWithoutTimeZone("2006-02-14 00:00:00", 0),
|
||||
LastUpdate: testutils.TimestampWithoutTimeZone("2013-05-26 14:49:45.738", 3),
|
||||
Active: Int32Ptr(1),
|
||||
}
|
||||
|
||||
var customer1 = model.Customer{
|
||||
CustomerID: 2,
|
||||
StoreID: 1,
|
||||
FirstName: "Patricia",
|
||||
LastName: "Johnson",
|
||||
Email: StringPtr("patricia.johnson@sakilacustomer.org"),
|
||||
AddressID: 6,
|
||||
Activebool: true,
|
||||
CreateDate: *testutils.TimestampWithoutTimeZone("2006-02-14 00:00:00", 0),
|
||||
LastUpdate: testutils.TimestampWithoutTimeZone("2013-05-26 14:49:45.738", 3),
|
||||
Active: Int32Ptr(1),
|
||||
}
|
||||
|
||||
var lastCustomer = model.Customer{
|
||||
CustomerID: 599,
|
||||
StoreID: 2,
|
||||
FirstName: "Austin",
|
||||
LastName: "Cintron",
|
||||
Email: StringPtr("austin.cintron@sakilacustomer.org"),
|
||||
AddressID: 605,
|
||||
Activebool: true,
|
||||
CreateDate: *testutils.TimestampWithoutTimeZone("2006-02-14 00:00:00", 0),
|
||||
LastUpdate: testutils.TimestampWithoutTimeZone("2013-05-26 14:49:45.738", 3),
|
||||
Active: Int32Ptr(1),
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue