diff --git a/execution/execution.go b/execution/execution.go index e29f46a..363b0f4 100644 --- a/execution/execution.go +++ b/execution/execution.go @@ -271,7 +271,6 @@ func mapRowToStruct(scanContext *scanContext, groupKey string, structPtrValue re if err != nil { panic("jet: " + err.Error() + ", " + fieldToString(&field) + " of type " + structType.String()) - return } updated = true } else { diff --git a/internal/jet/clause.go b/internal/jet/clause.go index b64dc0e..95283a1 100644 --- a/internal/jet/clause.go +++ b/internal/jet/clause.go @@ -11,7 +11,7 @@ type Clause interface { type ClauseWithProjections interface { Clause - projections() []Projection + projections() ProjectionList } type ClauseSelect struct { @@ -19,7 +19,7 @@ type ClauseSelect struct { Projections []Projection } -func (s *ClauseSelect) projections() []Projection { +func (s *ClauseSelect) projections() ProjectionList { return s.Projections } @@ -172,7 +172,7 @@ type ClauseSetStmtOperator struct { Offset ClauseOffset } -func (s *ClauseSetStmtOperator) projections() []Projection { +func (s *ClauseSetStmtOperator) projections() ProjectionList { if len(s.Selects) > 0 { return s.Selects[0].projections() } diff --git a/internal/jet/func_expression.go b/internal/jet/func_expression.go index 45ee0f5..2e6e9dd 100644 --- a/internal/jet/func_expression.go +++ b/internal/jet/func_expression.go @@ -17,10 +17,12 @@ func ABSi(integerExpression IntegerExpression) IntegerExpression { return newIntegerFunc("ABS", integerExpression) } +// POW calculates power of base with exponent func POW(base, exponent NumericExpression) FloatExpression { return NewFloatFunc("POW", base, exponent) } +// POWER calculates power of base with exponent func POWER(base, exponent NumericExpression) FloatExpression { return NewFloatFunc("POWER", base, exponent) } @@ -202,12 +204,14 @@ func CHR(integerExpression IntegerExpression) StringExpression { return newStringFunc("CHR", integerExpression) } +// CONCAT adds two or more expressions together func CONCAT(expressions ...Expression) StringExpression { return newStringFunc("CONCAT", expressions...) } -func CONCAT_WS(expressions ...Expression) StringExpression { - return newStringFunc("CONCAT_WS", expressions...) +// CONCAT_WS adds two or more expressions together with a separator. +func CONCAT_WS(separator Expression, expressions ...Expression) StringExpression { + return newStringFunc("CONCAT_WS", append([]Expression{separator}, expressions...)...) } // CONVERT converts string to dest_encoding. The original encoding is @@ -240,6 +244,7 @@ func DECODE(data StringExpression, format StringExpression) StringExpression { return newStringFunc("DECODE", data, format) } +// FORMAT formats a number to a format like "#,###,###.##", rounded to a specified number of decimal places, then it returns the result as a string. func FORMAT(formatStr StringExpression, formatArgs ...Expression) StringExpression { args := []Expression{formatStr} args = append(args, formatArgs...) @@ -341,6 +346,7 @@ func TO_HEX(number IntegerExpression) StringExpression { return newStringFunc("TO_HEX", number) } +// REGEXP_LIKE Returns 1 if the string expr matches the regular expression specified by the pattern pat, 0 otherwise. func REGEXP_LIKE(stringExp StringExpression, pattern StringExpression, matchType ...string) BoolExpression { if len(matchType) > 0 { return newBoolFunc("REGEXP_LIKE", stringExp, pattern, String(matchType[0], true)) diff --git a/internal/jet/select_table.go b/internal/jet/select_table.go index e32d714..6894bc0 100644 --- a/internal/jet/select_table.go +++ b/internal/jet/select_table.go @@ -10,17 +10,14 @@ type SelectTableImpl struct { selectStmt StatementWithProjections alias string - projections []Projection + projections ProjectionList } func NewSelectTable(selectStmt StatementWithProjections, alias string) SelectTableImpl { selectTable := SelectTableImpl{selectStmt: selectStmt, alias: alias} - for _, projection := range selectStmt.projections() { - newProjection := projection.fromImpl(&selectTable) - - selectTable.projections = append(selectTable.projections, newProjection) - } + projectionList := selectStmt.projections().fromImpl(&selectTable) + selectTable.projections = projectionList.(ProjectionList) return selectTable } diff --git a/internal/jet/statement.go b/internal/jet/statement.go index 4523750..23909c2 100644 --- a/internal/jet/statement.go +++ b/internal/jet/statement.go @@ -39,7 +39,7 @@ type StatementWithProjections interface { } type HasProjections interface { - projections() []Projection + projections() ProjectionList } type SerializerStatementInterfaceImpl struct { @@ -116,7 +116,7 @@ type StatementImpl struct { Clauses []Clause } -func (s *StatementImpl) projections() []Projection { +func (s *StatementImpl) projections() ProjectionList { for _, clause := range s.Clauses { if selectClause, ok := clause.(ClauseWithProjections); ok { return selectClause.projections() diff --git a/mysql/functions.go b/mysql/functions.go index 073d615..b4611f2 100644 --- a/mysql/functions.go +++ b/mysql/functions.go @@ -2,108 +2,182 @@ package mysql import "github.com/go-jet/jet/internal/jet" +// ROW is construct one table row from list of expressions. +var ROW = jet.ROW + // ------------------ Mathematical functions ---------------// -var POW = jet.POW -var LN = jet.LN -var LOG = jet.LOG - +// ABSf calculates absolute value from float expression var ABSf = jet.ABSf + +// ABSi calculates absolute value from int expression var ABSi = jet.ABSi + +// POW calculates power of base with exponent +var POW = jet.POW + +// POWER calculates power of base with exponent var POWER = jet.POWER + +// SQRT calculates square root of numeric expression var SQRT = jet.SQRT +// CBRT calculates cube root of numeric expression func CBRT(number jet.NumericExpression) jet.FloatExpression { return POWER(number, Float(1.0).DIV(Float(3.0))) } +// CEIL calculates ceil of float expression var CEIL = jet.CEIL + +// FLOOR calculates floor of float expression var FLOOR = jet.FLOOR + +// ROUND calculates round of a float expressions with optional precision var ROUND = jet.ROUND + +// SIGN returns sign of float expression var SIGN = jet.SIGN + +// TRUNC calculates trunc of float expression with precision var TRUNC = TRUNCATE +// TRUNCATE calculates trunc of float expression with precision var TRUNCATE = func(floatExpression jet.FloatExpression, precision jet.IntegerExpression) jet.FloatExpression { return jet.NewFloatFunc("TRUNCATE", floatExpression, precision) } -var BIT_NOT = jet.BIT_NOT +// LN calculates natural algorithm of float expression +var LN = jet.LN + +// LOG calculates logarithm of float expression +var LOG = jet.LOG // ----------------- Aggregate functions -------------------// +// AVG is aggregate function used to calculate avg value from numeric expression +var AVG = jet.AVG + +// BIT_AND is aggregate function used to calculates the bitwise AND of all non-null input values, or null if none. var BIT_AND = jet.BIT_AND + +// BIT_OR is aggregate function used to calculates the bitwise OR of all non-null input values, or null if none. var BIT_OR = jet.BIT_OR -var BOOL_AND = jet.BOOL_AND -var BOOL_OR = jet.BOOL_OR -var EVERY = jet.EVERY + +// COUNT is aggregate function. Returns number of input rows for which the value of expression is not null. +var COUNT = jet.COUNT + +// MAXi is aggregate function. Returns maximum value of int expression across all input values var MAXi = jet.MAXi + +// MAXf is aggregate function. Returns maximum value of float expression across all input values +var MAXf = jet.MAXf + +// MINi is aggregate function. Returns minimum value of int expression across all input values var MINi = jet.MINi + +// MINf is aggregate function. Returns minimum value of float expression across all input values +var MINf = jet.MINf + +// SUMi is aggregate function. Returns sum of expression across all integer expression. var SUMi = jet.SUMi +// SUMi is aggregate function. Returns sum of expression across all integer expression. var SUMf = jet.SUMf -var AVG = jet.AVG -var MAXf = jet.MAXf -var MINf = jet.MINf -var COUNT = jet.COUNT //--------------------- String functions ------------------// -var REGEXP_LIKE = jet.REGEXP_LIKE +// BIT_LENGTH returns number of bits in string expression var BIT_LENGTH = jet.BIT_LENGTH + +// CHAR_LENGTH returns number of characters in string expression var CHAR_LENGTH = jet.CHAR_LENGTH + +// OCTET_LENGTH returns number of bytes in string expression var OCTET_LENGTH = jet.OCTET_LENGTH + +// LOWER returns string expression in lower case var LOWER = jet.LOWER + +// UPPER returns string expression in upper case var UPPER = jet.UPPER -var BTRIM = jet.BTRIM + +// LTRIM removes the longest string containing only characters +// from characters (a space by default) from the start of string var LTRIM = jet.LTRIM + +// RTRIM removes the longest string containing only characters +// from characters (a space by default) from the end of string var RTRIM = jet.RTRIM -var CHR = jet.CHR + +// CONCAT adds two or more expressions together var CONCAT = jet.CONCAT + +// CONCAT_WS adds two or more expressions together with a separator. var CONCAT_WS = jet.CONCAT_WS -var CONVERT = jet.CONVERT -var CONVERT_FROM = jet.CONVERT_FROM -var CONVERT_TO = jet.CONVERT_TO -var ENCODE = jet.ENCODE -var DECODE = jet.DECODE + +// FORMAT formats a number to a format like "#,###,###.##", rounded to a specified number of decimal places, then it returns the result as a string. var FORMAT = jet.FORMAT -var INITCAP = jet.INITCAP + +// LEFT returns first n characters in the string. +// When n is negative, return all but last |n| characters. var LEFT = jet.LEFT + +// RIGHT returns last n characters in the string. +// When n is negative, return all but first |n| characters. var RIGHT = jet.RIGHT +// LENGTH returns number of characters in string with a given encoding func LENGTH(str jet.StringExpression) jet.StringExpression { return jet.LENGTH(str) } +// LPAD fills up the string to length length by prepending the characters +// fill (a space by default). If the string is already longer than length +// then it is truncated (on the right). func LPAD(str jet.StringExpression, length jet.IntegerExpression, text jet.StringExpression) jet.StringExpression { return jet.LPAD(str, length, text) } + +// RPAD fills up the string to length length by appending the characters +// fill (a space by default). If the string is already longer than length then it is truncated. func RPAD(str jet.StringExpression, length jet.IntegerExpression, text jet.StringExpression) jet.StringExpression { return jet.RPAD(str, length, text) } +// MD5 calculates the MD5 hash of string, returning the result in hexadecimal var MD5 = jet.MD5 -var REPEAT = jet.REPEAT -var REPLACE = jet.REPLACE -var REVERSE = jet.REVERSE -var STRPOS = jet.STRPOS -var SUBSTR = jet.SUBSTR -var TO_ASCII = jet.TO_ASCII -var TO_HEX = jet.TO_HEX -//----------Data Type Formatting Functions ----------------------// -var TO_CHAR = jet.TO_CHAR -var TO_DATE = jet.TO_DATE -var TO_NUMBER = jet.TO_NUMBER -var TO_TIMESTAMP = jet.TO_TIMESTAMP +// REPEAT repeats string the specified number of times +var REPEAT = jet.REPEAT + +// REPLACE replaces all occurrences in string of substring from with substring to +var REPLACE = jet.REPLACE + +// REVERSE returns reversed string. +var REVERSE = jet.REVERSE + +// SUBSTR extracts substring +var SUBSTR = jet.SUBSTR + +// REGEXP_LIKE Returns 1 if the string expr matches the regular expression specified by the pattern pat, 0 otherwise. +var REGEXP_LIKE = jet.REGEXP_LIKE //----------------- Date/Time Functions and Operators ------------// - +// CURRENT_DATE returns current date var CURRENT_DATE = jet.CURRENT_DATE -var CURRENT_TIME = jet.CURRENT_TIME -var CURRENT_TIMESTAMP = jet.CURRENT_TIMESTAMP -var LOCALTIME = jet.LOCALTIME -var LOCALTIMESTAMP = jet.LOCALTIMESTAMP +// CURRENT_TIME returns current time with time zone +func CURRENT_TIME(precision ...int) TimeExpression { + return TimeExp(jet.CURRENT_TIME(precision...)) +} + +// CURRENT_TIMESTAMP returns current timestamp with time zone +func CURRENT_TIMESTAMP(precision ...int) TimestampExpression { + return TimestampExp(jet.CURRENT_TIMESTAMP(precision...)) +} + +// NOW returns current datetime func NOW(fsp ...int) DateTimeExpression { if len(fsp) > 0 { return jet.NewTimestampFunc("NOW", Int(int64(fsp[0]), true)) @@ -111,18 +185,24 @@ func NOW(fsp ...int) DateTimeExpression { return jet.NewTimestampFunc("NOW") } +// TIMESTAMP return a datetime value based on the arguments: func TIMESTAMP(str StringExpression) TimestampExpression { return jet.NewTimestampFunc("TIMESTAMP", str) } +// UNIX_TIMESTAMP returns unix timestamp func UNIX_TIMESTAMP(str StringExpression) TimestampExpression { return jet.NewTimestampFunc("UNIX_TIMESTAMP", str) } -// --------------- Conditional Expressions Functions -------------// -var COALESCE = jet.COALESCE -var NULLIF = jet.NULLIF -var GREATEST = jet.GREATEST -var LEAST = jet.LEAST +//----------- Comparison operators ---------------// + +// EXISTS checks for existence of the rows in subQuery var EXISTS = jet.EXISTS + +// CASE create CASE operator with optional list of expressions var CASE = jet.CASE + +//----------------- Bit operators ---------------// + +var BIT_NOT = jet.BIT_NOT diff --git a/postgres/functions.go b/postgres/functions.go index fbded66..8f273aa 100644 --- a/postgres/functions.go +++ b/postgres/functions.go @@ -53,8 +53,8 @@ var CONCAT = func(expressions ...Expression) StringExpression { return jet.CONCAT(explicitLiteralCasts(expressions...)...) } -func CONCAT_WS(expressions ...Expression) StringExpression { - return jet.CONCAT_WS(explicitLiteralCasts(expressions...)...) +func CONCAT_WS(separator Expression, expressions ...Expression) StringExpression { + return jet.CONCAT_WS(explicitLiteralCast(separator), explicitLiteralCasts(expressions...)...) } var CONVERT = jet.CONVERT