MySQL float expressions.

This commit is contained in:
go-jet 2019-07-30 15:04:36 +02:00
parent 6bf9c32c07
commit 163ecf4c42
13 changed files with 401 additions and 85 deletions

13
cast.go
View file

@ -13,6 +13,8 @@ type cast interface {
AS_BIGINT() IntegerExpression AS_BIGINT() IntegerExpression
// Cast expression AS numeric type, using precision and optionally scale // Cast expression AS numeric type, using precision and optionally scale
AS_NUMERIC(precision int, scale ...int) FloatExpression AS_NUMERIC(precision int, scale ...int) FloatExpression
// Cast expression AS numeric type, using precision and optionally scale
AS_DECIMAL() FloatExpression
// Cast expression AS real type // Cast expression AS real type
AS_REAL() FloatExpression AS_REAL() FloatExpression
// Cast expression AS double precision type // Cast expression AS double precision type
@ -56,14 +58,14 @@ func (b *castImpl) serialize(statement statementType, out *sqlBuilder, options .
return castOverride(b.Expression, b.castType)(statement, out, options...) return castOverride(b.Expression, b.castType)(statement, out, options...)
} }
out.writeString("CAST") out.writeString("CAST(")
err := WRAP(b.Expression).serialize(statement, out, options...) err := b.Expression.serialize(statement, out, options...)
if err != nil { if err != nil {
return err return err
} }
out.writeString("AS") out.writeString("AS")
out.writeString(b.castType) out.writeString(b.castType + ")")
return err return err
} }
@ -102,6 +104,11 @@ func (b *castImpl) AS_NUMERIC(precision int, scale ...int) FloatExpression {
return FloatExp(b) return FloatExp(b)
} }
func (b *castImpl) AS_DECIMAL() FloatExpression {
b.castType = "decimal"
return FloatExp(b)
}
// Cast expression AS real type // Cast expression AS real type
func (b *castImpl) AS_REAL() FloatExpression { func (b *castImpl) AS_REAL() FloatExpression {
b.castType = "real" b.castType = "real"

View file

@ -250,6 +250,10 @@ func mapRowToStruct(scanContext *scanContext, groupKey string, structPtrValue re
field := structType.Field(i) field := structType.Field(i)
fieldValue := structValue.Field(i) fieldValue := structValue.Field(i)
if !fieldValue.CanSet() { // private field
continue
}
fieldMap := typeInf.fieldMappings[i] fieldMap := typeInf.fieldMappings[i]
if fieldMap.complexType { if fieldMap.complexType {
@ -466,6 +470,7 @@ func toCommonIdentifier(name string) string {
} }
func initializeValueIfNilPtr(value reflect.Value) { func initializeValueIfNilPtr(value reflect.Value) {
if !value.IsValid() || !value.CanSet() { if !value.IsValid() || !value.CanSet() {
return return
} }

View file

@ -81,7 +81,7 @@ func (n *floatInterfaceImpl) MOD(expression NumericExpression) FloatExpression {
} }
func (n *floatInterfaceImpl) POW(expression NumericExpression) FloatExpression { func (n *floatInterfaceImpl) POW(expression NumericExpression) FloatExpression {
return newBinaryFloatExpression(n.parent, expression, "^") return POWER(n.parent, expression)
} }
//---------------------------------------------------// //---------------------------------------------------//

View file

@ -70,8 +70,8 @@ func TestFloatExpressionMOD(t *testing.T) {
} }
func TestFloatExpressionPOW(t *testing.T) { func TestFloatExpressionPOW(t *testing.T) {
assertPostgreClauseSerialize(t, table1ColFloat.POW(table2ColFloat), "(table1.col_float ^ table2.col_float)") assertPostgreClauseSerialize(t, table1ColFloat.POW(table2ColFloat), "POWER(table1.col_float, table2.col_float)")
assertPostgreClauseSerialize(t, table1ColFloat.POW(Float(2.11)), "(table1.col_float ^ $1)", float64(2.11)) assertPostgreClauseSerialize(t, table1ColFloat.POW(Float(2.11)), "POWER(table1.col_float, $1)", float64(2.11))
} }
func TestFloatExp(t *testing.T) { func TestFloatExp(t *testing.T) {

View file

@ -11,7 +11,7 @@ func ROW(expressions ...Expression) Expression {
// ABSf calculates absolute value from float expression // ABSf calculates absolute value from float expression
func ABSf(floatExpression FloatExpression) FloatExpression { func ABSf(floatExpression FloatExpression) FloatExpression {
return newFloatFunc("ABS", floatExpression) return NewFloatFunc("ABS", floatExpression)
} }
// ABSi calculates absolute value from int expression // ABSi calculates absolute value from int expression
@ -19,62 +19,66 @@ func ABSi(integerExpression IntegerExpression) IntegerExpression {
return newIntegerFunc("ABS", integerExpression) return newIntegerFunc("ABS", integerExpression)
} }
func POWER(base, exponent NumericExpression) FloatExpression {
return NewFloatFunc("POWER", base, exponent)
}
// SQRT calculates square root of numeric expression // SQRT calculates square root of numeric expression
func SQRT(numericExpression NumericExpression) FloatExpression { func SQRT(numericExpression NumericExpression) FloatExpression {
return newFloatFunc("SQRT", numericExpression) return NewFloatFunc("SQRT", numericExpression)
} }
// CBRT calculates cube root of numeric expression // CBRT calculates cube root of numeric expression
func CBRT(numericExpression NumericExpression) FloatExpression { func CBRT(numericExpression NumericExpression) FloatExpression {
return newFloatFunc("CBRT", numericExpression) return NewFloatFunc("CBRT", numericExpression)
} }
// CEIL calculates ceil of float expression // CEIL calculates ceil of float expression
func CEIL(floatExpression FloatExpression) FloatExpression { func CEIL(floatExpression FloatExpression) FloatExpression {
return newFloatFunc("CEIL", floatExpression) return NewFloatFunc("CEIL", floatExpression)
} }
// FLOOR calculates floor of float expression // FLOOR calculates floor of float expression
func FLOOR(floatExpression FloatExpression) FloatExpression { func FLOOR(floatExpression FloatExpression) FloatExpression {
return newFloatFunc("FLOOR", floatExpression) return NewFloatFunc("FLOOR", floatExpression)
} }
// ROUND calculates round of a float expressions with optional precision // ROUND calculates round of a float expressions with optional precision
func ROUND(floatExpression FloatExpression, precision ...IntegerExpression) FloatExpression { func ROUND(floatExpression FloatExpression, precision ...IntegerExpression) FloatExpression {
if len(precision) > 0 { if len(precision) > 0 {
return newFloatFunc("ROUND", floatExpression, precision[0]) return NewFloatFunc("ROUND", floatExpression, precision[0])
} }
return newFloatFunc("ROUND", floatExpression) return NewFloatFunc("ROUND", floatExpression)
} }
// SIGN returns sign of float expression // SIGN returns sign of float expression
func SIGN(floatExpression FloatExpression) FloatExpression { func SIGN(floatExpression FloatExpression) FloatExpression {
return newFloatFunc("SIGN", floatExpression) return NewFloatFunc("SIGN", floatExpression)
} }
// TRUNC calculates trunc of float expression with optional precision // TRUNC calculates trunc of float expression with optional precision
func TRUNC(floatExpression FloatExpression, precision ...IntegerExpression) FloatExpression { func TRUNC(floatExpression FloatExpression, precision ...IntegerExpression) FloatExpression {
if len(precision) > 0 { if len(precision) > 0 {
return newFloatFunc("TRUNC", floatExpression, precision[0]) return NewFloatFunc("TRUNC", floatExpression, precision[0])
} }
return newFloatFunc("TRUNC", floatExpression) return NewFloatFunc("TRUNC", floatExpression)
} }
// LN calculates natural algorithm of float expression // LN calculates natural algorithm of float expression
func LN(floatExpression FloatExpression) FloatExpression { func LN(floatExpression FloatExpression) FloatExpression {
return newFloatFunc("LN", floatExpression) return NewFloatFunc("LN", floatExpression)
} }
// LOG calculates logarithm of float expression // LOG calculates logarithm of float expression
func LOG(floatExpression FloatExpression) FloatExpression { func LOG(floatExpression FloatExpression) FloatExpression {
return newFloatFunc("LOG", floatExpression) return NewFloatFunc("LOG", floatExpression)
} }
// ----------------- Aggregate functions -------------------// // ----------------- Aggregate functions -------------------//
// AVG is aggregate function used to calculate avg value from numeric expression // AVG is aggregate function used to calculate avg value from numeric expression
func AVG(numericExpression NumericExpression) FloatExpression { func AVG(numericExpression NumericExpression) FloatExpression {
return newFloatFunc("AVG", numericExpression) return NewFloatFunc("AVG", numericExpression)
} }
// BIT_AND is aggregate function used to calculates the bitwise AND of all non-null input values, or null if none. // BIT_AND is aggregate function used to calculates the bitwise AND of all non-null input values, or null if none.
@ -109,7 +113,7 @@ func EVERY(boolExpression BoolExpression) BoolExpression {
// MAXf is aggregate function. Returns maximum value of float expression across all input values // MAXf is aggregate function. Returns maximum value of float expression across all input values
func MAXf(floatExpression FloatExpression) FloatExpression { func MAXf(floatExpression FloatExpression) FloatExpression {
return newFloatFunc("MAX", floatExpression) return NewFloatFunc("MAX", floatExpression)
} }
// MAXi is aggregate function. Returns maximum value of int expression across all input values // MAXi is aggregate function. Returns maximum value of int expression across all input values
@ -119,7 +123,7 @@ func MAXi(integerExpression IntegerExpression) IntegerExpression {
// MINf is aggregate function. Returns minimum value of float expression across all input values // MINf is aggregate function. Returns minimum value of float expression across all input values
func MINf(floatExpression FloatExpression) FloatExpression { func MINf(floatExpression FloatExpression) FloatExpression {
return newFloatFunc("MIN", floatExpression) return NewFloatFunc("MIN", floatExpression)
} }
// MINi is aggregate function. Returns minimum value of int expression across all input values // MINi is aggregate function. Returns minimum value of int expression across all input values
@ -129,7 +133,7 @@ func MINi(integerExpression IntegerExpression) IntegerExpression {
// SUMf is aggregate function. Returns sum of expression across all float expressions // SUMf is aggregate function. Returns sum of expression across all float expressions
func SUMf(floatExpression FloatExpression) FloatExpression { func SUMf(floatExpression FloatExpression) FloatExpression {
return newFloatFunc("SUM", floatExpression) return NewFloatFunc("SUM", floatExpression)
} }
// SUMi is aggregate function. Returns sum of expression across all integer expression. // SUMi is aggregate function. Returns sum of expression across all integer expression.
@ -350,7 +354,7 @@ func TO_DATE(dateStr, format StringExpression) DateExpression {
// TO_NUMBER converts string to numeric using format // TO_NUMBER converts string to numeric using format
func TO_NUMBER(floatStr, format StringExpression) FloatExpression { func TO_NUMBER(floatStr, format StringExpression) FloatExpression {
return newFloatFunc("TO_NUMBER", floatStr, format) return NewFloatFunc("TO_NUMBER", floatStr, format)
} }
// TO_TIMESTAMP converts string to time stamp with time zone using format // TO_TIMESTAMP converts string to time stamp with time zone using format
@ -537,7 +541,7 @@ type floatFunc struct {
floatInterfaceImpl floatInterfaceImpl
} }
func newFloatFunc(name string, expressions ...Expression) FloatExpression { func NewFloatFunc(name string, expressions ...Expression) FloatExpression {
floatFunc := &floatFunc{} floatFunc := &floatFunc{}
floatFunc.funcExpressionImpl = *newFunc(name, expressions, floatFunc) floatFunc.funcExpressionImpl = *newFunc(name, expressions, floatFunc)

View file

@ -54,6 +54,7 @@ func AssertStatementSql(t *testing.T, query jet.Statement, expectedQuery string,
queryStr, args, err := query.Sql() queryStr, args, err := query.Sql()
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, queryStr, expectedQuery) assert.Equal(t, queryStr, expectedQuery)
assert.DeepEqual(t, args, expectedArgs) assert.DeepEqual(t, args, expectedArgs)
} }

View file

@ -36,3 +36,26 @@ type ColumnTimestamp jet.ColumnTimestamp
var TimestampColumn = jet.TimestampColumn var TimestampColumn = jet.TimestampColumn
var Timestamp = jet.Timestamp var Timestamp = jet.Timestamp
var CAST = jet.CAST
// ----------------- FUNCTIONS ----------------------//
var ABSf = jet.ABSf
var ABSi = jet.ABSi
var POWER = jet.POWER
var SQRT = jet.SQRT
func CBRT(number jet.NumericExpression) jet.FloatExpression {
return POWER(number, Float(1.0).DIV(Float(3.0)))
}
var CEIL = jet.CEIL
var FLOOR = jet.FLOOR
var ROUND = jet.ROUND
var SIGN = jet.SIGN
var TRUNC = TRUNCATE
var TRUNCATE = func(floatExpression jet.FloatExpression, precision jet.IntegerExpression) jet.FloatExpression {
return jet.NewFloatFunc("TRUNCATE", floatExpression, precision)
}

View file

@ -20,8 +20,8 @@ CREATE TABLE `all_types` (
`medium_int` MEDIUMINT NOT NULL, `medium_int` MEDIUMINT NOT NULL,
`umedium_int` MEDIUMINT unsigned NOT NULL, `umedium_int` MEDIUMINT unsigned NOT NULL,
`int` INT NOT NULL, `integer` INT NOT NULL,
`uint` INT unsigned NOT NULL, `uinteger` INT unsigned NOT NULL,
`big_int` bigint(20) NOT NULL, `big_int` bigint(20) NOT NULL,
`ubig_int` bigint(20) unsigned NOT NULL, `ubig_int` bigint(20) unsigned NOT NULL,
@ -57,6 +57,9 @@ CREATE TABLE `all_types` (
`double` double NOT NULL, `double` double NOT NULL,
`double_ptr` double, `double_ptr` double,
`real` real NOT NULL,
`real_ptr` real,
-- bit values -- bit values
`bit` bit(10) NOT NULL, `bit` bit(10) NOT NULL,
@ -110,8 +113,16 @@ CREATE TABLE `all_types` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
INSERT INTO `all_types` VALUES INSERT INTO `all_types` VALUES
(false, true, -3,3,-14,14,-150,150,-1600,1600,-17000,17000,-3,3,-14,14,-150,150,-1600,1600,-17000,17000,1.11,1.11,2.22,2.22,3.33,3.33,4.44,4.44,_binary '\0',_binary '\0','2008-07-04','2008-07-04','2011-12-18 13:17:17','2011-12-18 13:17:17','2007-12-31 23:00:01','2007-12-31 23:00:01',2004,2004,'char','char','varchar','varchar',_binary 'binary\0\0\0\0\0\0\0\0\0\0\0\0\0\0',_binary 'binary\0\0\0\0\0\0\0\0\0\0\0\0\0\0',_binary 'varbinary',_binary 'varbinary',_binary 'blob',_binary 'blob','text','text','value1','value1','s1','s2','{\"key1\": \"value1\", \"key2\": \"value2\"}','{\"key1\": \"value1\", \"key2\": \"value2\"}'), (false, true,
(false, NULL, -3,3,-14,14,-150,150,-1600,1600,-17000,17000,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1.11,NULL,2.22,NULL,3.33,NULL,4.44,NULL,_binary '\0',NULL,'2008-07-04',NULL,'2011-12-18 13:17:17',NULL,'2007-12-31 23:00:01',NULL,2004,NULL,'char',NULL,'varchar',NULL,_binary 'binary\0\0\0\0\0\0\0\0\0\0\0\0\0\0',NULL,_binary 'varbinary',NULL,_binary 'blob',NULL,'text',NULL,'value1',NULL,'s1',NULL,'{\"key1\": \"value1\", \"key2\": \"value2\"}',NULL); -3,3,-14,14,-150,150,-1600,1600,-17000,17000,
-3,3,-14,14,-150,150,-1600,1600,-17000,17000,
1.11,1.11,2.22,2.22,3.33,3.33,4.44,4.44,5.55,5.55,
_binary '\0',_binary '\0','2008-07-04','2008-07-04','2011-12-18 13:17:17','2011-12-18 13:17:17','2007-12-31 23:00:01','2007-12-31 23:00:01',2004,2004,'char','char','varchar','varchar',_binary 'binary\0\0\0\0\0\0\0\0\0\0\0\0\0\0',_binary 'binary\0\0\0\0\0\0\0\0\0\0\0\0\0\0',_binary 'varbinary',_binary 'varbinary',_binary 'blob',_binary 'blob','text','text','value1','value1','s1','s2','{\"key1\": \"value1\", \"key2\": \"value2\"}','{\"key1\": \"value1\", \"key2\": \"value2\"}'),
(false, NULL,
-3,3,-14,14,-150,150,-1600,1600,-17000,17000,
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
1.11,NULL,2.22,NULL,3.33,NULL,4.44,NULL,5.55,NULL,
_binary '\0',NULL,'2008-07-04',NULL,'2011-12-18 13:17:17',NULL,'2007-12-31 23:00:01',NULL,2004,NULL,'char',NULL,'varchar',NULL,_binary 'binary\0\0\0\0\0\0\0\0\0\0\0\0\0\0',NULL,_binary 'varbinary',NULL,_binary 'blob',NULL,'text',NULL,'value1',NULL,'s1',NULL,'{\"key1\": \"value1\", \"key2\": \"value2\"}',NULL);

View file

@ -110,7 +110,7 @@ INSERT INTO test_sample.ALL_types(
xml_ptr, xml, xml_ptr, xml,
json_ptr, json, jsonb_ptr, jsonb, json_ptr, json, jsonb_ptr, jsonb,
integer_array_ptr, integer_array, text_array_ptr, text_array, jsonb_array, text_multi_dim_array_ptr, text_multi_dim_array) integer_array_ptr, integer_array, text_array_ptr, text_array, jsonb_array, text_multi_dim_array_ptr, text_multi_dim_array)
VALUES (1, 1, 300, 300, 50000, 5000, 11.44, 11.44, 55.77, 55.77, 99.1, 99.1, 11111111.22, 11111111.22, DEFAULT, DEFAULT, DEFAULT, VALUES (1, 1, 300, 300, 50000, 5000, 1.11, 1.11, 2.22, 2.22, 5.55, 5.55, 11111111.22, 11111111.22, DEFAULT, DEFAULT, DEFAULT,
-- 100000, 100000, -- 100000, 100000,
'ABBA', 'ABBA', 'JOHN', 'JOHN', 'Some text', 'Some text', 'ABBA', 'ABBA', 'JOHN', 'JOHN', 'Some text', 'Some text',
'bytea', 'bytea', 'bytea', 'bytea',
@ -124,7 +124,7 @@ VALUES (1, 1, 300, 300, 50000, 5000, 11.44, 11.44, 55.77, 55.77, 99.1, 99.1, 111
'{"a": 1, "b": 3}', '{"a": 1, "b": 3}', '{"a": 1, "b": 3}', '{"a": 1, "b": 3}', '{"a": 1, "b": 3}', '{"a": 1, "b": 3}', '{"a": 1, "b": 3}', '{"a": 1, "b": 3}',
'{1, 2, 3}', '{1, 2, 3}', '{"breakfast", "consulting"}', '{"breakfast", "consulting"}', ARRAY['{"a": 1, "b": 2}'::jsonb, '{"a":3, "b": 4}'::jsonb], '{{"meeting", "lunch"}, {"training", "presentation"}}', '{{"meeting", "lunch"}, {"training", "presentation"}}') '{1, 2, 3}', '{1, 2, 3}', '{"breakfast", "consulting"}', '{"breakfast", "consulting"}', ARRAY['{"a": 1, "b": 2}'::jsonb, '{"a":3, "b": 4}'::jsonb], '{{"meeting", "lunch"}, {"training", "presentation"}}', '{{"meeting", "lunch"}, {"training", "presentation"}}')
, ,
(NULL, 1, NULL, 300, NULL, 5000, NULL, 11.44, NULL, 55.77, NULL, 99.1, NULL, 11111111.22, DEFAULT, DEFAULT, DEFAULT, (NULL, 1, NULL, 300, NULL, 5000, NULL, 1.11, NULL, 2.22, NULL, 5.55, NULL, 11111111.22, DEFAULT, DEFAULT, DEFAULT,
-- NULL, 100000, -- NULL, 100000,
NULL, 'ABBA', NULL, 'JOHN', NULL, 'Some text', NULL, 'ABBA', NULL, 'JOHN', NULL, 'Some text',
NULL, 'bytea', NULL, 'bytea',

View file

@ -4,6 +4,7 @@ import (
"github.com/go-jet/jet/internal/testutils" "github.com/go-jet/jet/internal/testutils"
"github.com/go-jet/jet/tests/.gentestdata/mysql/test_sample/model" "github.com/go-jet/jet/tests/.gentestdata/mysql/test_sample/model"
. "github.com/go-jet/jet/tests/.gentestdata/mysql/test_sample/table" . "github.com/go-jet/jet/tests/.gentestdata/mysql/test_sample/table"
"github.com/go-jet/jet/tests/testdata/common"
. "github.com/go-jet/jet/mysql" . "github.com/go-jet/jet/mysql"
@ -93,11 +94,106 @@ FROM test_sample.all_types;
assert.NilError(t, err) assert.NilError(t, err)
testutils.JsonPrint(dest)
testutils.AssertJSONFile(t, "./testdata/common/bool_operators.json", dest) testutils.AssertJSONFile(t, "./testdata/common/bool_operators.json", dest)
} }
func TestFloatOperators(t *testing.T) {
query := AllTypes.SELECT(
AllTypes.Numeric.EQ(AllTypes.Numeric).AS("eq1"),
AllTypes.Decimal.EQ(Float(12.22)).AS("eq2"),
AllTypes.Real.EQ(Float(12.12)).AS("eq3"),
AllTypes.Numeric.IS_DISTINCT_FROM(AllTypes.Numeric).AS("distinct1"),
AllTypes.Decimal.IS_DISTINCT_FROM(Float(12)).AS("distinct2"),
AllTypes.Real.IS_DISTINCT_FROM(Float(12.12)).AS("distinct3"),
AllTypes.Numeric.IS_NOT_DISTINCT_FROM(AllTypes.Numeric).AS("not_distinct1"),
AllTypes.Decimal.IS_NOT_DISTINCT_FROM(Float(12)).AS("not_distinct2"),
AllTypes.Real.IS_NOT_DISTINCT_FROM(Float(12.12)).AS("not_distinct3"),
AllTypes.Numeric.LT(Float(124)).AS("lt1"),
AllTypes.Numeric.LT(Float(34.56)).AS("lt2"),
AllTypes.Numeric.GT(Float(124)).AS("gt1"),
AllTypes.Numeric.GT(Float(34.56)).AS("gt2"),
TRUNC(AllTypes.Decimal.ADD(AllTypes.Decimal), Int(2)).AS("add1"),
TRUNC(AllTypes.Decimal.ADD(Float(11.22)), Int(2)).AS("add2"),
TRUNC(AllTypes.Decimal.SUB(AllTypes.DecimalPtr), Int(2)).AS("sub1"),
TRUNC(AllTypes.Decimal.SUB(Float(11.22)), Int(2)).AS("sub2"),
TRUNC(AllTypes.Decimal.MUL(AllTypes.DecimalPtr), Int(2)).AS("mul1"),
TRUNC(AllTypes.Decimal.MUL(Float(11.22)), Int(2)).AS("mul2"),
TRUNC(AllTypes.Decimal.DIV(AllTypes.DecimalPtr), Int(2)).AS("div1"),
TRUNC(AllTypes.Decimal.DIV(Float(11.22)), Int(2)).AS("div2"),
TRUNC(AllTypes.Decimal.MOD(AllTypes.DecimalPtr), Int(2)).AS("mod1"),
TRUNC(AllTypes.Decimal.MOD(Float(11.22)), Int(2)).AS("mod2"),
TRUNC(AllTypes.Decimal.POW(AllTypes.DecimalPtr), Int(2)).AS("pow1"),
TRUNC(AllTypes.Decimal.POW(Float(2.1)), Int(2)).AS("pow2"),
TRUNC(ABSf(AllTypes.Decimal), Int(2)).AS("abs"),
TRUNC(POWER(AllTypes.Decimal, Float(2.1)), Int(2)).AS("power"),
TRUNC(SQRT(AllTypes.Decimal), Int(2)).AS("sqrt"),
TRUNC(CBRT(AllTypes.Decimal), Int(2)).AS("cbrt"),
CEIL(AllTypes.Real).AS("ceil"),
FLOOR(AllTypes.Real).AS("floor"),
ROUND(AllTypes.Decimal).AS("round1"),
ROUND(AllTypes.Decimal, Int(2)).AS("round2"),
SIGN(AllTypes.Real).AS("sign"),
TRUNC(AllTypes.Decimal, Int(1)).AS("trunc"),
).LIMIT(2)
queryStr, _, err := query.Sql()
assert.NilError(t, err)
assert.Equal(t, queryStr, `
SELECT (all_types.numeric = all_types.numeric) AS "eq1",
(all_types.decimal = ?) AS "eq2",
(all_types.real = ?) AS "eq3",
(NOT all_types.numeric <=> all_types.numeric) AS "distinct1",
(NOT all_types.decimal <=> ?) AS "distinct2",
(NOT all_types.real <=> ?) AS "distinct3",
(all_types.numeric <=> all_types.numeric) AS "not_distinct1",
(all_types.decimal <=> ?) AS "not_distinct2",
(all_types.real <=> ?) AS "not_distinct3",
(all_types.numeric < ?) AS "lt1",
(all_types.numeric < ?) AS "lt2",
(all_types.numeric > ?) AS "gt1",
(all_types.numeric > ?) AS "gt2",
TRUNCATE((all_types.decimal + all_types.decimal), ?) AS "add1",
TRUNCATE((all_types.decimal + ?), ?) AS "add2",
TRUNCATE((all_types.decimal - all_types.decimal_ptr), ?) AS "sub1",
TRUNCATE((all_types.decimal - ?), ?) AS "sub2",
TRUNCATE((all_types.decimal * all_types.decimal_ptr), ?) AS "mul1",
TRUNCATE((all_types.decimal * ?), ?) AS "mul2",
TRUNCATE((all_types.decimal / all_types.decimal_ptr), ?) AS "div1",
TRUNCATE((all_types.decimal / ?), ?) AS "div2",
TRUNCATE((all_types.decimal % all_types.decimal_ptr), ?) AS "mod1",
TRUNCATE((all_types.decimal % ?), ?) AS "mod2",
TRUNCATE(POWER(all_types.decimal, all_types.decimal_ptr), ?) AS "pow1",
TRUNCATE(POWER(all_types.decimal, ?), ?) AS "pow2",
TRUNCATE(ABS(all_types.decimal), ?) AS "abs",
TRUNCATE(POWER(all_types.decimal, ?), ?) AS "power",
TRUNCATE(SQRT(all_types.decimal), ?) AS "sqrt",
TRUNCATE(POWER(all_types.decimal, (? / ?)), ?) AS "cbrt",
CEIL(all_types.real) AS "ceil",
FLOOR(all_types.real) AS "floor",
ROUND(all_types.decimal) AS "round1",
ROUND(all_types.decimal, ?) AS "round2",
SIGN(all_types.real) AS "sign",
TRUNCATE(all_types.decimal, ?) AS "trunc"
FROM test_sample.all_types
LIMIT ?;
`)
var dest []struct {
common.FloatExpressionTestResult `alias:"."`
}
err = query.Query(db, &dest)
assert.NilError(t, err)
testutils.AssertJSONFile(t, "./testdata/common/float_operators.json", dest)
}
var allTypesJson = ` var allTypesJson = `
[ [
{ {
@ -109,8 +205,8 @@ var allTypesJson = `
"UsmallInt": 14, "UsmallInt": 14,
"MediumInt": -150, "MediumInt": -150,
"UmediumInt": 150, "UmediumInt": 150,
"Int": -1600, "Integer": -1600,
"Uint": 1600, "Uinteger": 1600,
"BigInt": -17000, "BigInt": -17000,
"UbigInt": 17000, "UbigInt": 17000,
"TinyIntPtr": -3, "TinyIntPtr": -3,
@ -131,6 +227,8 @@ var allTypesJson = `
"FloatPtr": 3.33, "FloatPtr": 3.33,
"Double": 4.44, "Double": 4.44,
"DoublePtr": 4.44, "DoublePtr": 4.44,
"Real": 5.55,
"RealPtr": 5.55,
"Bit": "\u0000\u0003", "Bit": "\u0000\u0003",
"BitPtr": "\u0000\u0003", "BitPtr": "\u0000\u0003",
"Date": "2008-07-04T00:00:00Z", "Date": "2008-07-04T00:00:00Z",
@ -169,8 +267,8 @@ var allTypesJson = `
"UsmallInt": 14, "UsmallInt": 14,
"MediumInt": -150, "MediumInt": -150,
"UmediumInt": 150, "UmediumInt": 150,
"Int": -1600, "Integer": -1600,
"Uint": 1600, "Uinteger": 1600,
"BigInt": -17000, "BigInt": -17000,
"UbigInt": 17000, "UbigInt": 17000,
"TinyIntPtr": null, "TinyIntPtr": null,
@ -191,6 +289,8 @@ var allTypesJson = `
"FloatPtr": null, "FloatPtr": null,
"Double": 4.44, "Double": 4.44,
"DoublePtr": null, "DoublePtr": null,
"Real": 5.55,
"RealPtr": null,
"Bit": "\u0000\u0003", "Bit": "\u0000\u0003",
"BitPtr": null, "BitPtr": null,
"Date": "2008-07-04T00:00:00Z", "Date": "2008-07-04T00:00:00Z",

View file

@ -5,6 +5,7 @@ import (
"github.com/go-jet/jet/internal/testutils" "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/model"
. "github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/table" . "github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/table"
"github.com/go-jet/jet/tests/testdata/common"
"github.com/google/uuid" "github.com/google/uuid"
"gotest.tools/assert" "gotest.tools/assert"
"testing" "testing"
@ -245,52 +246,100 @@ LIMIT $5;
func TestFloatOperators(t *testing.T) { func TestFloatOperators(t *testing.T) {
query := AllTypes.SELECT( query := AllTypes.SELECT(
AllTypes.Numeric.EQ(AllTypes.Numeric), AllTypes.Numeric.EQ(AllTypes.Numeric).AS("eq1"),
AllTypes.Decimal.EQ(Float(12)), AllTypes.Decimal.EQ(Float(12.22)).AS("eq2"),
AllTypes.Real.EQ(Float(12.12)), AllTypes.Real.EQ(Float(12.12)).AS("eq3"),
AllTypes.Numeric.IS_DISTINCT_FROM(AllTypes.Numeric), AllTypes.Numeric.IS_DISTINCT_FROM(AllTypes.Numeric).AS("distinct1"),
AllTypes.Decimal.IS_DISTINCT_FROM(Float(12)), AllTypes.Decimal.IS_DISTINCT_FROM(Float(12)).AS("distinct2"),
AllTypes.Real.IS_DISTINCT_FROM(Float(12.12)), AllTypes.Real.IS_DISTINCT_FROM(Float(12.12)).AS("distinct3"),
AllTypes.Numeric.IS_NOT_DISTINCT_FROM(AllTypes.Numeric), AllTypes.Numeric.IS_NOT_DISTINCT_FROM(AllTypes.Numeric).AS("not_distinct1"),
AllTypes.Decimal.IS_NOT_DISTINCT_FROM(Float(12)), AllTypes.Decimal.IS_NOT_DISTINCT_FROM(Float(12)).AS("not_distinct2"),
AllTypes.Real.IS_NOT_DISTINCT_FROM(Float(12.12)), AllTypes.Real.IS_NOT_DISTINCT_FROM(Float(12.12)).AS("not_distinct3"),
//AllTypes.Numeric.LT(AllTypes.Integer), AllTypes.Numeric.LT(Float(124)).AS("lt1"),
AllTypes.Numeric.LT(Float(124)), AllTypes.Numeric.LT(Float(34.56)).AS("lt2"),
AllTypes.Numeric.LT(Float(34.56)), AllTypes.Numeric.GT(Float(124)).AS("gt1"),
//AllTypes.Numeric.GT(AllTypes.Smallint), AllTypes.Numeric.GT(Float(34.56)).AS("gt2"),
AllTypes.Numeric.GT(Float(124)),
AllTypes.Numeric.GT(Float(34.56)),
AllTypes.Real.ADD(AllTypes.RealPtr), TRUNC(AllTypes.Decimal.ADD(AllTypes.Decimal), Int(2)).AS("add1"),
AllTypes.Real.ADD(Float(11.22)), TRUNC(AllTypes.Decimal.ADD(Float(11.22)), Int(2)).AS("add2"),
AllTypes.Real.SUB(AllTypes.RealPtr), TRUNC(AllTypes.Decimal.SUB(AllTypes.DecimalPtr), Int(2)).AS("sub1"),
AllTypes.Real.SUB(Float(11.22)), TRUNC(AllTypes.Decimal.SUB(Float(11.22)), Int(2)).AS("sub2"),
AllTypes.Real.MUL(AllTypes.RealPtr), TRUNC(AllTypes.Decimal.MUL(AllTypes.DecimalPtr), Int(2)).AS("mul1"),
AllTypes.Real.MUL(Float(11.22)), TRUNC(AllTypes.Decimal.MUL(Float(11.22)), Int(2)).AS("mul2"),
AllTypes.Real.DIV(AllTypes.RealPtr), TRUNC(AllTypes.Decimal.DIV(AllTypes.DecimalPtr), Int(2)).AS("div1"),
AllTypes.Real.DIV(Float(11.22)), TRUNC(AllTypes.Decimal.DIV(Float(11.22)), Int(2)).AS("div2"),
AllTypes.Decimal.MOD(AllTypes.Decimal), TRUNC(AllTypes.Decimal.MOD(AllTypes.DecimalPtr), Int(2)).AS("mod1"),
AllTypes.Decimal.MOD(Float(11.22)), TRUNC(AllTypes.Decimal.MOD(Float(11.22)), Int(2)).AS("mod2"),
AllTypes.Real.POW(AllTypes.RealPtr), TRUNC(AllTypes.Decimal.POW(AllTypes.DecimalPtr), Int(2)).AS("pow1"),
AllTypes.Real.POW(Float(11.22)), TRUNC(AllTypes.Decimal.POW(Float(2.1)), Int(2)).AS("pow2"),
ABSf(AllTypes.Real), TRUNC(ABSf(AllTypes.Decimal), Int(2)).AS("abs"),
SQRT(AllTypes.Real), TRUNC(POWER(AllTypes.Decimal, Float(2.1)), Int(2)).AS("power"),
CBRT(AllTypes.Real), TRUNC(SQRT(AllTypes.Decimal), Int(2)).AS("sqrt"),
CEIL(AllTypes.Real), TRUNC(CAST(CBRT(AllTypes.Decimal)).AS_DECIMAL(), Int(2)).AS("cbrt"),
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()) CEIL(AllTypes.Real).AS("ceil"),
FLOOR(AllTypes.Real).AS("floor"),
ROUND(AllTypes.Decimal).AS("round1"),
ROUND(AllTypes.Decimal, AllTypes.Integer).AS("round2"),
err := query.Query(db, &struct{}{}) SIGN(AllTypes.Real).AS("sign"),
TRUNC(AllTypes.Decimal, Int(1)).AS("trunc"),
).LIMIT(2)
queryStr, _, err := query.Sql()
assert.NilError(t, err)
assert.Equal(t, queryStr, `
SELECT (all_types.numeric = all_types.numeric) AS "eq1",
(all_types.decimal = $1) AS "eq2",
(all_types.real = $2) AS "eq3",
(all_types.numeric IS DISTINCT FROM all_types.numeric) AS "distinct1",
(all_types.decimal IS DISTINCT FROM $3) AS "distinct2",
(all_types.real IS DISTINCT FROM $4) AS "distinct3",
(all_types.numeric IS NOT DISTINCT FROM all_types.numeric) AS "not_distinct1",
(all_types.decimal IS NOT DISTINCT FROM $5) AS "not_distinct2",
(all_types.real IS NOT DISTINCT FROM $6) AS "not_distinct3",
(all_types.numeric < $7) AS "lt1",
(all_types.numeric < $8) AS "lt2",
(all_types.numeric > $9) AS "gt1",
(all_types.numeric > $10) AS "gt2",
TRUNC((all_types.decimal + all_types.decimal), $11) AS "add1",
TRUNC((all_types.decimal + $12), $13) AS "add2",
TRUNC((all_types.decimal - all_types.decimal_ptr), $14) AS "sub1",
TRUNC((all_types.decimal - $15), $16) AS "sub2",
TRUNC((all_types.decimal * all_types.decimal_ptr), $17) AS "mul1",
TRUNC((all_types.decimal * $18), $19) AS "mul2",
TRUNC((all_types.decimal / all_types.decimal_ptr), $20) AS "div1",
TRUNC((all_types.decimal / $21), $22) AS "div2",
TRUNC((all_types.decimal % all_types.decimal_ptr), $23) AS "mod1",
TRUNC((all_types.decimal % $24), $25) AS "mod2",
TRUNC(POWER(all_types.decimal, all_types.decimal_ptr), $26) AS "pow1",
TRUNC(POWER(all_types.decimal, $27), $28) AS "pow2",
TRUNC(ABS(all_types.decimal), $29) AS "abs",
TRUNC(POWER(all_types.decimal, $30), $31) AS "power",
TRUNC(SQRT(all_types.decimal), $32) AS "sqrt",
TRUNC(CBRT(all_types.decimal)::decimal, $33) AS "cbrt",
CEIL(all_types.real) AS "ceil",
FLOOR(all_types.real) AS "floor",
ROUND(all_types.decimal) AS "round1",
ROUND(all_types.decimal, all_types.integer) AS "round2",
SIGN(all_types.real) AS "sign",
TRUNC(all_types.decimal, $34) AS "trunc"
FROM test_sample.all_types
LIMIT $35;
`)
var dest []struct {
common.FloatExpressionTestResult `alias:"."`
}
err = query.Query(db, &dest)
assert.NilError(t, err) assert.NilError(t, err)
//testutils.JsonPrint(dest)
testutils.AssertJSONFile(t, "./testdata/common/float_operators.json", dest)
} }
func TestIntegerOperators(t *testing.T) { func TestIntegerOperators(t *testing.T) {
@ -591,12 +640,12 @@ var allTypesRow0 = model.AllTypes{
Integer: 300, Integer: 300,
BigintPtr: Int64Ptr(50000), BigintPtr: Int64Ptr(50000),
Bigint: 5000, Bigint: 5000,
DecimalPtr: Float64Ptr(11.44), DecimalPtr: Float64Ptr(1.11),
Decimal: 11.44, Decimal: 1.11,
NumericPtr: Float64Ptr(55.77), NumericPtr: Float64Ptr(2.22),
Numeric: 55.77, Numeric: 2.22,
RealPtr: Float32Ptr(99.1), RealPtr: Float32Ptr(5.55),
Real: 99.1, Real: 5.55,
DoublePrecisionPtr: Float64Ptr(11111111.22), DoublePrecisionPtr: Float64Ptr(11111111.22),
DoublePrecision: 11111111.22, DoublePrecision: 11111111.22,
Smallserial: 1, Smallserial: 1,
@ -658,11 +707,11 @@ var allTypesRow1 = model.AllTypes{
BigintPtr: nil, BigintPtr: nil,
Bigint: 5000, Bigint: 5000,
DecimalPtr: nil, DecimalPtr: nil,
Decimal: 11.44, Decimal: 1.11,
NumericPtr: nil, NumericPtr: nil,
Numeric: 55.77, Numeric: 2.22,
RealPtr: nil, RealPtr: nil,
Real: 99.1, Real: 5.55,
DoublePrecisionPtr: nil, DoublePrecisionPtr: nil,
DoublePrecision: 11111111.22, DoublePrecision: 11111111.22,
Smallserial: 2, Smallserial: 2,

View file

@ -0,0 +1,40 @@
package common
type FloatExpressionTestResult struct {
Eq1 *bool
Eq2 *bool
Eq3 *bool
Distinct1 *bool
Distinct2 *bool
Distinct3 *bool
NotDistinct1 *bool
NotDistinct2 *bool
NotDistinct3 *bool
Lt1 *bool
Lt2 *bool
Gt1 *bool
Gt2 *bool
Add1 *float64
Add2 *float64
Sub1 *float64
Sub2 *float64
Mul1 *float64
Mul2 *float64
Div1 *float64
Div2 *float64
Mod1 *float64
Mod2 *float64
Pow1 *float64
Pow2 *float64
Abs *float64
Power *float64
Sqrt *float64
Cbrt *float64
Ceil *float64
Floor *float64
Round1 *float64
Round2 *float64
Sign *float64
Trunc *float64
}

View file

@ -0,0 +1,76 @@
[
{
"Eq1": true,
"Eq2": false,
"Eq3": false,
"Distinct1": false,
"Distinct2": true,
"Distinct3": true,
"NotDistinct1": true,
"NotDistinct2": false,
"NotDistinct3": false,
"Lt1": true,
"Lt2": true,
"Gt1": false,
"Gt2": false,
"Add1": 2.22,
"Add2": 12.33,
"Sub1": 0,
"Sub2": -10.11,
"Mul1": 1.23,
"Mul2": 12.45,
"Div1": 1,
"Div2": 0.09,
"Mod1": 0,
"Mod2": 1.11,
"Pow1": 1.12,
"Pow2": 1.24,
"Abs": 1.11,
"Power": 1.24,
"Sqrt": 1.05,
"Cbrt": 1.03,
"Ceil": 6,
"Floor": 5,
"Round1": 1,
"Round2": 1.11,
"Sign": 1,
"Trunc": 1.1
},
{
"Eq1": true,
"Eq2": false,
"Eq3": false,
"Distinct1": false,
"Distinct2": true,
"Distinct3": true,
"NotDistinct1": true,
"NotDistinct2": false,
"NotDistinct3": false,
"Lt1": true,
"Lt2": true,
"Gt1": false,
"Gt2": false,
"Add1": 2.22,
"Add2": 12.33,
"Sub1": null,
"Sub2": -10.11,
"Mul1": null,
"Mul2": 12.45,
"Div1": null,
"Div2": 0.09,
"Mod1": null,
"Mod2": 1.11,
"Pow1": null,
"Pow2": 1.24,
"Abs": 1.11,
"Power": 1.24,
"Sqrt": 1.05,
"Cbrt": 1.03,
"Ceil": 6,
"Floor": 5,
"Round1": 1,
"Round2": 1.11,
"Sign": 1,
"Trunc": 1.1
}
]