Merge pull request #8 from go-jet/mariadb

Add MariaDB support.
This commit is contained in:
go-jet 2019-08-16 13:02:31 +02:00 committed by GitHub
commit 7924d13875
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
62 changed files with 608 additions and 528067 deletions

View file

@ -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
View file

@ -18,3 +18,4 @@
# Test files
gen
.gentestdata
.tests/testdata/

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "tests/testdata"]
path = tests/testdata
url = https://github.com/go-jet/jet-test-data

View file

@ -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';
`
}

View file

@ -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

View file

@ -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
}

View file

@ -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
InNewLine bool
}
func (d *ClauseOptional) Serialize(statementType StatementType, out *SqlBuilder) {
if !d.Show {
return
}
if d.InNewLine {
out.NewLine()
}
out.WriteString(d.Name)
}

View file

@ -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
@ -16,7 +17,8 @@ type QueryPlaceholderFunc func(ord int) string
type DialectParams struct {
Name string
PackageName string
SerializeOverrides map[string]SerializeOverride
OperatorSerializeOverrides map[string]SerializeOverride
FunctionSerializeOverrides map[string]SerializeOverride
AliasQuoteChar byte
IdentifierQuoteChar byte
ArgumentPlaceholder QueryPlaceholderFunc
@ -26,7 +28,8 @@ func NewDialect(params DialectParams) Dialect {
return &dialectImpl{
name: params.Name,
packageName: params.PackageName,
serializeOverrides: params.SerializeOverrides,
operatorSerializeOverrides: params.OperatorSerializeOverrides,
functionSerializeOverrides: params.FunctionSerializeOverrides,
aliasQuoteChar: params.AliasQuoteChar,
identifierQuoteChar: params.IdentifierQuoteChar,
argumentPlaceholder: params.ArgumentPlaceholder,
@ -36,7 +39,8 @@ func NewDialect(params DialectParams) Dialect {
type dialectImpl struct {
name string
packageName string
serializeOverrides map[string]SerializeOverride
operatorSerializeOverrides map[string]SerializeOverride
functionSerializeOverrides map[string]SerializeOverride
aliasQuoteChar byte
identifierQuoteChar byte
argumentPlaceholder QueryPlaceholderFunc
@ -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 {

View file

@ -78,16 +78,21 @@ func (e *ExpressionInterfaceImpl) serializeForOrderBy(statement StatementType, o
// Representation of binary operations (e.g. comparisons, arithmetic)
type binaryOpExpression struct {
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)

View file

@ -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

View file

@ -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) {

View file

@ -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

View file

@ -2,6 +2,8 @@ package jet
const (
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, "~")
}

View file

@ -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

View file

@ -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) {

View file

@ -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)

View file

@ -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

View file

@ -8,17 +8,19 @@ 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,
OperatorSerializeOverrides: operatorSerializeOverrides,
AliasQuoteChar: '"',
IdentifierQuoteChar: '`',
ArgumentPlaceholder: func(int) string {
@ -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...)
}
}

View file

@ -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")
}

View file

@ -32,5 +32,3 @@ var TimestampExp = jet.TimestampExp
var Raw = jet.Raw
var NewEnumValue = jet.NewEnumValue
type Statement jet.Statement

View file

@ -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")
}

View file

@ -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

View file

@ -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
@ -66,6 +69,7 @@ type selectStatementImpl struct {
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)
}

View file

@ -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;
`)
}

View file

@ -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
View 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
}

View file

@ -3,21 +3,21 @@ 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,
OperatorSerializeOverrides: operatorSerializeOverrides,
AliasQuoteChar: '"',
IdentifierQuoteChar: '"',
ArgumentPlaceholder: func(ord int) string {
@ -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...)
}
}

View file

@ -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) {

View file

@ -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

View file

@ -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

View file

@ -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
View 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

View file

@ -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

View file

@ -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');

View file

@ -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,

View file

@ -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)),
}
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,6 +802,19 @@ LIMIT ?;
//testutils.PrintJson(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",
@ -796,6 +826,8 @@ LIMIT ?;
"TimestampT": "2009-11-17T19:34:58.351387Z"
}
`)
}
}
var allTypesJson = `

View file

@ -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)
}

View file

@ -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()

View file

@ -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",
(
@ -181,7 +189,6 @@ SELECT payment.payment_id AS "payment.payment_id",
FROM dvds.customer
LIMIT ?
),
(
(
(
SELECT payment.payment_id AS "payment.payment_id"
@ -196,7 +203,6 @@ SELECT payment.payment_id AS "payment.payment_id",
LIMIT ?
OFFSET ?
)
)
LIMIT ?
)
FROM dvds.payment
@ -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
(
)
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
(
)
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)
}

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

File diff suppressed because it is too large Load diff

View file

@ -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()

View file

@ -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) {

View file

@ -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
(
)
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))

View file

@ -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")
}

View file

@ -126,7 +126,6 @@ SELECT payment.payment_id AS "payment.payment_id",
FROM dvds.customer
LIMIT 1
),
(
(
(
SELECT payment.payment_id AS "payment.payment_id"
@ -141,7 +140,6 @@ SELECT payment.payment_id AS "payment.payment_id",
LIMIT 1
OFFSET 2
)
)
LIMIT 1
)
FROM dvds.payment
@ -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
(
)
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) {

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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

1
tests/testdata Submodule

@ -0,0 +1 @@
Subproject commit 7f3f3cc26ce34324f3699d6b422376671b827490

View file

@ -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
}
]

View file

@ -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
}

View file

@ -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
}
]

View file

@ -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
}
]