commit
7924d13875
62 changed files with 608 additions and 528067 deletions
|
|
@ -30,6 +30,14 @@ jobs:
|
|||
steps:
|
||||
- checkout
|
||||
|
||||
- run:
|
||||
name: Submodule init
|
||||
command: |
|
||||
git submodule init
|
||||
git submodule update
|
||||
cd ./tests/testdata && git fetch && git checkout master
|
||||
|
||||
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: |
|
||||
|
|
@ -71,10 +79,10 @@ jobs:
|
|||
sudo apt-get install default-mysql-client
|
||||
|
||||
- run:
|
||||
name: Init MySQL database
|
||||
name: Create MySQL user and databases
|
||||
command: |
|
||||
mysql -h 127.0.0.1 -u root -pjet -e "grant all privileges on *.* to 'jet'@'%';"
|
||||
mysql -h 127.0.0.1 -u root -pjet -e "set global sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';"
|
||||
mysql -h 127.0.0.1 -u root -pjet -e "set global sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';"
|
||||
mysql -h 127.0.0.1 -u jet -pjet -e "create database test_sample"
|
||||
|
||||
- run:
|
||||
|
|
@ -98,4 +106,75 @@ jobs:
|
|||
|
||||
- store_test_results: # Upload test results for display in Test Summary: https://circleci.com/docs/2.0/collect-test-data/
|
||||
path: /tmp/test-results
|
||||
build-mariadb:
|
||||
docker:
|
||||
# specify the version
|
||||
- image: circleci/golang:1.11
|
||||
|
||||
- image: circleci/mariadb:10.3
|
||||
command: [--default-authentication-plugin=mysql_native_password]
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: jet
|
||||
MYSQL_DATABASE: dvds
|
||||
MYSQL_USER: jet
|
||||
MYSQL_PASSWORD: jet
|
||||
|
||||
working_directory: /go/src/github.com/go-jet/jet
|
||||
|
||||
environment: # environment variables for the build itself
|
||||
TEST_RESULTS: /tmp/test-results # path to where test results will be saved
|
||||
|
||||
steps:
|
||||
- checkout
|
||||
|
||||
- run:
|
||||
name: Submodule init
|
||||
command: |
|
||||
git submodule init
|
||||
git submodule update
|
||||
cd ./tests/testdata && git fetch && git checkout master
|
||||
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: |
|
||||
go get github.com/google/uuid
|
||||
go get github.com/lib/pq
|
||||
go get github.com/go-sql-driver/mysql
|
||||
|
||||
go get github.com/pkg/profile
|
||||
go get gotest.tools/assert
|
||||
go get github.com/davecgh/go-spew/spew
|
||||
go get github.com/jstemmer/go-junit-report
|
||||
|
||||
go install github.com/go-jet/jet/cmd/jet
|
||||
|
||||
- run:
|
||||
name: Install MySQL CLI;
|
||||
command: |
|
||||
sudo apt-get install default-mysql-client
|
||||
|
||||
- run:
|
||||
name: Init MariaDB database
|
||||
command: |
|
||||
mysql -h 127.0.0.1 -u root -pjet -e "grant all privileges on *.* to 'jet'@'%';"
|
||||
mysql -h 127.0.0.1 -u root -pjet -e "set global sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';"
|
||||
mysql -h 127.0.0.1 -u jet -pjet -e "create database test_sample"
|
||||
|
||||
- run:
|
||||
name: Init MariaDB database
|
||||
command: |
|
||||
cd tests
|
||||
go run ./init/init.go -testsuite MariaDB
|
||||
cd ..
|
||||
|
||||
- run:
|
||||
name: Run MariaDB tests
|
||||
command: |
|
||||
go test -v ./tests/mysql/ -source=MariaDB
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
build_and_test:
|
||||
jobs:
|
||||
- build
|
||||
- build-mariadb
|
||||
|
|
|
|||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -18,3 +18,4 @@
|
|||
# Test files
|
||||
gen
|
||||
.gentestdata
|
||||
.tests/testdata/
|
||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
[submodule "tests/testdata"]
|
||||
path = tests/testdata
|
||||
url = https://github.com/go-jet/jet-test-data
|
||||
|
|
@ -95,10 +95,10 @@ ORDER BY ordinal_position;
|
|||
|
||||
func (m *MySqlQuerySet) ListOfEnumsQuery() string {
|
||||
return `
|
||||
SELECT (CASE DATA_TYPE WHEN 'enum' then CONCAT(TABLE_NAME, '_', COLUMN_NAME) ELSE '' END ), SUBSTRING(COLUMN_TYPE,5)
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = ?
|
||||
AND DATA_TYPE = 'enum';
|
||||
SELECT (CASE c.DATA_TYPE WHEN 'enum' then CONCAT(c.TABLE_NAME, '_', c.COLUMN_NAME) ELSE '' END ), SUBSTRING(c.COLUMN_TYPE,5)
|
||||
FROM information_schema.columns as c
|
||||
INNER JOIN information_schema.tables as t on (t.table_schema = c.table_schema AND t.table_name = c.table_name)
|
||||
WHERE c.table_schema = ? AND DATA_TYPE = 'enum' AND t.TABLE_TYPE = 'BASE TABLE';
|
||||
`
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -92,10 +92,10 @@ type binaryBoolExpression struct {
|
|||
binaryOpExpression
|
||||
}
|
||||
|
||||
func newBinaryBoolOperator(lhs, rhs Expression, operator string) BoolExpression {
|
||||
func newBinaryBoolOperator(lhs, rhs Expression, operator string, additionalParams ...Expression) BoolExpression {
|
||||
binaryBoolExpression := binaryBoolExpression{}
|
||||
|
||||
binaryBoolExpression.binaryOpExpression = newBinaryExpression(lhs, rhs, operator)
|
||||
binaryBoolExpression.binaryOpExpression = newBinaryExpression(lhs, rhs, operator, additionalParams...)
|
||||
binaryBoolExpression.ExpressionInterfaceImpl.Parent = &binaryBoolExpression
|
||||
binaryBoolExpression.boolInterfaceImpl.parent = &binaryBoolExpression
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ func (b *castExpression) serialize(statement StatementType, out *SqlBuilder, opt
|
|||
expression := b.expression
|
||||
castType := b.cast
|
||||
|
||||
if castOverride := out.Dialect.SerializeOverride("CAST"); castOverride != nil {
|
||||
if castOverride := out.Dialect.OperatorSerializeOverride("CAST"); castOverride != nil {
|
||||
castOverride(expression, String(castType))(statement, out, options...)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -184,14 +184,6 @@ func (s *ClauseSetStmtOperator) Serialize(statementType StatementType, out *SqlB
|
|||
panic("jet: UNION Statement must contain at least two SELECT statements")
|
||||
}
|
||||
|
||||
wrap := s.OrderBy.List != nil || s.Limit.Count >= 0 || s.Offset.Count >= 0
|
||||
|
||||
if wrap {
|
||||
out.NewLine()
|
||||
out.WriteString("(")
|
||||
out.IncreaseIdent()
|
||||
}
|
||||
|
||||
for i, selectStmt := range s.Selects {
|
||||
out.NewLine()
|
||||
if i > 0 {
|
||||
|
|
@ -210,12 +202,6 @@ func (s *ClauseSetStmtOperator) Serialize(statementType StatementType, out *SqlB
|
|||
selectStmt.serialize(statementType, out)
|
||||
}
|
||||
|
||||
if wrap {
|
||||
out.DecreaseIdent()
|
||||
out.NewLine()
|
||||
out.WriteString(")")
|
||||
}
|
||||
|
||||
s.OrderBy.Serialize(statementType, out)
|
||||
s.Limit.Serialize(statementType, out)
|
||||
s.Offset.Serialize(statementType, out)
|
||||
|
|
@ -391,26 +377,19 @@ func (d *ClauseStatementBegin) Serialize(statementType StatementType, out *SqlBu
|
|||
}
|
||||
}
|
||||
|
||||
type ClauseString struct {
|
||||
Name string
|
||||
Data string
|
||||
}
|
||||
|
||||
func (d *ClauseString) Serialize(statementType StatementType, out *SqlBuilder) {
|
||||
out.NewLine()
|
||||
out.WriteString(d.Name)
|
||||
out.WriteString(d.Data)
|
||||
}
|
||||
|
||||
type ClauseOptional struct {
|
||||
Name string
|
||||
Show bool
|
||||
Name string
|
||||
Show bool
|
||||
InNewLine bool
|
||||
}
|
||||
|
||||
func (d *ClauseOptional) Serialize(statementType StatementType, out *SqlBuilder) {
|
||||
if !d.Show {
|
||||
return
|
||||
}
|
||||
if d.InNewLine {
|
||||
out.NewLine()
|
||||
}
|
||||
out.WriteString(d.Name)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ package jet
|
|||
type Dialect interface {
|
||||
Name() string
|
||||
PackageName() string
|
||||
SerializeOverride(operator string) SerializeOverride
|
||||
OperatorSerializeOverride(operator string) SerializeOverride
|
||||
FunctionSerializeOverride(function string) SerializeOverride
|
||||
AliasQuoteChar() byte
|
||||
IdentifierQuoteChar() byte
|
||||
ArgumentPlaceholder() QueryPlaceholderFunc
|
||||
|
|
@ -14,32 +15,35 @@ type SerializeOverride func(expressions ...Expression) SerializeFunc
|
|||
type QueryPlaceholderFunc func(ord int) string
|
||||
|
||||
type DialectParams struct {
|
||||
Name string
|
||||
PackageName string
|
||||
SerializeOverrides map[string]SerializeOverride
|
||||
AliasQuoteChar byte
|
||||
IdentifierQuoteChar byte
|
||||
ArgumentPlaceholder QueryPlaceholderFunc
|
||||
Name string
|
||||
PackageName string
|
||||
OperatorSerializeOverrides map[string]SerializeOverride
|
||||
FunctionSerializeOverrides map[string]SerializeOverride
|
||||
AliasQuoteChar byte
|
||||
IdentifierQuoteChar byte
|
||||
ArgumentPlaceholder QueryPlaceholderFunc
|
||||
}
|
||||
|
||||
func NewDialect(params DialectParams) Dialect {
|
||||
return &dialectImpl{
|
||||
name: params.Name,
|
||||
packageName: params.PackageName,
|
||||
serializeOverrides: params.SerializeOverrides,
|
||||
aliasQuoteChar: params.AliasQuoteChar,
|
||||
identifierQuoteChar: params.IdentifierQuoteChar,
|
||||
argumentPlaceholder: params.ArgumentPlaceholder,
|
||||
name: params.Name,
|
||||
packageName: params.PackageName,
|
||||
operatorSerializeOverrides: params.OperatorSerializeOverrides,
|
||||
functionSerializeOverrides: params.FunctionSerializeOverrides,
|
||||
aliasQuoteChar: params.AliasQuoteChar,
|
||||
identifierQuoteChar: params.IdentifierQuoteChar,
|
||||
argumentPlaceholder: params.ArgumentPlaceholder,
|
||||
}
|
||||
}
|
||||
|
||||
type dialectImpl struct {
|
||||
name string
|
||||
packageName string
|
||||
serializeOverrides map[string]SerializeOverride
|
||||
aliasQuoteChar byte
|
||||
identifierQuoteChar byte
|
||||
argumentPlaceholder QueryPlaceholderFunc
|
||||
name string
|
||||
packageName string
|
||||
operatorSerializeOverrides map[string]SerializeOverride
|
||||
functionSerializeOverrides map[string]SerializeOverride
|
||||
aliasQuoteChar byte
|
||||
identifierQuoteChar byte
|
||||
argumentPlaceholder QueryPlaceholderFunc
|
||||
|
||||
supportsReturning bool
|
||||
}
|
||||
|
|
@ -52,8 +56,18 @@ func (d *dialectImpl) PackageName() string {
|
|||
return d.packageName
|
||||
}
|
||||
|
||||
func (d *dialectImpl) SerializeOverride(operator string) SerializeOverride {
|
||||
return d.serializeOverrides[operator]
|
||||
func (d *dialectImpl) OperatorSerializeOverride(operator string) SerializeOverride {
|
||||
if d.operatorSerializeOverrides == nil {
|
||||
return nil
|
||||
}
|
||||
return d.operatorSerializeOverrides[operator]
|
||||
}
|
||||
|
||||
func (d *dialectImpl) FunctionSerializeOverride(function string) SerializeOverride {
|
||||
if d.functionSerializeOverrides == nil {
|
||||
return nil
|
||||
}
|
||||
return d.functionSerializeOverrides[function]
|
||||
}
|
||||
|
||||
func (d *dialectImpl) AliasQuoteChar() byte {
|
||||
|
|
|
|||
|
|
@ -77,17 +77,22 @@ func (e *ExpressionInterfaceImpl) serializeForOrderBy(statement StatementType, o
|
|||
|
||||
// Representation of binary operations (e.g. comparisons, arithmetic)
|
||||
type binaryOpExpression struct {
|
||||
lhs, rhs Expression
|
||||
operator string
|
||||
lhs, rhs Expression
|
||||
additionalParam Expression
|
||||
operator string
|
||||
}
|
||||
|
||||
func newBinaryExpression(lhs, rhs Expression, operator string) binaryOpExpression {
|
||||
func newBinaryExpression(lhs, rhs Expression, operator string, additionalParam ...Expression) binaryOpExpression {
|
||||
binaryExpression := binaryOpExpression{
|
||||
lhs: lhs,
|
||||
rhs: rhs,
|
||||
operator: operator,
|
||||
}
|
||||
|
||||
if len(additionalParam) > 0 {
|
||||
binaryExpression.additionalParam = additionalParam[0]
|
||||
}
|
||||
|
||||
return binaryExpression
|
||||
}
|
||||
|
||||
|
|
@ -105,8 +110,8 @@ func (c *binaryOpExpression) serialize(statement StatementType, out *SqlBuilder,
|
|||
out.WriteString("(")
|
||||
}
|
||||
|
||||
if serializeOverride := out.Dialect.SerializeOverride(c.operator); serializeOverride != nil {
|
||||
serializeOverrideFunc := serializeOverride(c.lhs, c.rhs)
|
||||
if serializeOverride := out.Dialect.OperatorSerializeOverride(c.operator); serializeOverride != nil {
|
||||
serializeOverrideFunc := serializeOverride(c.lhs, c.rhs, c.additionalParam)
|
||||
serializeOverrideFunc(statement, out, options...)
|
||||
} else {
|
||||
c.lhs.serialize(statement, out)
|
||||
|
|
|
|||
|
|
@ -349,7 +349,7 @@ func TO_HEX(number IntegerExpression) StringExpression {
|
|||
// 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))
|
||||
return newBoolFunc("REGEXP_LIKE", stringExp, pattern, ConstLiteral(matchType[0]))
|
||||
}
|
||||
|
||||
return newBoolFunc("REGEXP_LIKE", stringExp, pattern)
|
||||
|
|
@ -391,7 +391,7 @@ func CURRENT_TIME(precision ...int) TimezExpression {
|
|||
var timezFunc *timezFunc
|
||||
|
||||
if len(precision) > 0 {
|
||||
timezFunc = newTimezFunc("CURRENT_TIME", constLiteral(precision[0]))
|
||||
timezFunc = newTimezFunc("CURRENT_TIME", ConstLiteral(precision[0]))
|
||||
} else {
|
||||
timezFunc = newTimezFunc("CURRENT_TIME")
|
||||
}
|
||||
|
|
@ -406,7 +406,7 @@ func CURRENT_TIMESTAMP(precision ...int) TimestampzExpression {
|
|||
var timestampzFunc *timestampzFunc
|
||||
|
||||
if len(precision) > 0 {
|
||||
timestampzFunc = newTimestampzFunc("CURRENT_TIMESTAMP", constLiteral(precision[0]))
|
||||
timestampzFunc = newTimestampzFunc("CURRENT_TIMESTAMP", ConstLiteral(precision[0]))
|
||||
} else {
|
||||
timestampzFunc = newTimestampzFunc("CURRENT_TIMESTAMP")
|
||||
}
|
||||
|
|
@ -421,7 +421,7 @@ func LOCALTIME(precision ...int) TimeExpression {
|
|||
var timeFunc *timeFunc
|
||||
|
||||
if len(precision) > 0 {
|
||||
timeFunc = newTimeFunc("LOCALTIME", constLiteral(precision[0]))
|
||||
timeFunc = newTimeFunc("LOCALTIME", ConstLiteral(precision[0]))
|
||||
} else {
|
||||
timeFunc = newTimeFunc("LOCALTIME")
|
||||
}
|
||||
|
|
@ -436,7 +436,7 @@ func LOCALTIMESTAMP(precision ...int) TimestampExpression {
|
|||
var timestampFunc *timestampFunc
|
||||
|
||||
if len(precision) > 0 {
|
||||
timestampFunc = NewTimestampFunc("LOCALTIMESTAMP", constLiteral(precision[0]))
|
||||
timestampFunc = NewTimestampFunc("LOCALTIMESTAMP", ConstLiteral(precision[0]))
|
||||
} else {
|
||||
timestampFunc = NewTimestampFunc("LOCALTIMESTAMP")
|
||||
}
|
||||
|
|
@ -505,7 +505,7 @@ func newFunc(name string, expressions []Expression, parent Expression) *funcExpr
|
|||
}
|
||||
|
||||
func (f *funcExpressionImpl) serialize(statement StatementType, out *SqlBuilder, options ...SerializeOption) {
|
||||
if serializeOverride := out.Dialect.SerializeOverride(f.name); serializeOverride != nil {
|
||||
if serializeOverride := out.Dialect.FunctionSerializeOverride(f.name); serializeOverride != nil {
|
||||
serializeOverrideFunc := serializeOverride(f.expressions...)
|
||||
serializeOverrideFunc(statement, out, options...)
|
||||
return
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ func TestIntExpressionPOW(t *testing.T) {
|
|||
|
||||
func TestIntExpressionBIT_NOT(t *testing.T) {
|
||||
assertClauseSerialize(t, BIT_NOT(table2ColInt), "(~ table2.col_int)")
|
||||
assertClauseSerialize(t, BIT_NOT(Int(11)), "(~ $1)", int64(11))
|
||||
assertClauseSerialize(t, BIT_NOT(Int(11)), "(~ 11)")
|
||||
}
|
||||
|
||||
func TestIntExpressionBIT_AND(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ func literal(value interface{}, optionalConstant ...bool) *literalExpressionImpl
|
|||
return &exp
|
||||
}
|
||||
|
||||
func constLiteral(value interface{}) *literalExpressionImpl {
|
||||
func ConstLiteral(value interface{}) *literalExpressionImpl {
|
||||
exp := literal(value)
|
||||
exp.constant = true
|
||||
|
||||
|
|
@ -61,13 +61,10 @@ type integerLiteralExpression struct {
|
|||
}
|
||||
|
||||
// Int is constructor for integer expressions literals.
|
||||
func Int(value int64, constant ...bool) IntegerExpression {
|
||||
func Int(value int64) IntegerExpression {
|
||||
numLiteral := &integerLiteralExpression{}
|
||||
|
||||
numLiteral.literalExpressionImpl = *literal(value)
|
||||
if len(constant) > 0 && constant[0] == true {
|
||||
numLiteral.constant = true
|
||||
}
|
||||
|
||||
numLiteral.literalExpressionImpl.Parent = numLiteral
|
||||
numLiteral.integerInterfaceImpl.parent = numLiteral
|
||||
|
|
@ -114,12 +111,9 @@ type stringLiteral struct {
|
|||
}
|
||||
|
||||
// String creates new string literal expression
|
||||
func String(value string, constant ...bool) StringExpression {
|
||||
func String(value string) StringExpression {
|
||||
stringLiteral := stringLiteral{}
|
||||
stringLiteral.literalExpressionImpl = *literal(value)
|
||||
if len(constant) > 0 && constant[0] == true {
|
||||
stringLiteral.constant = true
|
||||
}
|
||||
|
||||
stringLiteral.stringInterfaceImpl.parent = &stringLiteral
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
package jet
|
||||
|
||||
const (
|
||||
StringConcatOperator = "||"
|
||||
StringConcatOperator = "||"
|
||||
StringRegexpLikeOperator = "REGEXP"
|
||||
StringNotRegexpLikeOperator = "NOT REGEXP"
|
||||
)
|
||||
|
||||
//----------- Logical operators ---------------//
|
||||
|
|
@ -13,6 +15,9 @@ func NOT(exp BoolExpression) BoolExpression {
|
|||
|
||||
// BIT_NOT inverts every bit in integer expression result
|
||||
func BIT_NOT(expr IntegerExpression) IntegerExpression {
|
||||
if literalExp, ok := expr.(LiteralExpression); ok {
|
||||
literalExp.SetConstant(true)
|
||||
}
|
||||
return newPrefixIntegerOperator(expr, "~")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@ type StringExpression interface {
|
|||
LIKE(pattern StringExpression) BoolExpression
|
||||
NOT_LIKE(pattern StringExpression) BoolExpression
|
||||
|
||||
REGEXP_LIKE(pattern StringExpression, matchType ...string) BoolExpression
|
||||
REGEXP_LIKE(pattern StringExpression, caseSensitive ...bool) BoolExpression
|
||||
NOT_REGEXP_LIKE(pattern StringExpression, caseSensitive ...bool) BoolExpression
|
||||
}
|
||||
|
||||
type stringInterfaceImpl struct {
|
||||
|
|
@ -70,11 +71,16 @@ func (s *stringInterfaceImpl) NOT_LIKE(pattern StringExpression) BoolExpression
|
|||
return newBinaryBoolOperator(s.parent, pattern, "NOT LIKE")
|
||||
}
|
||||
|
||||
func (s *stringInterfaceImpl) REGEXP_LIKE(pattern StringExpression, matchType ...string) BoolExpression {
|
||||
return REGEXP_LIKE(s.parent, pattern, matchType...)
|
||||
func (s *stringInterfaceImpl) REGEXP_LIKE(pattern StringExpression, caseSensitive ...bool) BoolExpression {
|
||||
return newBinaryBoolOperator(s.parent, pattern, StringRegexpLikeOperator, Bool(len(caseSensitive) > 0 && caseSensitive[0]))
|
||||
}
|
||||
|
||||
func (s *stringInterfaceImpl) NOT_REGEXP_LIKE(pattern StringExpression, caseSensitive ...bool) BoolExpression {
|
||||
return newBinaryBoolOperator(s.parent, pattern, StringNotRegexpLikeOperator, Bool(len(caseSensitive) > 0 && caseSensitive[0]))
|
||||
}
|
||||
|
||||
//---------------------------------------------------//
|
||||
|
||||
type binaryStringExpression struct {
|
||||
ExpressionInterfaceImpl
|
||||
stringInterfaceImpl
|
||||
|
|
|
|||
|
|
@ -67,8 +67,13 @@ func TestStringNOT_LIKE(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestStringREGEXP_LIKE(t *testing.T) {
|
||||
assertClauseSerialize(t, table3StrCol.REGEXP_LIKE(table2ColStr), "REGEXP_LIKE(table3.col2, table2.col_str)")
|
||||
assertClauseSerialize(t, table3StrCol.REGEXP_LIKE(String("JOHN"), "c"), "REGEXP_LIKE(table3.col2, $1, 'c')", "JOHN")
|
||||
assertClauseSerialize(t, table3StrCol.REGEXP_LIKE(table2ColStr), "(table3.col2 REGEXP table2.col_str)")
|
||||
assertClauseSerialize(t, table3StrCol.REGEXP_LIKE(String("JOHN"), true), "(table3.col2 REGEXP $1)", "JOHN")
|
||||
}
|
||||
|
||||
func TestStringNOT_REGEXP_LIKE(t *testing.T) {
|
||||
assertClauseSerialize(t, table3StrCol.NOT_REGEXP_LIKE(table2ColStr), "(table3.col2 NOT REGEXP table2.col_str)")
|
||||
assertClauseSerialize(t, table3StrCol.NOT_REGEXP_LIKE(String("JOHN"), true), "(table3.col2 NOT REGEXP $1)", "JOHN")
|
||||
}
|
||||
|
||||
func TestStringExp(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ type castImpl struct {
|
|||
jet.Cast
|
||||
}
|
||||
|
||||
func CAST(expr jet.Expression) cast {
|
||||
func CAST(expr Expression) cast {
|
||||
castImpl := &castImpl{}
|
||||
|
||||
castImpl.Cast = jet.NewCastImpl(expr)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package mysql
|
|||
import "github.com/go-jet/jet/internal/jet"
|
||||
|
||||
type DeleteStatement interface {
|
||||
jet.Statement
|
||||
Statement
|
||||
|
||||
WHERE(expression BoolExpression) DeleteStatement
|
||||
ORDER_BY(orderByClauses ...jet.OrderByClause) DeleteStatement
|
||||
|
|
|
|||
|
|
@ -8,19 +8,21 @@ var Dialect = NewDialect()
|
|||
|
||||
func NewDialect() jet.Dialect {
|
||||
|
||||
serializeOverrides := map[string]jet.SerializeOverride{}
|
||||
serializeOverrides["IS DISTINCT FROM"] = mysql_IS_DISTINCT_FROM
|
||||
serializeOverrides["IS NOT DISTINCT FROM"] = mysql_IS_NOT_DISTINCT_FROM
|
||||
serializeOverrides["/"] = mysql_DIVISION
|
||||
serializeOverrides["#"] = mysql_BIT_XOR
|
||||
serializeOverrides[jet.StringConcatOperator] = mysql_CONCAT_operator
|
||||
operatorSerializeOverrides := map[string]jet.SerializeOverride{}
|
||||
operatorSerializeOverrides[jet.StringRegexpLikeOperator] = mysql_REGEXP_LIKE_operator
|
||||
operatorSerializeOverrides[jet.StringNotRegexpLikeOperator] = mysql_NOT_REGEXP_LIKE_operator
|
||||
operatorSerializeOverrides["IS DISTINCT FROM"] = mysql_IS_DISTINCT_FROM
|
||||
operatorSerializeOverrides["IS NOT DISTINCT FROM"] = mysql_IS_NOT_DISTINCT_FROM
|
||||
operatorSerializeOverrides["/"] = mysql_DIVISION
|
||||
operatorSerializeOverrides["#"] = mysql_BIT_XOR
|
||||
operatorSerializeOverrides[jet.StringConcatOperator] = mysql_CONCAT_operator
|
||||
|
||||
mySQLDialectParams := jet.DialectParams{
|
||||
Name: "MySQL",
|
||||
PackageName: "mysql",
|
||||
SerializeOverrides: serializeOverrides,
|
||||
AliasQuoteChar: '"',
|
||||
IdentifierQuoteChar: '`',
|
||||
Name: "MySQL",
|
||||
PackageName: "mysql",
|
||||
OperatorSerializeOverrides: operatorSerializeOverrides,
|
||||
AliasQuoteChar: '"',
|
||||
IdentifierQuoteChar: '`',
|
||||
ArgumentPlaceholder: func(int) string {
|
||||
return "?"
|
||||
},
|
||||
|
|
@ -31,7 +33,7 @@ func NewDialect() jet.Dialect {
|
|||
|
||||
func mysql_BIT_XOR(expressions ...jet.Expression) jet.SerializeFunc {
|
||||
return func(statement jet.StatementType, out *jet.SqlBuilder, options ...jet.SerializeOption) {
|
||||
if len(expressions) != 2 {
|
||||
if len(expressions) < 2 {
|
||||
panic("jet: invalid number of expressions for operator XOR")
|
||||
}
|
||||
|
||||
|
|
@ -48,7 +50,7 @@ func mysql_BIT_XOR(expressions ...jet.Expression) jet.SerializeFunc {
|
|||
|
||||
func mysql_CONCAT_operator(expressions ...jet.Expression) jet.SerializeFunc {
|
||||
return func(statement jet.StatementType, out *jet.SqlBuilder, options ...jet.SerializeOption) {
|
||||
if len(expressions) != 2 {
|
||||
if len(expressions) < 2 {
|
||||
panic("jet: invalid number of expressions for operator CONCAT")
|
||||
}
|
||||
out.WriteString("CONCAT(")
|
||||
|
|
@ -65,7 +67,7 @@ func mysql_CONCAT_operator(expressions ...jet.Expression) jet.SerializeFunc {
|
|||
|
||||
func mysql_DIVISION(expressions ...jet.Expression) jet.SerializeFunc {
|
||||
return func(statement jet.StatementType, out *jet.SqlBuilder, options ...jet.SerializeOption) {
|
||||
if len(expressions) != 2 {
|
||||
if len(expressions) < 2 {
|
||||
panic("jet: invalid number of expressions for operator DIV")
|
||||
}
|
||||
|
||||
|
|
@ -89,7 +91,7 @@ func mysql_DIVISION(expressions ...jet.Expression) jet.SerializeFunc {
|
|||
|
||||
func mysql_IS_NOT_DISTINCT_FROM(expressions ...jet.Expression) jet.SerializeFunc {
|
||||
return func(statement jet.StatementType, out *jet.SqlBuilder, options ...jet.SerializeOption) {
|
||||
if len(expressions) != 2 {
|
||||
if len(expressions) < 2 {
|
||||
panic("jet: invalid number of expressions for operator")
|
||||
}
|
||||
|
||||
|
|
@ -106,3 +108,55 @@ func mysql_IS_DISTINCT_FROM(expressions ...jet.Expression) jet.SerializeFunc {
|
|||
out.WriteString(")")
|
||||
}
|
||||
}
|
||||
|
||||
func mysql_REGEXP_LIKE_operator(expressions ...jet.Expression) jet.SerializeFunc {
|
||||
return func(statement jet.StatementType, out *jet.SqlBuilder, options ...jet.SerializeOption) {
|
||||
if len(expressions) < 2 {
|
||||
panic("jet: invalid number of expressions for operator")
|
||||
}
|
||||
|
||||
jet.Serialize(expressions[0], statement, out, options...)
|
||||
|
||||
caseSensitive := false
|
||||
|
||||
if len(expressions) >= 3 {
|
||||
if stringLiteral, ok := expressions[2].(jet.LiteralExpression); ok {
|
||||
caseSensitive = stringLiteral.Value().(bool)
|
||||
}
|
||||
}
|
||||
|
||||
out.WriteString("REGEXP")
|
||||
|
||||
if caseSensitive {
|
||||
out.WriteString("BINARY")
|
||||
}
|
||||
|
||||
jet.Serialize(expressions[1], statement, out, options...)
|
||||
}
|
||||
}
|
||||
|
||||
func mysql_NOT_REGEXP_LIKE_operator(expressions ...jet.Expression) jet.SerializeFunc {
|
||||
return func(statement jet.StatementType, out *jet.SqlBuilder, options ...jet.SerializeOption) {
|
||||
if len(expressions) < 2 {
|
||||
panic("jet: invalid number of expressions for operator")
|
||||
}
|
||||
|
||||
jet.Serialize(expressions[0], statement, out, options...)
|
||||
|
||||
caseSensitive := false
|
||||
|
||||
if len(expressions) >= 3 {
|
||||
if stringLiteral, ok := expressions[2].(jet.LiteralExpression); ok {
|
||||
caseSensitive = stringLiteral.Value().(bool)
|
||||
}
|
||||
}
|
||||
|
||||
out.WriteString("NOT REGEXP")
|
||||
|
||||
if caseSensitive {
|
||||
out.WriteString("BINARY")
|
||||
}
|
||||
|
||||
jet.Serialize(expressions[1], statement, out, options...)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,3 +46,17 @@ func TestExists(t *testing.T) {
|
|||
WHERE table1.col1 = table2.col3
|
||||
))`, int64(1))
|
||||
}
|
||||
|
||||
func TestString_REGEXP_LIKE_operator(t *testing.T) {
|
||||
assertClauseSerialize(t, table3StrCol.REGEXP_LIKE(table2ColStr), "(table3.col2 REGEXP table2.col_str)")
|
||||
assertClauseSerialize(t, table3StrCol.REGEXP_LIKE(String("JOHN")), "(table3.col2 REGEXP ?)", "JOHN")
|
||||
assertClauseSerialize(t, table3StrCol.REGEXP_LIKE(String("JOHN"), false), "(table3.col2 REGEXP ?)", "JOHN")
|
||||
assertClauseSerialize(t, table3StrCol.REGEXP_LIKE(String("JOHN"), true), "(table3.col2 REGEXP BINARY ?)", "JOHN")
|
||||
}
|
||||
|
||||
func TestString_NOT_REGEXP_LIKE_operator(t *testing.T) {
|
||||
assertClauseSerialize(t, table3StrCol.NOT_REGEXP_LIKE(table2ColStr), "(table3.col2 NOT REGEXP table2.col_str)")
|
||||
assertClauseSerialize(t, table3StrCol.NOT_REGEXP_LIKE(String("JOHN")), "(table3.col2 NOT REGEXP ?)", "JOHN")
|
||||
assertClauseSerialize(t, table3StrCol.NOT_REGEXP_LIKE(String("JOHN"), false), "(table3.col2 NOT REGEXP ?)", "JOHN")
|
||||
assertClauseSerialize(t, table3StrCol.NOT_REGEXP_LIKE(String("JOHN"), true), "(table3.col2 NOT REGEXP BINARY ?)", "JOHN")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,5 +32,3 @@ var TimestampExp = jet.TimestampExp
|
|||
var Raw = jet.Raw
|
||||
|
||||
var NewEnumValue = jet.NewEnumValue
|
||||
|
||||
type Statement jet.Statement
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ func CURRENT_TIMESTAMP(precision ...int) TimestampExpression {
|
|||
// NOW returns current datetime
|
||||
func NOW(fsp ...int) DateTimeExpression {
|
||||
if len(fsp) > 0 {
|
||||
return jet.NewTimestampFunc("NOW", Int(int64(fsp[0]), true))
|
||||
return jet.NewTimestampFunc("NOW", jet.ConstLiteral(int64(fsp[0])))
|
||||
}
|
||||
return jet.NewTimestampFunc("NOW")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import "github.com/go-jet/jet/internal/jet"
|
|||
|
||||
// InsertStatement is interface for SQL INSERT statements
|
||||
type InsertStatement interface {
|
||||
jet.Statement
|
||||
Statement
|
||||
|
||||
// Insert row of values
|
||||
VALUES(value interface{}, values ...interface{}) InsertStatement
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@ var (
|
|||
)
|
||||
|
||||
type SelectStatement interface {
|
||||
jet.Statement
|
||||
Statement
|
||||
jet.HasProjections
|
||||
jet.Expression
|
||||
Expression
|
||||
|
||||
DISTINCT() SelectStatement
|
||||
FROM(table ReadableTable) SelectStatement
|
||||
|
|
@ -23,6 +23,7 @@ type SelectStatement interface {
|
|||
LIMIT(limit int64) SelectStatement
|
||||
OFFSET(offset int64) SelectStatement
|
||||
FOR(lock SelectLock) SelectStatement
|
||||
LOCK_IN_SHARE_MODE() SelectStatement
|
||||
|
||||
UNION(rhs SelectStatement) SetStatement
|
||||
UNION_ALL(rhs SelectStatement) SetStatement
|
||||
|
|
@ -31,22 +32,24 @@ type SelectStatement interface {
|
|||
}
|
||||
|
||||
//SELECT creates new SelectStatement with list of projections
|
||||
func SELECT(projection jet.Projection, projections ...jet.Projection) SelectStatement {
|
||||
return newSelectStatement(nil, append([]jet.Projection{projection}, projections...))
|
||||
func SELECT(projection Projection, projections ...Projection) SelectStatement {
|
||||
return newSelectStatement(nil, append([]Projection{projection}, projections...))
|
||||
}
|
||||
|
||||
func newSelectStatement(table ReadableTable, projections []jet.Projection) SelectStatement {
|
||||
func newSelectStatement(table ReadableTable, projections []Projection) SelectStatement {
|
||||
newSelect := &selectStatementImpl{}
|
||||
newSelect.ExpressionStatementImpl.StatementImpl = jet.NewStatementImpl(Dialect, jet.SelectStatementType, newSelect, &newSelect.Select,
|
||||
&newSelect.From, &newSelect.Where, &newSelect.GroupBy, &newSelect.Having, &newSelect.OrderBy,
|
||||
&newSelect.Limit, &newSelect.Offset, &newSelect.For)
|
||||
&newSelect.Limit, &newSelect.Offset, &newSelect.For, &newSelect.ShareLock)
|
||||
|
||||
newSelect.ExpressionStatementImpl.ExpressionInterfaceImpl.Parent = newSelect
|
||||
|
||||
newSelect.Select.Projections = projections
|
||||
newSelect.Select.Projections = toJetProjectionList(projections)
|
||||
newSelect.From.Table = table
|
||||
newSelect.Limit.Count = -1
|
||||
newSelect.Offset.Count = -1
|
||||
newSelect.ShareLock.Name = "LOCK IN SHARE MODE"
|
||||
newSelect.ShareLock.InNewLine = true
|
||||
|
||||
newSelect.setOperatorsImpl.parent = newSelect
|
||||
|
||||
|
|
@ -57,15 +60,16 @@ type selectStatementImpl struct {
|
|||
jet.ExpressionStatementImpl
|
||||
setOperatorsImpl
|
||||
|
||||
Select jet.ClauseSelect
|
||||
From jet.ClauseFrom
|
||||
Where jet.ClauseWhere
|
||||
GroupBy jet.ClauseGroupBy
|
||||
Having jet.ClauseHaving
|
||||
OrderBy jet.ClauseOrderBy
|
||||
Limit jet.ClauseLimit
|
||||
Offset jet.ClauseOffset
|
||||
For jet.ClauseFor
|
||||
Select jet.ClauseSelect
|
||||
From jet.ClauseFrom
|
||||
Where jet.ClauseWhere
|
||||
GroupBy jet.ClauseGroupBy
|
||||
Having jet.ClauseHaving
|
||||
OrderBy jet.ClauseOrderBy
|
||||
Limit jet.ClauseLimit
|
||||
Offset jet.ClauseOffset
|
||||
For jet.ClauseFor
|
||||
ShareLock jet.ClauseOptional
|
||||
}
|
||||
|
||||
func (s *selectStatementImpl) DISTINCT() SelectStatement {
|
||||
|
|
@ -113,6 +117,11 @@ func (s *selectStatementImpl) FOR(lock SelectLock) SelectStatement {
|
|||
return s
|
||||
}
|
||||
|
||||
func (s *selectStatementImpl) LOCK_IN_SHARE_MODE() SelectStatement {
|
||||
s.ShareLock.Show = true
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *selectStatementImpl) AsTable(alias string) SelectTable {
|
||||
return newSelectTable(s, alias)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,3 +124,11 @@ FROM db.table1
|
|||
FOR SHARE NOWAIT;
|
||||
`)
|
||||
}
|
||||
|
||||
func TestSelect_LOCK_IN_SHARE_MODE(t *testing.T) {
|
||||
testutils.AssertStatementSql(t, SELECT(table1ColBool).FROM(table1).LOCK_IN_SHARE_MODE(), `
|
||||
SELECT table1.col_bool AS "table1.col_bool"
|
||||
FROM db.table1
|
||||
LOCK IN SHARE MODE;
|
||||
`)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ type Table interface {
|
|||
|
||||
type readableTable interface {
|
||||
// Generates a select query on the current tableName.
|
||||
SELECT(projection jet.Projection, projections ...jet.Projection) SelectStatement
|
||||
SELECT(projection Projection, projections ...Projection) SelectStatement
|
||||
|
||||
// Creates a inner join tableName Expression using onCondition.
|
||||
INNER_JOIN(table ReadableTable, onCondition BoolExpression) joinSelectUpdateTable
|
||||
|
|
@ -47,8 +47,8 @@ type readableTableInterfaceImpl struct {
|
|||
}
|
||||
|
||||
// Generates a select query on the current tableName.
|
||||
func (r *readableTableInterfaceImpl) SELECT(projection1 jet.Projection, projections ...jet.Projection) SelectStatement {
|
||||
return newSelectStatement(r.parent, append([]jet.Projection{projection1}, projections...))
|
||||
func (r *readableTableInterfaceImpl) SELECT(projection1 Projection, projections ...Projection) SelectStatement {
|
||||
return newSelectStatement(r.parent, append([]Projection{projection1}, projections...))
|
||||
}
|
||||
|
||||
// Creates a inner join tableName Expression using onCondition.
|
||||
|
|
|
|||
16
mysql/types.go
Normal file
16
mysql/types.go
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
package mysql
|
||||
|
||||
import "github.com/go-jet/jet/internal/jet"
|
||||
|
||||
type Statement jet.Statement
|
||||
type Projection jet.Projection
|
||||
|
||||
func toJetProjectionList(projections []Projection) []jet.Projection {
|
||||
ret := []jet.Projection{}
|
||||
|
||||
for _, projection := range projections {
|
||||
ret = append(ret, projection)
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
|
@ -3,23 +3,23 @@ package postgres
|
|||
import (
|
||||
"github.com/go-jet/jet/internal/jet"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var Dialect = NewDialect()
|
||||
|
||||
func NewDialect() jet.Dialect {
|
||||
|
||||
serializeOverrides := map[string]jet.SerializeOverride{}
|
||||
serializeOverrides["REGEXP_LIKE"] = postgres_REGEXP_LIKE_function
|
||||
serializeOverrides["CAST"] = postgresCAST
|
||||
operatorSerializeOverrides := map[string]jet.SerializeOverride{}
|
||||
operatorSerializeOverrides[jet.StringRegexpLikeOperator] = postgres_REGEXP_LIKE_operator
|
||||
operatorSerializeOverrides[jet.StringNotRegexpLikeOperator] = postgres_NOT_REGEXP_LIKE_operator
|
||||
operatorSerializeOverrides["CAST"] = postgresCAST
|
||||
|
||||
dialectParams := jet.DialectParams{
|
||||
Name: "PostgreSQL",
|
||||
PackageName: "postgres",
|
||||
SerializeOverrides: serializeOverrides,
|
||||
AliasQuoteChar: '"',
|
||||
IdentifierQuoteChar: '"',
|
||||
Name: "PostgreSQL",
|
||||
PackageName: "postgres",
|
||||
OperatorSerializeOverrides: operatorSerializeOverrides,
|
||||
AliasQuoteChar: '"',
|
||||
IdentifierQuoteChar: '"',
|
||||
ArgumentPlaceholder: func(ord int) string {
|
||||
return "$" + strconv.Itoa(ord)
|
||||
},
|
||||
|
|
@ -53,7 +53,7 @@ func postgresCAST(expressions ...jet.Expression) jet.SerializeFunc {
|
|||
}
|
||||
}
|
||||
|
||||
func postgres_REGEXP_LIKE_function(expressions ...jet.Expression) jet.SerializeFunc {
|
||||
func postgres_REGEXP_LIKE_operator(expressions ...jet.Expression) jet.SerializeFunc {
|
||||
return func(statement jet.StatementType, out *jet.SqlBuilder, options ...jet.SerializeOption) {
|
||||
if len(expressions) < 2 {
|
||||
panic("jet: invalid number of expressions for operator")
|
||||
|
|
@ -65,9 +65,7 @@ func postgres_REGEXP_LIKE_function(expressions ...jet.Expression) jet.SerializeF
|
|||
|
||||
if len(expressions) >= 3 {
|
||||
if stringLiteral, ok := expressions[2].(jet.LiteralExpression); ok {
|
||||
matchType := stringLiteral.Value().(string)
|
||||
|
||||
caseSensitive = !strings.Contains(matchType, "i")
|
||||
caseSensitive = stringLiteral.Value().(bool)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -80,3 +78,29 @@ func postgres_REGEXP_LIKE_function(expressions ...jet.Expression) jet.SerializeF
|
|||
jet.Serialize(expressions[1], statement, out, options...)
|
||||
}
|
||||
}
|
||||
|
||||
func postgres_NOT_REGEXP_LIKE_operator(expressions ...jet.Expression) jet.SerializeFunc {
|
||||
return func(statement jet.StatementType, out *jet.SqlBuilder, options ...jet.SerializeOption) {
|
||||
if len(expressions) < 2 {
|
||||
panic("jet: invalid number of expressions for operator")
|
||||
}
|
||||
|
||||
jet.Serialize(expressions[0], statement, out, options...)
|
||||
|
||||
caseSensitive := false
|
||||
|
||||
if len(expressions) >= 3 {
|
||||
if stringLiteral, ok := expressions[2].(jet.LiteralExpression); ok {
|
||||
caseSensitive = stringLiteral.Value().(bool)
|
||||
}
|
||||
}
|
||||
|
||||
if caseSensitive {
|
||||
out.WriteString("!~")
|
||||
} else {
|
||||
out.WriteString("!~*")
|
||||
}
|
||||
|
||||
jet.Serialize(expressions[1], statement, out, options...)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,15 +3,17 @@ package postgres
|
|||
import "testing"
|
||||
|
||||
func TestString_REGEXP_LIKE_operator(t *testing.T) {
|
||||
assertClauseSerialize(t, table3StrCol.REGEXP_LIKE(table2ColStr), "table3.col2 ~* table2.col_str")
|
||||
assertClauseSerialize(t, table3StrCol.REGEXP_LIKE(String("JOHN"), "c"), "table3.col2 ~ $1", "JOHN")
|
||||
assertClauseSerialize(t, table3StrCol.REGEXP_LIKE(String("JOHN"), "i"), "table3.col2 ~* $1", "JOHN")
|
||||
assertClauseSerialize(t, table3StrCol.REGEXP_LIKE(table2ColStr), "(table3.col2 ~* table2.col_str)")
|
||||
assertClauseSerialize(t, table3StrCol.REGEXP_LIKE(String("JOHN")), "(table3.col2 ~* $1)", "JOHN")
|
||||
assertClauseSerialize(t, table3StrCol.REGEXP_LIKE(String("JOHN"), false), "(table3.col2 ~* $1)", "JOHN")
|
||||
assertClauseSerialize(t, table3StrCol.REGEXP_LIKE(String("JOHN"), true), "(table3.col2 ~ $1)", "JOHN")
|
||||
}
|
||||
|
||||
func TestString_REGEXP_LIKE_function(t *testing.T) {
|
||||
assertClauseSerialize(t, REGEXP_LIKE(table3StrCol, table2ColStr), "table3.col2 ~* table2.col_str")
|
||||
assertClauseSerialize(t, REGEXP_LIKE(table3StrCol, String("JOHN"), "c"), "table3.col2 ~ $1", "JOHN")
|
||||
assertClauseSerialize(t, REGEXP_LIKE(table3StrCol, String("JOHN"), "i"), "table3.col2 ~* $1", "JOHN")
|
||||
func TestString_NOT_REGEXP_LIKE_operator(t *testing.T) {
|
||||
assertClauseSerialize(t, table3StrCol.NOT_REGEXP_LIKE(table2ColStr), "(table3.col2 !~* table2.col_str)")
|
||||
assertClauseSerialize(t, table3StrCol.NOT_REGEXP_LIKE(String("JOHN")), "(table3.col2 !~* $1)", "JOHN")
|
||||
assertClauseSerialize(t, table3StrCol.NOT_REGEXP_LIKE(String("JOHN"), false), "(table3.col2 !~* $1)", "JOHN")
|
||||
assertClauseSerialize(t, table3StrCol.NOT_REGEXP_LIKE(String("JOHN"), true), "(table3.col2 !~ $1)", "JOHN")
|
||||
}
|
||||
|
||||
func TestExists(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ var SUMi = jet.SUMi
|
|||
|
||||
//--------------------- String functions ------------------//
|
||||
|
||||
var REGEXP_LIKE = jet.REGEXP_LIKE
|
||||
var BIT_LENGTH = jet.BIT_LENGTH
|
||||
var CHAR_LENGTH = jet.CHAR_LENGTH
|
||||
var OCTET_LENGTH = jet.OCTET_LENGTH
|
||||
|
|
|
|||
|
|
@ -37,11 +37,11 @@ type SelectStatement interface {
|
|||
}
|
||||
|
||||
//SELECT creates new SelectStatement with list of projections
|
||||
func SELECT(projection jet.Projection, projections ...jet.Projection) SelectStatement {
|
||||
return newSelectStatement(nil, append([]jet.Projection{projection}, projections...))
|
||||
func SELECT(projection Projection, projections ...Projection) SelectStatement {
|
||||
return newSelectStatement(nil, append([]Projection{projection}, projections...))
|
||||
}
|
||||
|
||||
func newSelectStatement(table ReadableTable, projections []jet.Projection) SelectStatement {
|
||||
func newSelectStatement(table ReadableTable, projections []Projection) SelectStatement {
|
||||
newSelect := &selectStatementImpl{}
|
||||
newSelect.ExpressionStatementImpl.StatementImpl = jet.NewStatementImpl(Dialect, jet.SelectStatementType, newSelect, &newSelect.Select,
|
||||
&newSelect.From, &newSelect.Where, &newSelect.GroupBy, &newSelect.Having, &newSelect.OrderBy,
|
||||
|
|
@ -49,7 +49,7 @@ func newSelectStatement(table ReadableTable, projections []jet.Projection) Selec
|
|||
|
||||
newSelect.ExpressionStatementImpl.ExpressionInterfaceImpl.Parent = newSelect
|
||||
|
||||
newSelect.Select.Projections = projections
|
||||
newSelect.Select.Projections = toJetProjectionList(projections)
|
||||
newSelect.From.Table = table
|
||||
newSelect.Limit.Count = -1
|
||||
newSelect.Offset.Count = -1
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import "github.com/go-jet/jet/internal/jet"
|
|||
|
||||
type readableTable interface {
|
||||
// Generates a select query on the current tableName.
|
||||
SELECT(projection jet.Projection, projections ...jet.Projection) SelectStatement
|
||||
SELECT(projection Projection, projections ...Projection) SelectStatement
|
||||
|
||||
// Creates a inner join tableName Expression using onCondition.
|
||||
INNER_JOIN(table ReadableTable, onCondition BoolExpression) ReadableTable
|
||||
|
|
@ -52,8 +52,8 @@ type readableTableInterfaceImpl struct {
|
|||
}
|
||||
|
||||
// Generates a select query on the current tableName.
|
||||
func (r *readableTableInterfaceImpl) SELECT(projection1 jet.Projection, projections ...jet.Projection) SelectStatement {
|
||||
return newSelectStatement(r.parent, append([]jet.Projection{projection1}, projections...))
|
||||
func (r *readableTableInterfaceImpl) SELECT(projection1 Projection, projections ...Projection) SelectStatement {
|
||||
return newSelectStatement(r.parent, append([]Projection{projection1}, projections...))
|
||||
}
|
||||
|
||||
// Creates a inner join tableName Expression using onCondition.
|
||||
|
|
|
|||
16
postgres/types.go
Normal file
16
postgres/types.go
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
package postgres
|
||||
|
||||
import "github.com/go-jet/jet/internal/jet"
|
||||
|
||||
type Statement jet.Statement
|
||||
type Projection jet.Projection
|
||||
|
||||
func toJetProjectionList(projections []Projection) []jet.Projection {
|
||||
ret := []jet.Projection{}
|
||||
|
||||
for _, projection := range projections {
|
||||
ret = append(ret, projection)
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -1,159 +0,0 @@
|
|||
-- MySQL dump 10.13 Distrib 8.0.16, for Linux (x86_64)
|
||||
|
||||
|
||||
--
|
||||
-- Table structure for table `all_types8`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `all_types`;
|
||||
|
||||
CREATE TABLE `all_types` (
|
||||
`boolean` BOOLEAN NOT NULL,
|
||||
`boolean_ptr` BOOLEAN,
|
||||
|
||||
`tiny_int` TINYINT NOT NULL,
|
||||
`u_tiny_int` TINYINT unsigned NOT NULL,
|
||||
|
||||
`small_int` SMALLINT NOT NULL,
|
||||
`u_small_int` SMALLINT unsigned NOT NULL,
|
||||
|
||||
`medium_int` MEDIUMINT NOT NULL,
|
||||
`u_medium_int` MEDIUMINT unsigned NOT NULL,
|
||||
|
||||
`integer` INT NOT NULL,
|
||||
`u_integer` INT unsigned NOT NULL,
|
||||
|
||||
`big_int` bigint(20) NOT NULL,
|
||||
`u_big_int` bigint(20) unsigned NOT NULL,
|
||||
|
||||
-- ptr
|
||||
|
||||
`tiny_int_ptr` TINYINT,
|
||||
`u_tiny_int_ptr` TINYINT unsigned,
|
||||
|
||||
`small_int_ptr` SMALLINT,
|
||||
`u_small_int_ptr` SMALLINT unsigned,
|
||||
|
||||
`medium_int_ptr` MEDIUMINT,
|
||||
`u_medium_int_ptr` MEDIUMINT unsigned,
|
||||
|
||||
`integer_ptr` INT,
|
||||
`u_integer_ptr` INT unsigned,
|
||||
|
||||
`big_int_ptr` bigint(20),
|
||||
`u_big_int_ptr` bigint(20) unsigned,
|
||||
|
||||
|
||||
-- floats
|
||||
`decimal` decimal(5, 2) unsigned NOT NULL,
|
||||
`decimal_ptr` decimal(5,2),
|
||||
|
||||
`numeric` numeric(5,2) NOT NULL,
|
||||
`numeric_ptr` numeric(5, 2),
|
||||
|
||||
`float` float NOT NULL,
|
||||
`float_ptr` float,
|
||||
|
||||
`double` double NOT NULL,
|
||||
`double_ptr` double,
|
||||
|
||||
`real` real NOT NULL,
|
||||
`real_ptr` real,
|
||||
|
||||
-- bit values
|
||||
|
||||
`bit` bit(10) NOT NULL,
|
||||
`bit_ptr` bit(10),
|
||||
|
||||
-- date and time
|
||||
`time` time NOT NULL,
|
||||
`time_ptr` time,
|
||||
|
||||
`date` date NOT NULL,
|
||||
`date_ptr` date,
|
||||
|
||||
`date_time` datetime NOT NULL,
|
||||
`date_time_ptr` datetime,
|
||||
|
||||
`timestamp` timestamp NOT NULL,
|
||||
`timestamp_ptr` timestamp,
|
||||
|
||||
`year` year NOT NULL,
|
||||
`year_ptr` year,
|
||||
|
||||
-- strings
|
||||
|
||||
`char` char(20) NOT NULL,
|
||||
`char_ptr` char(20),
|
||||
|
||||
`var_char` varchar(20) NOT NULL,
|
||||
`var_char_ptr` varchar(20),
|
||||
|
||||
`binary` binary(20) NOT NULL,
|
||||
`binary_ptr` binary(20),
|
||||
|
||||
`var_binary` varbinary(20) NOT NULL,
|
||||
`var_binary_ptr` varbinary(20),
|
||||
|
||||
`blob` blob NOT NULL,
|
||||
`blob_ptr` blob,
|
||||
|
||||
`text` text NOT NULL,
|
||||
`text_ptr` text,
|
||||
|
||||
`enum` enum('value1', 'value2', 'value3') NOT NULL,
|
||||
`enum_ptr` enum('value1', 'value2', 'value3'),
|
||||
|
||||
`set` set('s1', 's2', 's3') NOT NULL,
|
||||
`set_ptr` set('s1', 's2', 's3'),
|
||||
|
||||
-- json
|
||||
|
||||
`json` json NOT NULL,
|
||||
`json_ptr` json
|
||||
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
INSERT INTO `all_types` VALUES
|
||||
(false, true,
|
||||
-3,3,14,14,-150,150,-1600,1600,5000,50000,
|
||||
-3,3,14,14,-150,150,-1600,1600,50000,50000,
|
||||
1.11,1.11,2.22,2.22,3.33,3.33,4.44,4.44,5.55,5.55,
|
||||
_binary '\0',_binary '\0',
|
||||
'10:11:12.33', '10:11:12.33', '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,5000,50000,
|
||||
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,
|
||||
'10:11:12.33', 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);
|
||||
|
||||
|
||||
|
||||
-- Link table --------------------
|
||||
|
||||
DROP TABLE IF EXISTS test_sample.link;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS test_sample.link (
|
||||
id int PRIMARY KEY AUTO_INCREMENT,
|
||||
url VARCHAR (255) NOT NULL,
|
||||
name VARCHAR (255) NOT NULL,
|
||||
description VARCHAR (255)
|
||||
);
|
||||
|
||||
INSERT INTO test_sample.link (ID, url, name, description) VALUES
|
||||
(0, 'http://www.youtube.com', 'Youtube' , '');
|
||||
|
||||
-- Link2 table --------------------
|
||||
|
||||
DROP TABLE IF EXISTS test_sample.link2;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS test_sample.link2 (
|
||||
id int PRIMARY KEY AUTO_INCREMENT,
|
||||
url VARCHAR (255) NOT NULL,
|
||||
name VARCHAR (255) NOT NULL,
|
||||
description VARCHAR (255)
|
||||
);
|
||||
|
||||
INSERT INTO test_sample.link2 (ID, url, name, description) VALUES
|
||||
(0, 'http://www.youtube.com', 'Youtube' , '');
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,239 +0,0 @@
|
|||
|
||||
-- AllTypes table -----------------------------
|
||||
|
||||
create schema IF NOT EXISTS test_sample;
|
||||
|
||||
DROP TABLE IF EXISTS test_sample.all_types;
|
||||
|
||||
CREATE TABLE test_sample.ALL_TYPES
|
||||
(
|
||||
-- numeric
|
||||
small_int_ptr smallint,
|
||||
small_int smallint NOT NULL,
|
||||
integer_ptr integer,
|
||||
integer integer NOT NULL,
|
||||
big_int_ptr bigint,
|
||||
big_int bigint NOT NULL,
|
||||
decimal_ptr decimal(10, 2),
|
||||
decimal decimal(10, 2) NOT NULL,
|
||||
numeric_ptr numeric(20, 3),
|
||||
numeric numeric(20,3) NOT NULL,
|
||||
real_ptr real,
|
||||
real real NOT NULL,
|
||||
double_precision_ptr double precision,
|
||||
double_precision double precision NOT NULL,
|
||||
smallserial smallserial NOT NULL,
|
||||
serial serial NOT NULL,
|
||||
bigserial bigserial NOT NULL,
|
||||
|
||||
--monetary
|
||||
-- money_ptr money,
|
||||
-- money money NOT NULL,
|
||||
|
||||
var_char_ptr character varying(100),
|
||||
var_char character varying(200) NOT NULL,
|
||||
char_ptr character(80),
|
||||
char character(80) NOT NULL,
|
||||
text_ptr text,
|
||||
text text NOT NULL,
|
||||
|
||||
--binary
|
||||
bytea_ptr bytea,
|
||||
bytea bytea NOT NULL,
|
||||
|
||||
--datetime
|
||||
timestampz_ptr timestamp with time zone,
|
||||
timestampz timestamp with time zone NOT NULL,
|
||||
timestamp_ptr timestamp without time zone,
|
||||
timestamp timestamp without time zone NOT NULL,
|
||||
date_ptr date,
|
||||
date date NOT NULL,
|
||||
timez_ptr time with time zone,
|
||||
timez time with time zone NOT NULL,
|
||||
time_ptr time without time zone,
|
||||
time time without time zone NOT NULL,
|
||||
interval_ptr interval,
|
||||
interval interval NOT NULL,
|
||||
|
||||
--boolean
|
||||
boolean_ptr boolean,
|
||||
boolean boolean NOT NULL,
|
||||
|
||||
--geometry
|
||||
point_ptr point,
|
||||
|
||||
--bitstrings
|
||||
bit_ptr bit(3),
|
||||
bit bit(3) NOT NULL,
|
||||
bit_varying_ptr bit varying(20),
|
||||
bit_varying bit varying(40) NOT NULL,
|
||||
|
||||
--textsearch
|
||||
tsvector_ptr tsvector,
|
||||
tsvector tsvector NOT NULL,
|
||||
|
||||
--uuid
|
||||
uuid_ptr uuid,
|
||||
uuid uuid NOT NULL,
|
||||
|
||||
--xml
|
||||
xml_ptr xml,
|
||||
xml xml NOT NULL,
|
||||
|
||||
--json
|
||||
json_ptr json,
|
||||
json json NOT NULL,
|
||||
jsonb_ptr jsonb,
|
||||
jsonb jsonb NOT NULL,
|
||||
|
||||
--array
|
||||
integer_array_ptr integer[],
|
||||
integer_array integer[] NOT NULL,
|
||||
text_array_ptr text[],
|
||||
text_array text[] NOT NULL,
|
||||
jsonb_array jsonb[] NOT NULL,
|
||||
text_multi_dim_array_ptr text[][],
|
||||
text_multi_dim_array text[][] NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO test_sample.ALL_types(
|
||||
small_int_ptr, "small_int", integer_ptr, "integer", big_int_ptr, "big_int", decimal_ptr, "decimal", numeric_ptr, "numeric", real_ptr, "real", double_precision_ptr, double_precision, smallserial, serial, bigserial,
|
||||
-- money_ptr, money,
|
||||
var_char_ptr, var_char, char_ptr, char, text_ptr, text,
|
||||
bytea_ptr, bytea,
|
||||
timestampz_ptr, timestampz, timestamp_ptr, "timestamp", date_ptr, date, timez_ptr, timez, time_ptr, "time", interval_ptr, "interval",
|
||||
boolean_ptr, "boolean",
|
||||
point_ptr,
|
||||
bit_ptr, "bit", bit_varying_ptr, bit_varying,
|
||||
tsvector_ptr, tsvector,
|
||||
uuid_ptr, uuid,
|
||||
xml_ptr, xml,
|
||||
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)
|
||||
VALUES (14, 14, 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,
|
||||
'ABBA', 'ABBA', 'JOHN', 'JOHN', 'Some text', 'Some text',
|
||||
'bytea', 'bytea',
|
||||
'January 8 04:05:06 1999 PST', 'January 8 04:05:06 1999 PST', '1999-01-08 04:05:06', '1999-01-08 04:05:06', '1999-01-08', '1999-01-08', '04:05:06 -8:00', '04:05:06 -8:00', '04:05:06', '04:05:06', '3 4:05:06', '3 4:05:06',
|
||||
TRUE, FALSE,
|
||||
'(2,3)',
|
||||
B'101', B'101', B'101111', B'101111',
|
||||
to_tsvector('supernovae'), to_tsvector('supernovae'),
|
||||
'A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11', 'A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11',
|
||||
'<Sub>abc</Sub>', '<Sub>abc</Sub>',
|
||||
'{"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"}}')
|
||||
,
|
||||
(NULL, 14, NULL, 300, NULL, 5000, NULL, 1.11, NULL, 2.22, NULL, 5.55, NULL, 11111111.22, DEFAULT, DEFAULT, DEFAULT,
|
||||
-- NULL, 100000,
|
||||
NULL, 'ABBA', NULL, 'JOHN', NULL, 'Some text',
|
||||
NULL, 'bytea',
|
||||
NULL, 'January 8 04:05:06 1999 PST', NULL, '1999-01-08 04:05:06', NULL, '1999-01-08', NULL, '04:05:06 -8:00', NULL, '04:05:06', NULL, '3 4:05:06',
|
||||
NULL, FALSE,
|
||||
NULL,
|
||||
NULL, B'101', NULL, B'101111',
|
||||
NULL, to_tsvector('supernovae'),
|
||||
NULL, 'A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11',
|
||||
NULL, '<Sub>abc</Sub>',
|
||||
NULL, '{"a": 1, "b": 3}', NULL, '{"a": 1, "b": 3}',
|
||||
NULL, '{1, 2, 3}', NULL, '{"breakfast", "consulting"}', ARRAY['{"a": 1, "b": 2}'::jsonb, '{"a":3, "b": 4}'::jsonb], NULL, '{{"meeting", "lunch"}, {"training", "presentation"}}')
|
||||
;
|
||||
|
||||
-- Link table --------------------
|
||||
|
||||
DROP TABLE IF EXISTS test_sample.link;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS test_sample.link (
|
||||
id serial PRIMARY KEY,
|
||||
url VARCHAR (255) NOT NULL,
|
||||
name VARCHAR (255) NOT NULL,
|
||||
description VARCHAR (255)
|
||||
);
|
||||
|
||||
INSERT INTO test_sample.link (ID, url, name, description) VALUES
|
||||
(0, 'http://www.youtube.com', 'Youtube' , '');
|
||||
|
||||
|
||||
-- Employee table ---------------
|
||||
|
||||
DROP TABLE IF EXISTS test_sample.employee;
|
||||
|
||||
CREATE TABLE test_sample.employee (
|
||||
employee_id INT PRIMARY KEY,
|
||||
first_name VARCHAR (255) NOT NULL,
|
||||
last_name VARCHAR (255) NOT NULL,
|
||||
employment_date timestamp with time zone,
|
||||
manager_id INT,
|
||||
FOREIGN KEY (manager_id)
|
||||
REFERENCES test_sample.employee (employee_id)
|
||||
ON DELETE CASCADE
|
||||
);
|
||||
INSERT INTO test_sample.employee (
|
||||
employee_id,
|
||||
first_name,
|
||||
last_name,
|
||||
employment_date,
|
||||
manager_id
|
||||
)
|
||||
VALUES
|
||||
(1, 'Windy', 'Hays', '1999-01-08 04:05:06.100 +1:00', NULL),
|
||||
(2, 'Ava', 'Christensen', '1999-01-08 04:05:06 +1:00', 1),
|
||||
(3, 'Hassan', 'Conner', '1999-01-08 04:05:06 +1:00', 1),
|
||||
(4, 'Anna', 'Reeves', '1999-01-08 04:05:06 +1:00', 2),
|
||||
(5, 'Sau', 'Norman', '1999-01-08 04:05:06 +1:00', 2),
|
||||
(6, 'Kelsie', 'Hays', '1999-01-08 04:05:06 +1:00', 3),
|
||||
(7, 'Tory', 'Goff', '1999-01-08 04:05:06 +1:00', 3),
|
||||
(8, 'Salley', 'Lester', '1999-01-08 04:05:06 +1:00', 3);
|
||||
|
||||
|
||||
-- Person table ------------------
|
||||
|
||||
DROP TYPE IF EXISTS test_sample.MOOD CASCADE;
|
||||
|
||||
CREATE TYPE test_sample.MOOD AS ENUM ('sad', 'ok', 'happy');
|
||||
|
||||
DROP TABLE IF EXISTS test_sample.person;
|
||||
|
||||
|
||||
CREATE TABLE test_sample.person(
|
||||
person_id uuid NOT NULL PRIMARY KEY,
|
||||
first_name varchar(100),
|
||||
last_name varchar(100),
|
||||
"Mood" test_sample.mood
|
||||
);
|
||||
|
||||
INSERT INTO test_sample.person(person_id, first_name, last_name, "Mood") VALUES
|
||||
('b68dbff4-a87d-11e9-a7f2-98ded00c39c6', 'Sad', 'John', 'sad'),
|
||||
('b68dbff5-a87d-11e9-a7f2-98ded00c39c7', 'Ok', 'John', 'ok'),
|
||||
('b68dbff6-a87d-11e9-a7f2-98ded00c39c8', 'Ok', 'John', 'ok');
|
||||
|
||||
|
||||
|
||||
-- WEIRD TABLE NAMES --------------
|
||||
|
||||
DROP TABLE IF EXISTS test_sample."WEIRD NAMES TABLE";
|
||||
|
||||
CREATE TABLE test_sample."WEIRD NAMES TABLE"(
|
||||
"weird_column_name1" varchar(100) NOT NULL,
|
||||
"Weird_Column_Name2" varchar(100) NOT NULL,
|
||||
"wEiRd_cOluMn_nAmE3" varchar(100) NOT NULL,
|
||||
"WeIrd_CoLuMN_Name4" varchar(100) NOT NULL,
|
||||
"WEIRD_COLUMN_NAME5" varchar(100) NOT NULL,
|
||||
|
||||
"WeirdColumnName6" varchar(100) NOT NULL,
|
||||
"weirdColumnName7" varchar(100) NOT NULL,
|
||||
"weirdcolumnname8" varchar(100),
|
||||
|
||||
"weird col name9" varchar(100) NOT NULL,
|
||||
"wEiRd cOlu nAmE10" varchar(100) NOT NULL,
|
||||
"WEIRD COLU NAME11" varchar(100) NOT NULL,
|
||||
"Weird Colu Name12" varchar(100) NOT NULL,
|
||||
|
||||
"weird-col-name13" varchar(100) NOT NULL,
|
||||
"wEiRd-cOlu-nAmE14" varchar(100) NOT NULL,
|
||||
"WEIRD-COLU-NAME15" varchar(100) NOT NULL,
|
||||
"Weird-Colu-Name16" varchar(100) NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO test_sample."WEIRD NAMES TABLE"
|
||||
VALUES ('Doe', 'Doe', 'Doe', 'Doe','Doe', 'Doe', 'Doe', 'Doe','Doe', 'Doe', 'Doe', 'Doe','Doe', 'Doe', 'Doe', 'Doe');
|
||||
|
|
@ -12,6 +12,7 @@ import (
|
|||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var testSuite string
|
||||
|
|
@ -24,12 +25,14 @@ func init() {
|
|||
|
||||
func main() {
|
||||
|
||||
testSuite = strings.ToLower(testSuite)
|
||||
|
||||
if testSuite == "postgres" {
|
||||
initPostgresDB()
|
||||
return
|
||||
}
|
||||
|
||||
if testSuite == "mysql" {
|
||||
if testSuite == "mysql" || testSuite == "mariadb" {
|
||||
initMySQLDB()
|
||||
return
|
||||
}
|
||||
|
|
@ -47,7 +50,7 @@ func initMySQLDB() {
|
|||
|
||||
for _, dbName := range mySQLDBs {
|
||||
cmdLine := fmt.Sprintf("mysql -h 127.0.0.1 -u %s -p%s %s < %s",
|
||||
dbconfig.MySQLUser, dbconfig.MySQLPassword, dbName, "./init/data/mysql/"+dbName+".sql")
|
||||
dbconfig.MySQLUser, dbconfig.MySQLPassword, dbName, "./testdata/init/mysql/"+dbName+".sql")
|
||||
|
||||
fmt.Println(cmdLine)
|
||||
|
||||
|
|
@ -71,7 +74,6 @@ func initMySQLDB() {
|
|||
|
||||
panicOnError(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func initPostgresDB() {
|
||||
|
|
@ -93,7 +95,7 @@ func initPostgresDB() {
|
|||
|
||||
for _, schemaName := range schemaNames {
|
||||
|
||||
execFile(db, "./init/data/postgres/"+schemaName+".sql")
|
||||
execFile(db, "./testdata/init/postgres/"+schemaName+".sql")
|
||||
|
||||
err = postgres.Generate("./.gentestdata", postgres.DBConnection{
|
||||
Host: dbconfig.Host,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import (
|
|||
"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/table"
|
||||
"github.com/go-jet/jet/tests/testdata/common"
|
||||
"github.com/go-jet/jet/tests/testdata/results/common"
|
||||
"github.com/google/uuid"
|
||||
"time"
|
||||
|
||||
|
|
@ -26,6 +26,12 @@ func TestAllTypes(t *testing.T) {
|
|||
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Equal(t, len(dest), 2)
|
||||
|
||||
if sourceIsMariaDB() { // MariaDB saves current timestamp in a case of NULL value insert
|
||||
return
|
||||
}
|
||||
|
||||
//testutils.PrintJson(dest)
|
||||
testutils.AssertJSON(t, dest, allTypesJson)
|
||||
}
|
||||
|
|
@ -187,7 +193,7 @@ FROM test_sample.all_types;
|
|||
|
||||
assert.NilError(t, err)
|
||||
|
||||
testutils.AssertJSONFile(t, dest, "./testdata/common/bool_operators.json")
|
||||
testutils.AssertJSONFile(t, dest, "./testdata/results/common/bool_operators.json")
|
||||
}
|
||||
|
||||
func TestFloatOperators(t *testing.T) {
|
||||
|
|
@ -284,7 +290,7 @@ LIMIT ?;
|
|||
|
||||
assert.NilError(t, err)
|
||||
|
||||
testutils.AssertJSONFile(t, dest, "./testdata/common/float_operators.json")
|
||||
testutils.AssertJSONFile(t, dest, "./testdata/results/common/float_operators.json")
|
||||
}
|
||||
|
||||
func TestIntegerOperators(t *testing.T) {
|
||||
|
|
@ -423,11 +429,12 @@ LIMIT ?;
|
|||
|
||||
//testutils.PrintJson(dest)
|
||||
|
||||
testutils.AssertJSONFile(t, dest, "./testdata/common/int_operators.json")
|
||||
testutils.AssertJSONFile(t, dest, "./testdata/results/common/int_operators.json")
|
||||
}
|
||||
|
||||
func TestStringOperators(t *testing.T) {
|
||||
query := AllTypes.SELECT(
|
||||
|
||||
var projectionList = []Projection{
|
||||
AllTypes.Text.EQ(AllTypes.Char),
|
||||
AllTypes.Text.EQ(String("Text")),
|
||||
AllTypes.Text.NOT_EQ(AllTypes.VarCharPtr),
|
||||
|
|
@ -445,8 +452,11 @@ func TestStringOperators(t *testing.T) {
|
|||
AllTypes.Text.LIKE(String("abc")),
|
||||
AllTypes.Text.NOT_LIKE(String("_b_")),
|
||||
AllTypes.Text.REGEXP_LIKE(String("aba")),
|
||||
AllTypes.Text.REGEXP_LIKE(String("aba"), "c"),
|
||||
String("ABA").REGEXP_LIKE(String("aba"), "i"),
|
||||
AllTypes.Text.REGEXP_LIKE(String("aba"), false),
|
||||
String("ABA").REGEXP_LIKE(String("aba"), true),
|
||||
AllTypes.Text.NOT_REGEXP_LIKE(String("aba")),
|
||||
AllTypes.Text.NOT_REGEXP_LIKE(String("aba"), false),
|
||||
String("ABA").NOT_REGEXP_LIKE(String("aba"), true),
|
||||
|
||||
BIT_LENGTH(AllTypes.Text),
|
||||
CHAR_LENGTH(AllTypes.Char),
|
||||
|
|
@ -469,17 +479,24 @@ func TestStringOperators(t *testing.T) {
|
|||
REVERSE(AllTypes.VarCharPtr),
|
||||
SUBSTR(AllTypes.CharPtr, Int(3)),
|
||||
SUBSTR(AllTypes.CharPtr, Int(3), Int(2)),
|
||||
REGEXP_LIKE(String("ABA"), String("aba")),
|
||||
REGEXP_LIKE(String("ABA"), String("aba"), "i"),
|
||||
REGEXP_LIKE(AllTypes.Text, String("aba"), "i"),
|
||||
)
|
||||
}
|
||||
|
||||
if !sourceIsMariaDB() {
|
||||
projectionList = append(projectionList, []Projection{
|
||||
REGEXP_LIKE(String("ABA"), String("aba")),
|
||||
REGEXP_LIKE(String("ABA"), String("aba"), "i"),
|
||||
REGEXP_LIKE(AllTypes.Text, String("aba"), "i"),
|
||||
}...)
|
||||
}
|
||||
//_, args, _ := query.Sql()
|
||||
|
||||
//fmt.Println(query.Sql())
|
||||
//fmt.Println(args[15])
|
||||
|
||||
// fmt.Println(query.Sql())
|
||||
query := SELECT(projectionList[0], projectionList[1:]...).
|
||||
FROM(AllTypes)
|
||||
|
||||
fmt.Println(query.DebugSql())
|
||||
|
||||
err := query.Query(db, &struct{}{})
|
||||
|
||||
|
|
@ -756,7 +773,7 @@ func TestTimeLiterals(t *testing.T) {
|
|||
TimestampT(timeT).AS("timestampT"),
|
||||
).FROM(AllTypes).LIMIT(1)
|
||||
|
||||
fmt.Println(query.DebugSql())
|
||||
//fmt.Println(query.DebugSql())
|
||||
|
||||
testutils.AssertStatementSql(t, query, `
|
||||
SELECT CAST(? AS DATE) AS "date",
|
||||
|
|
@ -785,7 +802,20 @@ LIMIT ?;
|
|||
|
||||
//testutils.PrintJson(dest)
|
||||
|
||||
testutils.AssertJSON(t, dest, `
|
||||
if sourceIsMariaDB() {
|
||||
testutils.AssertJSON(t, dest, `
|
||||
{
|
||||
"Date": "2009-11-17T00:00:00Z",
|
||||
"DateT": "2009-11-17T00:00:00Z",
|
||||
"Time": "0000-01-01T20:34:58Z",
|
||||
"TimeT": "0000-01-01T19:34:58Z",
|
||||
"DateTime": "2009-11-17T19:34:58Z",
|
||||
"Timestamp": "2019-08-06T10:10:30Z",
|
||||
"TimestampT": "2009-11-17T19:34:58Z"
|
||||
}
|
||||
`)
|
||||
} else {
|
||||
testutils.AssertJSON(t, dest, `
|
||||
{
|
||||
"Date": "2009-11-17T00:00:00Z",
|
||||
"DateT": "2009-11-17T00:00:00Z",
|
||||
|
|
@ -796,6 +826,8 @@ LIMIT ?;
|
|||
"TimestampT": "2009-11-17T19:34:58.351387Z"
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var allTypesJson = `
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ func assertGeneratedFiles(t *testing.T) {
|
|||
enumFiles, err := ioutil.ReadDir(genTestDir3 + "/dvds/enum")
|
||||
assert.NilError(t, err)
|
||||
|
||||
assertFileNameEqual(t, enumFiles, "film_list_rating.go", "film_rating.go", "nicer_but_slower_film_list_rating.go")
|
||||
assertFileNameEqual(t, enumFiles, "film_rating.go")
|
||||
assertFileContent(t, genTestDir3+"/dvds/enum/film_rating.go", "\npackage enum", mpaaRatingEnumFile)
|
||||
|
||||
// Model files
|
||||
|
|
@ -82,7 +82,7 @@ func assertGeneratedFiles(t *testing.T) {
|
|||
|
||||
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", "film_list_rating.go", "film_rating.go", "nicer_but_slower_film_list_rating.go")
|
||||
"payment.go", "rental.go", "staff.go", "store.go", "film_rating.go")
|
||||
|
||||
assertFileContent(t, genTestDir3+"/dvds/model/actor.go", "\npackage model", actorModelFile)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package mysql
|
|||
|
||||
import (
|
||||
"database/sql"
|
||||
"flag"
|
||||
"github.com/go-jet/jet/tests/dbconfig"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
|
|
@ -13,6 +14,19 @@ import (
|
|||
|
||||
var db *sql.DB
|
||||
|
||||
var source string
|
||||
|
||||
const MariaDB = "MariaDB"
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&source, "source", "", "MySQL or MariaDB")
|
||||
flag.Parse()
|
||||
}
|
||||
|
||||
func sourceIsMariaDB() bool {
|
||||
return source == MariaDB
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
defer profile.Start().Stop()
|
||||
|
||||
|
|
|
|||
|
|
@ -65,10 +65,14 @@ ORDER BY actor.actor_id;
|
|||
|
||||
//testutils.PrintJson(dest)
|
||||
//testutils.SaveJsonFile(dest, "mysql/testdata/all_actors.json")
|
||||
testutils.AssertJSONFile(t, dest, "mysql/testdata/all_actors.json")
|
||||
testutils.AssertJSONFile(t, dest, "./testdata/results/mysql/all_actors.json")
|
||||
}
|
||||
|
||||
func TestSelectGroupByHaving(t *testing.T) {
|
||||
if sourceIsMariaDB() {
|
||||
return
|
||||
}
|
||||
|
||||
expectedSQL := `
|
||||
SELECT customer.customer_id AS "customer.customer_id",
|
||||
customer.store_id AS "customer.store_id",
|
||||
|
|
@ -134,7 +138,7 @@ ORDER BY payment.customer_id, SUM(payment.amount) ASC;
|
|||
assert.Equal(t, len(dest), 174)
|
||||
|
||||
//testutils.SaveJsonFile(dest, "mysql/testdata/customer_payment_sum.json")
|
||||
testutils.AssertJSONFile(t, dest, "mysql/testdata/customer_payment_sum.json")
|
||||
testutils.AssertJSONFile(t, dest, "./testdata/results/mysql/customer_payment_sum.json")
|
||||
}
|
||||
|
||||
func TestSubQuery(t *testing.T) {
|
||||
|
|
@ -170,10 +174,14 @@ func TestSubQuery(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
|
||||
//testutils.SaveJsonFile(dest, "mysql/testdata/r_rating_films.json")
|
||||
testutils.AssertJSONFile(t, dest, "mysql/testdata/r_rating_films.json")
|
||||
testutils.AssertJSONFile(t, dest, "./testdata/results/mysql/r_rating_films.json")
|
||||
}
|
||||
|
||||
func TestSelectAndUnionInProjection(t *testing.T) {
|
||||
if sourceIsMariaDB() {
|
||||
return
|
||||
}
|
||||
|
||||
expectedSQL := `
|
||||
SELECT payment.payment_id AS "payment.payment_id",
|
||||
(
|
||||
|
|
@ -183,19 +191,17 @@ SELECT payment.payment_id AS "payment.payment_id",
|
|||
),
|
||||
(
|
||||
(
|
||||
(
|
||||
SELECT payment.payment_id AS "payment.payment_id"
|
||||
FROM dvds.payment
|
||||
LIMIT ?
|
||||
OFFSET ?
|
||||
)
|
||||
UNION
|
||||
(
|
||||
SELECT payment.payment_id AS "payment.payment_id"
|
||||
FROM dvds.payment
|
||||
LIMIT ?
|
||||
OFFSET ?
|
||||
)
|
||||
SELECT payment.payment_id AS "payment.payment_id"
|
||||
FROM dvds.payment
|
||||
LIMIT ?
|
||||
OFFSET ?
|
||||
)
|
||||
UNION
|
||||
(
|
||||
SELECT payment.payment_id AS "payment.payment_id"
|
||||
FROM dvds.payment
|
||||
LIMIT ?
|
||||
OFFSET ?
|
||||
)
|
||||
LIMIT ?
|
||||
)
|
||||
|
|
@ -223,19 +229,17 @@ LIMIT ?;
|
|||
func TestSelectUNION(t *testing.T) {
|
||||
expectedSQL := `
|
||||
(
|
||||
(
|
||||
SELECT payment.payment_id AS "payment.payment_id"
|
||||
FROM dvds.payment
|
||||
LIMIT ?
|
||||
OFFSET ?
|
||||
)
|
||||
UNION
|
||||
(
|
||||
SELECT payment.payment_id AS "payment.payment_id"
|
||||
FROM dvds.payment
|
||||
LIMIT ?
|
||||
OFFSET ?
|
||||
)
|
||||
SELECT payment.payment_id AS "payment.payment_id"
|
||||
FROM dvds.payment
|
||||
LIMIT ?
|
||||
OFFSET ?
|
||||
)
|
||||
UNION
|
||||
(
|
||||
SELECT payment.payment_id AS "payment.payment_id"
|
||||
FROM dvds.payment
|
||||
LIMIT ?
|
||||
OFFSET ?
|
||||
)
|
||||
LIMIT ?;
|
||||
`
|
||||
|
|
@ -260,19 +264,17 @@ LIMIT ?;
|
|||
func TestSelectUNION_ALL(t *testing.T) {
|
||||
expectedSQL := `
|
||||
(
|
||||
(
|
||||
SELECT payment.payment_id AS "payment.payment_id"
|
||||
FROM dvds.payment
|
||||
LIMIT ?
|
||||
OFFSET ?
|
||||
)
|
||||
UNION ALL
|
||||
(
|
||||
SELECT payment.payment_id AS "payment.payment_id"
|
||||
FROM dvds.payment
|
||||
LIMIT ?
|
||||
OFFSET ?
|
||||
)
|
||||
SELECT payment.payment_id AS "payment.payment_id"
|
||||
FROM dvds.payment
|
||||
LIMIT ?
|
||||
OFFSET ?
|
||||
)
|
||||
UNION ALL
|
||||
(
|
||||
SELECT payment.payment_id AS "payment.payment_id"
|
||||
FROM dvds.payment
|
||||
LIMIT ?
|
||||
OFFSET ?
|
||||
)
|
||||
ORDER BY "payment.payment_id"
|
||||
LIMIT ?
|
||||
|
|
@ -403,11 +405,16 @@ LIMIT ?;
|
|||
|
||||
//testutils.SaveJsonFile(dest, "./mysql/testdata/lang_film_actor_inventory_rental.json")
|
||||
|
||||
testutils.AssertJSONFile(t, dest, "./mysql/testdata/lang_film_actor_inventory_rental.json")
|
||||
testutils.AssertJSONFile(t, dest, "./testdata/results/mysql/lang_film_actor_inventory_rental.json")
|
||||
}
|
||||
}
|
||||
|
||||
func getRowLockTestData() map[SelectLock]string {
|
||||
if sourceIsMariaDB() {
|
||||
return map[SelectLock]string{
|
||||
UPDATE(): "UPDATE",
|
||||
}
|
||||
}
|
||||
return map[SelectLock]string{
|
||||
UPDATE(): "UPDATE",
|
||||
SHARE(): "SHARE",
|
||||
|
|
@ -455,6 +462,10 @@ FOR`
|
|||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
if sourceIsMariaDB() {
|
||||
return
|
||||
}
|
||||
|
||||
for lockType, lockTypeStr := range getRowLockTestData() {
|
||||
query.FOR(lockType.SKIP_LOCKED())
|
||||
|
||||
|
|
@ -496,3 +507,23 @@ SELECT true,
|
|||
err := query.Query(db, &struct{}{})
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
func TestLockInShareMode(t *testing.T) {
|
||||
expectedSQL := `
|
||||
SELECT *
|
||||
FROM dvds.address
|
||||
LIMIT 3
|
||||
OFFSET 1
|
||||
LOCK IN SHARE MODE;
|
||||
`
|
||||
query := Address.
|
||||
SELECT(STAR).
|
||||
LIMIT(3).
|
||||
OFFSET(1).
|
||||
LOCK_IN_SHARE_MODE()
|
||||
|
||||
testutils.AssertDebugStatementSql(t, query, expectedSQL)
|
||||
|
||||
err := query.Query(db, &struct{}{})
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
|
|
|||
1202
tests/mysql/testdata/all_actors.json
vendored
1202
tests/mysql/testdata/all_actors.json
vendored
File diff suppressed because it is too large
Load diff
3134
tests/mysql/testdata/customer_payment_sum.json
vendored
3134
tests/mysql/testdata/customer_payment_sum.json
vendored
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
9469
tests/mysql/testdata/r_rating_films.json
vendored
9469
tests/mysql/testdata/r_rating_films.json
vendored
File diff suppressed because it is too large
Load diff
|
|
@ -139,6 +139,35 @@ WHERE link.id = 201;
|
|||
testutils.AssertExec(t, stmt, db)
|
||||
}
|
||||
|
||||
func TestUpdateWithModelDataAndMutableColumns(t *testing.T) {
|
||||
|
||||
setupLinkTableForUpdateTest(t)
|
||||
|
||||
link := model.Link{
|
||||
ID: 201,
|
||||
URL: "http://www.duckduckgo.com",
|
||||
Name: "DuckDuckGo",
|
||||
}
|
||||
|
||||
stmt := Link.
|
||||
UPDATE(Link.MutableColumns).
|
||||
MODEL(link).
|
||||
WHERE(Link.ID.EQ(Int(int64(link.ID))))
|
||||
|
||||
var expectedSQL = `
|
||||
UPDATE test_sample.link
|
||||
SET url = 'http://www.duckduckgo.com',
|
||||
name = 'DuckDuckGo',
|
||||
description = NULL
|
||||
WHERE link.id = 201;
|
||||
`
|
||||
fmt.Println(stmt.DebugSql())
|
||||
|
||||
testutils.AssertDebugStatementSql(t, stmt, expectedSQL, "http://www.duckduckgo.com", "DuckDuckGo", nil, int64(201))
|
||||
|
||||
testutils.AssertExec(t, stmt, db)
|
||||
}
|
||||
|
||||
func TestUpdateWithInvalidModelData(t *testing.T) {
|
||||
defer func() {
|
||||
r := recover()
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import (
|
|||
. "github.com/go-jet/jet/postgres"
|
||||
"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/testdata/common"
|
||||
"github.com/go-jet/jet/tests/testdata/results/common"
|
||||
"github.com/google/uuid"
|
||||
"gotest.tools/assert"
|
||||
"testing"
|
||||
|
|
@ -179,9 +179,10 @@ func TestStringOperators(t *testing.T) {
|
|||
AllTypes.Text.CONCAT(Int(11)),
|
||||
AllTypes.Text.LIKE(String("abc")),
|
||||
AllTypes.Text.NOT_LIKE(String("_b_")),
|
||||
AllTypes.Text.REGEXP_LIKE(String("aba")),
|
||||
AllTypes.Text.REGEXP_LIKE(String("aba"), "c"),
|
||||
AllTypes.Text.REGEXP_LIKE(String("aba"), "i"),
|
||||
AllTypes.Text.REGEXP_LIKE(String("^t")),
|
||||
AllTypes.Text.REGEXP_LIKE(String("^t"), true),
|
||||
AllTypes.Text.NOT_REGEXP_LIKE(String("^t")),
|
||||
AllTypes.Text.NOT_REGEXP_LIKE(String("^t"), true),
|
||||
|
||||
BIT_LENGTH(String("length")),
|
||||
CHAR_LENGTH(AllTypes.Char),
|
||||
|
|
@ -232,7 +233,7 @@ func TestStringOperators(t *testing.T) {
|
|||
TO_HEX(AllTypes.IntegerPtr),
|
||||
)
|
||||
|
||||
//fmt.Println(query.Sql())
|
||||
//fmt.Println(query.DebugSql())
|
||||
|
||||
err := query.Query(db, &struct{}{})
|
||||
|
||||
|
|
@ -307,7 +308,7 @@ LIMIT $5;
|
|||
|
||||
assert.NilError(t, err)
|
||||
|
||||
testutils.AssertJSONFile(t, dest, "./testdata/common/bool_operators.json")
|
||||
testutils.AssertJSONFile(t, dest, "./testdata/results/common/bool_operators.json")
|
||||
}
|
||||
|
||||
func TestFloatOperators(t *testing.T) {
|
||||
|
|
@ -405,7 +406,7 @@ LIMIT $35;
|
|||
|
||||
//testutils.PrintJson(dest)
|
||||
|
||||
testutils.AssertJSONFile(t, dest, "./testdata/common/float_operators.json")
|
||||
testutils.AssertJSONFile(t, dest, "./testdata/results/common/float_operators.json")
|
||||
}
|
||||
|
||||
func TestIntegerOperators(t *testing.T) {
|
||||
|
|
@ -467,7 +468,7 @@ func TestIntegerOperators(t *testing.T) {
|
|||
AllTypes.SmallInt.BIT_XOR(Int(11)).AS("bit xor 2"),
|
||||
|
||||
BIT_NOT(Int(-1).MUL(AllTypes.SmallInt)).AS("bit_not_1"),
|
||||
BIT_NOT(Int(-11, true)).AS("bit_not_2"),
|
||||
BIT_NOT(Int(-11)).AS("bit_not_2"),
|
||||
|
||||
AllTypes.SmallInt.BIT_SHIFT_LEFT(AllTypes.SmallInt.DIV(Int(2))).AS("bit shift left 1"),
|
||||
AllTypes.SmallInt.BIT_SHIFT_LEFT(Int(4)).AS("bit shift left 2"),
|
||||
|
|
@ -544,7 +545,7 @@ LIMIT $23;
|
|||
|
||||
//testutils.SaveJsonFile("./testdata/common/int_operators.json", dest)
|
||||
//testutils.PrintJson(dest)
|
||||
testutils.AssertJSONFile(t, dest, "./testdata/common/int_operators.json")
|
||||
testutils.AssertJSONFile(t, dest, "./testdata/results/common/int_operators.json")
|
||||
}
|
||||
|
||||
func TestTimeExpression(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ func TestJoinEverything(t *testing.T) {
|
|||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(dest), 275)
|
||||
testutils.AssertJSONFile(t, dest, "./postgres/testdata/joined_everything.json")
|
||||
testutils.AssertJSONFile(t, dest, "./testdata/results/postgres/joined_everything.json")
|
||||
}
|
||||
|
||||
func TestSelfJoin(t *testing.T) {
|
||||
|
|
@ -215,21 +215,19 @@ func TestUnionForQuotedNames(t *testing.T) {
|
|||
//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
|
||||
)
|
||||
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))
|
||||
|
|
|
|||
|
|
@ -62,5 +62,5 @@ func TestNorthwindJoinEverything(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
|
||||
//jsonSave("./testdata/northwind-all.json", dest)
|
||||
testutils.AssertJSONFile(t, dest, "./postgres/testdata/northwind-all.json")
|
||||
testutils.AssertJSONFile(t, dest, "./testdata/results/postgres/northwind-all.json")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,19 +128,17 @@ SELECT payment.payment_id AS "payment.payment_id",
|
|||
),
|
||||
(
|
||||
(
|
||||
(
|
||||
SELECT payment.payment_id AS "payment.payment_id"
|
||||
FROM dvds.payment
|
||||
LIMIT 1
|
||||
OFFSET 10
|
||||
)
|
||||
UNION
|
||||
(
|
||||
SELECT payment.payment_id AS "payment.payment_id"
|
||||
FROM dvds.payment
|
||||
LIMIT 1
|
||||
OFFSET 2
|
||||
)
|
||||
SELECT payment.payment_id AS "payment.payment_id"
|
||||
FROM dvds.payment
|
||||
LIMIT 1
|
||||
OFFSET 10
|
||||
)
|
||||
UNION
|
||||
(
|
||||
SELECT payment.payment_id AS "payment.payment_id"
|
||||
FROM dvds.payment
|
||||
LIMIT 1
|
||||
OFFSET 2
|
||||
)
|
||||
LIMIT 1
|
||||
)
|
||||
|
|
@ -1063,7 +1061,7 @@ ORDER BY customer.customer_id, SUM(payment.amount) ASC;
|
|||
assert.Equal(t, len(dest), 104)
|
||||
|
||||
//testutils.SaveJsonFile(dest, "postgres/testdata/customer_payment_sum.json")
|
||||
testutils.AssertJSONFile(t, dest, "postgres/testdata/customer_payment_sum.json")
|
||||
testutils.AssertJSONFile(t, dest, "./testdata/results/postgres/customer_payment_sum.json")
|
||||
}
|
||||
|
||||
func TestSelectGroupBy2(t *testing.T) {
|
||||
|
|
@ -1217,19 +1215,17 @@ ORDER BY payment.payment_date ASC;
|
|||
func TestUnion(t *testing.T) {
|
||||
expectedQuery := `
|
||||
(
|
||||
(
|
||||
SELECT payment.payment_id AS "payment.payment_id",
|
||||
payment.amount AS "payment.amount"
|
||||
FROM dvds.payment
|
||||
WHERE payment.amount <= 100
|
||||
)
|
||||
UNION ALL
|
||||
(
|
||||
SELECT payment.payment_id AS "payment.payment_id",
|
||||
payment.amount AS "payment.amount"
|
||||
FROM dvds.payment
|
||||
WHERE payment.amount >= 200
|
||||
)
|
||||
SELECT payment.payment_id AS "payment.payment_id",
|
||||
payment.amount AS "payment.amount"
|
||||
FROM dvds.payment
|
||||
WHERE payment.amount <= 100
|
||||
)
|
||||
UNION ALL
|
||||
(
|
||||
SELECT payment.payment_id AS "payment.payment_id",
|
||||
payment.amount AS "payment.amount"
|
||||
FROM dvds.payment
|
||||
WHERE payment.amount >= 200
|
||||
)
|
||||
ORDER BY "payment.payment_id" ASC, "payment.amount" DESC
|
||||
LIMIT 10
|
||||
|
|
@ -1510,7 +1506,7 @@ ORDER BY actor.actor_id ASC, film.film_id ASC;
|
|||
assert.NilError(t, err)
|
||||
|
||||
//jsonSave("./testdata/quick-start-dest.json", dest)
|
||||
testutils.AssertJSONFile(t, dest, "./postgres/testdata/quick-start-dest.json")
|
||||
testutils.AssertJSONFile(t, dest, "./testdata/results/postgres/quick-start-dest.json")
|
||||
|
||||
var dest2 []struct {
|
||||
model.Category
|
||||
|
|
@ -1523,7 +1519,7 @@ ORDER BY actor.actor_id ASC, film.film_id ASC;
|
|||
assert.NilError(t, err)
|
||||
|
||||
//jsonSave("./testdata/quick-start-dest2.json", dest2)
|
||||
testutils.AssertJSONFile(t, dest2, "./postgres/testdata/quick-start-dest2.json")
|
||||
testutils.AssertJSONFile(t, dest2, "./testdata/results/postgres/quick-start-dest2.json")
|
||||
}
|
||||
|
||||
func TestQuickStartWithSubQueries(t *testing.T) {
|
||||
|
|
@ -1575,7 +1571,7 @@ func TestQuickStartWithSubQueries(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
|
||||
//jsonSave("./testdata/quick-start-dest.json", dest)
|
||||
testutils.AssertJSONFile(t, dest, "./postgres/testdata/quick-start-dest.json")
|
||||
testutils.AssertJSONFile(t, dest, "./testdata/results/postgres/quick-start-dest.json")
|
||||
|
||||
var dest2 []struct {
|
||||
model.Category
|
||||
|
|
@ -1588,7 +1584,7 @@ func TestQuickStartWithSubQueries(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
|
||||
//jsonSave("./testdata/quick-start-dest2.json", dest2)
|
||||
testutils.AssertJSONFile(t, dest2, "./postgres/testdata/quick-start-dest2.json")
|
||||
testutils.AssertJSONFile(t, dest2, "./testdata/results/postgres/quick-start-dest2.json")
|
||||
}
|
||||
|
||||
func TestExpressionWrappers(t *testing.T) {
|
||||
|
|
|
|||
1978
tests/postgres/testdata/customer_payment_sum.json
vendored
1978
tests/postgres/testdata/customer_payment_sum.json
vendored
File diff suppressed because it is too large
Load diff
252320
tests/postgres/testdata/joined_everything.json
vendored
252320
tests/postgres/testdata/joined_everything.json
vendored
File diff suppressed because it is too large
Load diff
135339
tests/postgres/testdata/northwind-all.json
vendored
135339
tests/postgres/testdata/northwind-all.json
vendored
File diff suppressed because it is too large
Load diff
6067
tests/postgres/testdata/quick-start-dest.json
vendored
6067
tests/postgres/testdata/quick-start-dest.json
vendored
File diff suppressed because it is too large
Load diff
1769
tests/postgres/testdata/quick-start-dest2.json
vendored
1769
tests/postgres/testdata/quick-start-dest2.json
vendored
File diff suppressed because it is too large
Load diff
1
tests/testdata
Submodule
1
tests/testdata
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 7f3f3cc26ce34324f3699d6b422376671b827490
|
||||
38
tests/testdata/common/bool_operators.json
vendored
38
tests/testdata/common/bool_operators.json
vendored
|
|
@ -1,38 +0,0 @@
|
|||
[
|
||||
{
|
||||
"Eq1": false,
|
||||
"Eq2": false,
|
||||
"NEq1": true,
|
||||
"NEq2": false,
|
||||
"Distinct1": true,
|
||||
"Distinct2": true,
|
||||
"NotDistinct1": false,
|
||||
"NotDistinct2": false,
|
||||
"IsTrue": false,
|
||||
"IsNotTrue": true,
|
||||
"IsFalse": true,
|
||||
"IsNotFalse": false,
|
||||
"IsUnknown": false,
|
||||
"IsNotUnknown": true,
|
||||
"Complex1": true,
|
||||
"Complex2": true
|
||||
},
|
||||
{
|
||||
"Eq1": null,
|
||||
"Eq2": false,
|
||||
"NEq1": null,
|
||||
"NEq2": false,
|
||||
"Distinct1": true,
|
||||
"Distinct2": true,
|
||||
"NotDistinct1": false,
|
||||
"NotDistinct2": false,
|
||||
"IsTrue": false,
|
||||
"IsNotTrue": true,
|
||||
"IsFalse": true,
|
||||
"IsNotFalse": false,
|
||||
"IsUnknown": false,
|
||||
"IsNotUnknown": true,
|
||||
"Complex1": true,
|
||||
"Complex2": true
|
||||
}
|
||||
]
|
||||
93
tests/testdata/common/common.go
vendored
93
tests/testdata/common/common.go
vendored
|
|
@ -1,93 +0,0 @@
|
|||
package common
|
||||
|
||||
type ExpressionTestResult struct {
|
||||
IsNull *bool
|
||||
IsNotNull *bool
|
||||
In *bool
|
||||
InSelect *bool
|
||||
NotIn *bool
|
||||
NotInSelect *bool
|
||||
}
|
||||
|
||||
type EqualityExpResult struct {
|
||||
Eq1 *bool
|
||||
Eq2 *bool
|
||||
Distinct1 *bool
|
||||
Distinct2 *bool
|
||||
NotDistinct1 *bool
|
||||
NotDistinct2 *bool
|
||||
Lt1 *bool
|
||||
Lt2 *bool
|
||||
Lte1 *bool
|
||||
Lte2 *bool
|
||||
Gt1 *bool
|
||||
Gt2 *bool
|
||||
Gte1 *bool
|
||||
Gte2 *bool
|
||||
}
|
||||
|
||||
type AllTypesIntegerExpResult struct {
|
||||
EqualityExpResult `alias:"."`
|
||||
|
||||
Add1 *int64
|
||||
Add2 *int64
|
||||
Sub1 *int64
|
||||
Sub2 *int64
|
||||
Mul1 *int64
|
||||
Mul2 *int64
|
||||
Div1 *int64
|
||||
Div2 *int64
|
||||
Mod1 *int64
|
||||
Mod2 *int64
|
||||
Pow1 *int64
|
||||
Pow2 *int64
|
||||
BitAnd1 *int64
|
||||
BitAnd2 *int64
|
||||
BitOr1 *int64
|
||||
BitOr2 *int64
|
||||
BitXor1 *int64
|
||||
BitXor2 *int64
|
||||
BitShiftLeft1 *int64
|
||||
BitShiftLeft2 *int64
|
||||
BitShiftRight1 *int64
|
||||
BitShiftRight2 *int64
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
76
tests/testdata/common/float_operators.json
vendored
76
tests/testdata/common/float_operators.json
vendored
|
|
@ -1,76 +0,0 @@
|
|||
[
|
||||
{
|
||||
"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
|
||||
}
|
||||
]
|
||||
78
tests/testdata/common/int_operators.json
vendored
78
tests/testdata/common/int_operators.json
vendored
|
|
@ -1,78 +0,0 @@
|
|||
[
|
||||
{
|
||||
"Eq1": true,
|
||||
"Eq2": false,
|
||||
"Distinct1": false,
|
||||
"Distinct2": true,
|
||||
"NotDistinct1": true,
|
||||
"NotDistinct2": false,
|
||||
"Lt1": true,
|
||||
"Lt2": false,
|
||||
"Lte1": true,
|
||||
"Lte2": false,
|
||||
"Gt1": false,
|
||||
"Gt2": true,
|
||||
"Gte1": false,
|
||||
"Gte2": true,
|
||||
"Add1": 10000,
|
||||
"Add2": 5011,
|
||||
"Sub1": 0,
|
||||
"Sub2": 4989,
|
||||
"Mul1": 25000000,
|
||||
"Mul2": 55000,
|
||||
"Div1": 1,
|
||||
"Div2": 454,
|
||||
"Mod1": 0,
|
||||
"Mod2": 6,
|
||||
"Pow1": 38416,
|
||||
"Pow2": 7529536,
|
||||
"BitAnd1": 14,
|
||||
"BitAnd2": 14,
|
||||
"BitOr1": 14,
|
||||
"BitOr2": 30,
|
||||
"BitXor1": 0,
|
||||
"BitXor2": 5,
|
||||
"BitShiftLeft1": 1792,
|
||||
"BitShiftLeft2": 224,
|
||||
"BitShiftRight1": 3,
|
||||
"BitShiftRight2": 7
|
||||
},
|
||||
{
|
||||
"Eq1": true,
|
||||
"Eq2": false,
|
||||
"Distinct1": false,
|
||||
"Distinct2": true,
|
||||
"NotDistinct1": true,
|
||||
"NotDistinct2": false,
|
||||
"Lt1": null,
|
||||
"Lt2": false,
|
||||
"Lte1": null,
|
||||
"Lte2": false,
|
||||
"Gt1": null,
|
||||
"Gt2": true,
|
||||
"Gte1": null,
|
||||
"Gte2": true,
|
||||
"Add1": 10000,
|
||||
"Add2": 5011,
|
||||
"Sub1": 0,
|
||||
"Sub2": 4989,
|
||||
"Mul1": 25000000,
|
||||
"Mul2": 55000,
|
||||
"Div1": 1,
|
||||
"Div2": 454,
|
||||
"Mod1": 0,
|
||||
"Mod2": 6,
|
||||
"Pow1": 38416,
|
||||
"Pow2": 7529536,
|
||||
"BitAnd1": 14,
|
||||
"BitAnd2": 14,
|
||||
"BitOr1": 14,
|
||||
"BitOr2": 30,
|
||||
"BitXor1": 0,
|
||||
"BitXor2": 5,
|
||||
"BitShiftLeft1": 1792,
|
||||
"BitShiftLeft2": 224,
|
||||
"BitShiftRight1": 3,
|
||||
"BitShiftRight2": 7
|
||||
}
|
||||
]
|
||||
Loading…
Add table
Add a link
Reference in a new issue