Add automatic type cast for integer literals
In parameterized statements integer literals, like Int(num), are replaced with a placeholders. For some expressions, postgres interpreter will not have enough information to deduce the type. If this is the case postgres returns an error. Int8, Int16, Int32.... functions now will add automatic type cast over a placeholder, so type deduction is always possible.
This commit is contained in:
parent
47545ce571
commit
01305a138f
10 changed files with 146 additions and 106 deletions
|
|
@ -29,7 +29,7 @@ ON CONFLICT (col_bool) ON CONSTRAINT table_pkey DO NOTHING`)
|
|||
)
|
||||
assertClauseSerialize(t, onConflict, `
|
||||
ON CONFLICT (col_bool, col_float) WHERE (col_float + col_int) > col_float DO UPDATE
|
||||
SET col_bool = $1,
|
||||
SET col_bool = $1::boolean,
|
||||
col_int = $2
|
||||
WHERE table2.col_float > $3`)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ func TestExists(t *testing.T) {
|
|||
).EQ(Bool(true)),
|
||||
`((EXISTS (
|
||||
SELECT $1
|
||||
)) = $2)`, int64(1), true)
|
||||
)) = $2::boolean)`, int64(1), true)
|
||||
|
||||
assertProjectionSerialize(t, EXISTS(
|
||||
SELECT(Int(1)),
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ VALUES ('one', 'two'),
|
|||
('1', '2'),
|
||||
('theta', 'beta')
|
||||
ON CONFLICT (col_bool) WHERE col_bool IS NOT FALSE DO UPDATE
|
||||
SET col_bool = TRUE,
|
||||
SET col_bool = TRUE::boolean,
|
||||
col_int = 1,
|
||||
(col1, col_bool) = ROW(2, 'two')
|
||||
WHERE table1.col1 > 2
|
||||
|
|
@ -191,7 +191,7 @@ INSERT INTO db.table1 (col1, col_bool)
|
|||
VALUES ('one', 'two'),
|
||||
('1', '2')
|
||||
ON CONFLICT ON CONSTRAINT idk_primary_key DO UPDATE
|
||||
SET col_bool = FALSE,
|
||||
SET col_bool = FALSE::boolean,
|
||||
col_int = 1,
|
||||
(col1, col_bool) = ROW(2, 'two')
|
||||
WHERE table1.col1 > 2
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ func TestIntervalExpressionMethods(t *testing.T) {
|
|||
assertSerialize(t, table1ColInterval.EQ(INTERVAL(10, SECOND)), "(table1.col_interval = INTERVAL '10 SECOND')")
|
||||
assertSerialize(t, table1ColInterval.EQ(INTERVALd(11*time.Minute)), "(table1.col_interval = INTERVAL '11 MINUTE')")
|
||||
assertSerialize(t, table1ColInterval.EQ(INTERVALd(11*time.Minute)).EQ(Bool(false)),
|
||||
"((table1.col_interval = INTERVAL '11 MINUTE') = $1)", false)
|
||||
"((table1.col_interval = INTERVAL '11 MINUTE') = $1::boolean)", false)
|
||||
assertSerialize(t, table1ColInterval.NOT_EQ(table2ColInterval), "(table1.col_interval != table2.col_interval)")
|
||||
assertSerialize(t, table1ColInterval.IS_DISTINCT_FROM(table2ColInterval), "(table1.col_interval IS DISTINCT FROM table2.col_interval)")
|
||||
assertSerialize(t, table1ColInterval.IS_NOT_DISTINCT_FROM(table2ColInterval), "(table1.col_interval IS NOT DISTINCT FROM table2.col_interval)")
|
||||
|
|
|
|||
|
|
@ -6,35 +6,52 @@ import (
|
|||
"github.com/go-jet/jet/v2/internal/jet"
|
||||
)
|
||||
|
||||
// Bool creates new bool literal expression
|
||||
var Bool = jet.Bool
|
||||
func Bool(value bool) BoolExpression {
|
||||
return CAST(jet.Bool(value)).AS_BOOL()
|
||||
}
|
||||
|
||||
// Int is constructor for 64 bit signed integer expressions literals.
|
||||
var Int = jet.Int
|
||||
|
||||
// Int8 is constructor for 8 bit signed integer expressions literals.
|
||||
var Int8 = jet.Int8
|
||||
func Int8(value int8) IntegerExpression {
|
||||
return CAST(jet.Int8(value)).AS_SMALLINT()
|
||||
}
|
||||
|
||||
// Int16 is constructor for 16 bit signed integer expressions literals.
|
||||
var Int16 = jet.Int16
|
||||
func Int16(value int16) IntegerExpression {
|
||||
return CAST(jet.Int16(value)).AS_SMALLINT()
|
||||
}
|
||||
|
||||
// Int32 is constructor for 32 bit signed integer expressions literals.
|
||||
var Int32 = jet.Int32
|
||||
func Int32(value int32) IntegerExpression {
|
||||
return CAST(jet.Int32(value)).AS_INTEGER()
|
||||
}
|
||||
|
||||
// Int64 is constructor for 64 bit signed integer expressions literals.
|
||||
var Int64 = jet.Int
|
||||
func Int64(value int64) IntegerExpression {
|
||||
return CAST(jet.Int(value)).AS_BIGINT()
|
||||
}
|
||||
|
||||
// Uint8 is constructor for 8 bit unsigned integer expressions literals.
|
||||
var Uint8 = jet.Uint8
|
||||
func Uint8(value uint8) IntegerExpression {
|
||||
return CAST(jet.Uint8(value)).AS_SMALLINT()
|
||||
}
|
||||
|
||||
// Uint16 is constructor for 16 bit unsigned integer expressions literals.
|
||||
var Uint16 = jet.Uint16
|
||||
func Uint16(value uint16) IntegerExpression {
|
||||
return CAST(jet.Uint16(value)).AS_INTEGER()
|
||||
}
|
||||
|
||||
// Uint32 is constructor for 32 bit unsigned integer expressions literals.
|
||||
var Uint32 = jet.Uint32
|
||||
func Uint32(value uint32) IntegerExpression {
|
||||
return CAST(jet.Uint32(value)).AS_BIGINT()
|
||||
}
|
||||
|
||||
// Uint64 is constructor for 64 bit unsigned integer expressions literals.
|
||||
var Uint64 = jet.Uint64
|
||||
func Uint64(value uint64) IntegerExpression {
|
||||
return CAST(jet.Uint64(value)).AS_BIGINT()
|
||||
}
|
||||
|
||||
// Float creates new float literal expression
|
||||
var Float = jet.Float
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import (
|
|||
)
|
||||
|
||||
func TestBool(t *testing.T) {
|
||||
assertSerialize(t, Bool(false), `$1`, false)
|
||||
assertSerialize(t, Bool(false), `$1::boolean`, false)
|
||||
}
|
||||
|
||||
func TestInt(t *testing.T) {
|
||||
|
|
@ -16,42 +16,42 @@ func TestInt(t *testing.T) {
|
|||
|
||||
func TestInt8(t *testing.T) {
|
||||
val := int8(math.MinInt8)
|
||||
assertSerialize(t, Int8(val), `$1`, val)
|
||||
assertSerialize(t, Int8(val), `$1::smallint`, val)
|
||||
}
|
||||
|
||||
func TestInt16(t *testing.T) {
|
||||
val := int16(math.MinInt16)
|
||||
assertSerialize(t, Int16(val), `$1`, val)
|
||||
assertSerialize(t, Int16(val), `$1::smallint`, val)
|
||||
}
|
||||
|
||||
func TestInt32(t *testing.T) {
|
||||
val := int32(math.MinInt32)
|
||||
assertSerialize(t, Int32(val), `$1`, val)
|
||||
assertSerialize(t, Int32(val), `$1::integer`, val)
|
||||
}
|
||||
|
||||
func TestInt64(t *testing.T) {
|
||||
val := int64(math.MinInt64)
|
||||
assertSerialize(t, Int64(val), `$1`, val)
|
||||
assertSerialize(t, Int64(val), `$1::bigint`, val)
|
||||
}
|
||||
|
||||
func TestUint8(t *testing.T) {
|
||||
val := uint8(math.MaxUint8)
|
||||
assertSerialize(t, Uint8(val), `$1`, val)
|
||||
assertSerialize(t, Uint8(val), `$1::smallint`, val)
|
||||
}
|
||||
|
||||
func TestUint16(t *testing.T) {
|
||||
val := uint16(math.MaxUint16)
|
||||
assertSerialize(t, Uint16(val), `$1`, val)
|
||||
assertSerialize(t, Uint16(val), `$1::integer`, val)
|
||||
}
|
||||
|
||||
func TestUint32(t *testing.T) {
|
||||
val := uint32(math.MaxUint32)
|
||||
assertSerialize(t, Uint32(val), `$1`, val)
|
||||
assertSerialize(t, Uint32(val), `$1::bigint`, val)
|
||||
}
|
||||
|
||||
func TestUint64(t *testing.T) {
|
||||
val := uint64(math.MaxUint64)
|
||||
assertSerialize(t, Uint64(val), `$1`, val)
|
||||
assertSerialize(t, Uint64(val), `$1::bigint`, val)
|
||||
}
|
||||
|
||||
func TestFloat(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ func TestSelectLiterals(t *testing.T) {
|
|||
assertStatementSql(t, SELECT(Int(1), Float(2.2), Bool(false)).FROM(table1), `
|
||||
SELECT $1,
|
||||
$2,
|
||||
$3
|
||||
$3::boolean
|
||||
FROM db.table1;
|
||||
`, int64(1), 2.2, false)
|
||||
}
|
||||
|
|
@ -59,7 +59,7 @@ func TestSelectWhere(t *testing.T) {
|
|||
assertStatementSql(t, SELECT(table1ColInt).FROM(table1).WHERE(Bool(true)), `
|
||||
SELECT table1.col_int AS "table1.col_int"
|
||||
FROM db.table1
|
||||
WHERE $1;
|
||||
WHERE $1::boolean;
|
||||
`, true)
|
||||
assertStatementSql(t, SELECT(table1ColInt).FROM(table1).WHERE(table1ColInt.GT_EQ(Int(10))), `
|
||||
SELECT table1.col_int AS "table1.col_int"
|
||||
|
|
@ -80,7 +80,7 @@ func TestSelectHaving(t *testing.T) {
|
|||
assertStatementSql(t, SELECT(table3ColInt).FROM(table3).HAVING(table1ColBool.EQ(Bool(true))), `
|
||||
SELECT table3.col_int AS "table3.col_int"
|
||||
FROM db.table3
|
||||
HAVING table1.col_bool = $1;
|
||||
HAVING table1.col_bool = $1::boolean;
|
||||
`, true)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue