Table interface cleanup.

This commit is contained in:
zer0sub 2019-06-05 17:15:20 +02:00
parent 8f51662fe5
commit 4d7fbf8f49
32 changed files with 543 additions and 794 deletions

View file

@ -20,10 +20,6 @@ var sqlBuilderTableTemplate = `
{{- end}} {{- end}}
{{- end}} {{- end}}
{{define "nullable" -}}
{{- if .IsNullable}}sqlbuilder.Nullable{{else}}sqlbuilder.NotNullable{{end}}
{{- end}}
package table package table
import ( import (
@ -46,12 +42,12 @@ var {{camelize .Name}} = new{{.GoStructName}}()
func new{{.GoStructName}}() *{{.GoStructName}} { func new{{.GoStructName}}() *{{.GoStructName}} {
var ( var (
{{- range .Columns}} {{- range .Columns}}
{{camelize .Name}}Column = sqlbuilder.New{{.SqlBuilderColumnType}}("{{.Name}}", {{template "nullable" .}}) {{camelize .Name}}Column = sqlbuilder.New{{.SqlBuilderColumnType}}("{{.Name}}", {{.IsNullable}})
{{- end}} {{- end}}
) )
return &{{.GoStructName}}{ return &{{.GoStructName}}{
Table: *sqlbuilder.NewTable("{{.SchemaName}}", "{{.Name}}", {{template "column-list" .Columns}}), Table: sqlbuilder.NewTable("{{.SchemaName}}", "{{.Name}}", {{template "column-list" .Columns}}),
//Columns //Columns
{{- range .Columns}} {{- range .Columns}}
@ -65,7 +61,7 @@ func new{{.GoStructName}}() *{{.GoStructName}} {
func (a *{{.GoStructName}}) AS(alias string) *{{.GoStructName}} { func (a *{{.GoStructName}}) AS(alias string) *{{.GoStructName}} {
aliasTable := new{{.GoStructName}}() aliasTable := new{{.GoStructName}}()
aliasTable.Table.SetAlias(alias) aliasTable.Table.AS(alias)
return aliasTable return aliasTable
} }

View file

@ -40,35 +40,35 @@ func (b *boolInterfaceImpl) IS_NOT_DISTINCT_FROM(rhs BoolExpression) BoolExpress
} }
func (b *boolInterfaceImpl) AND(expression BoolExpression) BoolExpression { func (b *boolInterfaceImpl) AND(expression BoolExpression) BoolExpression {
return And(b.parent, expression) return newBinaryBoolExpression(b.parent, expression, "AND")
} }
func (b *boolInterfaceImpl) OR(expression BoolExpression) BoolExpression { func (b *boolInterfaceImpl) OR(expression BoolExpression) BoolExpression {
return Or(b.parent, expression) return newBinaryBoolExpression(b.parent, expression, "OR")
} }
func (b *boolInterfaceImpl) IS_TRUE() BoolExpression { func (b *boolInterfaceImpl) IS_TRUE() BoolExpression {
return IS_TRUE(b.parent) return newPostifxBoolExpression(b.parent, "IS TRUE")
} }
func (b *boolInterfaceImpl) IS_NOT_TRUE() BoolExpression { func (b *boolInterfaceImpl) IS_NOT_TRUE() BoolExpression {
return IS_NOT_TRUE(b.parent) return newPostifxBoolExpression(b.parent, "IS NOT TRUE")
} }
func (b *boolInterfaceImpl) IS_FALSE() BoolExpression { func (b *boolInterfaceImpl) IS_FALSE() BoolExpression {
return IS_FALSE(b.parent) return newPostifxBoolExpression(b.parent, "IS FALSE")
} }
func (b *boolInterfaceImpl) IS_NOT_FALSE() BoolExpression { func (b *boolInterfaceImpl) IS_NOT_FALSE() BoolExpression {
return IS_NOT_FALSE(b.parent) return newPostifxBoolExpression(b.parent, "IS NOT FALSE")
} }
func (b *boolInterfaceImpl) IS_UNKNOWN() BoolExpression { func (b *boolInterfaceImpl) IS_UNKNOWN() BoolExpression {
return IS_UNKNOWN(b.parent) return newPostifxBoolExpression(b.parent, "IS UNKNOWN")
} }
func (b *boolInterfaceImpl) IS_NOT_UNKNOWN() BoolExpression { func (b *boolInterfaceImpl) IS_NOT_UNKNOWN() BoolExpression {
return IS_NOT_UNKNOWN(b.parent) return newPostifxBoolExpression(b.parent, "IS NOT UNKNOWN")
} }
//---------------------------------------------------// //---------------------------------------------------//

View file

@ -5,62 +5,62 @@ import (
) )
func TestBoolExpressionEQ(t *testing.T) { func TestBoolExpressionEQ(t *testing.T) {
assertExpressionSerialize(t, table1ColBool.EQ(table2ColBool), "(table1.colBool = table2.colBool)") assertClauseSerialize(t, table1ColBool.EQ(table2ColBool), "(table1.colBool = table2.colBool)")
assertExpressionSerialize(t, table1ColBool.EQ(Bool(true)), "(table1.colBool = $1)", true) assertClauseSerialize(t, table1ColBool.EQ(Bool(true)), "(table1.colBool = $1)", true)
} }
func TestBoolExpressionNOT_EQ(t *testing.T) { func TestBoolExpressionNOT_EQ(t *testing.T) {
assertExpressionSerialize(t, table1ColBool.NOT_EQ(table2ColBool), "(table1.colBool != table2.colBool)") assertClauseSerialize(t, table1ColBool.NOT_EQ(table2ColBool), "(table1.colBool != table2.colBool)")
assertExpressionSerialize(t, table1ColBool.NOT_EQ(Bool(true)), "(table1.colBool != $1)", true) assertClauseSerialize(t, table1ColBool.NOT_EQ(Bool(true)), "(table1.colBool != $1)", true)
} }
func TestBoolExpressionIS_TRUE(t *testing.T) { func TestBoolExpressionIS_TRUE(t *testing.T) {
assertExpressionSerialize(t, table1ColBool.IS_TRUE(), "table1.colBool IS TRUE") assertClauseSerialize(t, table1ColBool.IS_TRUE(), "table1.colBool IS TRUE")
assertExpressionSerialize(t, (Int(2).EQ(table1ColInt)).IS_TRUE(), assertClauseSerialize(t, (Int(2).EQ(table1ColInt)).IS_TRUE(),
`($1 = table1.colInt) IS TRUE`, int64(2)) `($1 = table1.colInt) IS TRUE`, int64(2))
assertExpressionSerialize(t, (Int(2).EQ(table1ColInt)).IS_TRUE().AND(Int(4).EQ(table2ColInt)), assertClauseSerialize(t, (Int(2).EQ(table1ColInt)).IS_TRUE().AND(Int(4).EQ(table2ColInt)),
`(($1 = table1.colInt) IS TRUE AND ($2 = table2.colInt))`, int64(2), int64(4)) `(($1 = table1.colInt) IS TRUE AND ($2 = table2.colInt))`, int64(2), int64(4))
} }
func TestBoolExpressionIS_NOT_TRUE(t *testing.T) { func TestBoolExpressionIS_NOT_TRUE(t *testing.T) {
assertExpressionSerialize(t, table1ColBool.IS_NOT_TRUE(), "table1.colBool IS NOT TRUE") assertClauseSerialize(t, table1ColBool.IS_NOT_TRUE(), "table1.colBool IS NOT TRUE")
} }
func TestBoolExpressionIS_FALSE(t *testing.T) { func TestBoolExpressionIS_FALSE(t *testing.T) {
assertExpressionSerialize(t, table1ColBool.IS_FALSE(), "table1.colBool IS FALSE") assertClauseSerialize(t, table1ColBool.IS_FALSE(), "table1.colBool IS FALSE")
} }
func TestBoolExpressionIS_NOT_FALSE(t *testing.T) { func TestBoolExpressionIS_NOT_FALSE(t *testing.T) {
assertExpressionSerialize(t, table1ColBool.IS_NOT_FALSE(), "table1.colBool IS NOT FALSE") assertClauseSerialize(t, table1ColBool.IS_NOT_FALSE(), "table1.colBool IS NOT FALSE")
} }
func TestBoolExpressionIS_UNKNOWN(t *testing.T) { func TestBoolExpressionIS_UNKNOWN(t *testing.T) {
assertExpressionSerialize(t, table1ColBool.IS_UNKNOWN(), "table1.colBool IS UNKNOWN") assertClauseSerialize(t, table1ColBool.IS_UNKNOWN(), "table1.colBool IS UNKNOWN")
} }
func TestBoolExpressionIS_NOT_UNKNOWN(t *testing.T) { func TestBoolExpressionIS_NOT_UNKNOWN(t *testing.T) {
assertExpressionSerialize(t, table1ColBool.IS_NOT_UNKNOWN(), "table1.colBool IS NOT UNKNOWN") assertClauseSerialize(t, table1ColBool.IS_NOT_UNKNOWN(), "table1.colBool IS NOT UNKNOWN")
} }
func TestBinaryBoolExpression(t *testing.T) { func TestBinaryBoolExpression(t *testing.T) {
boolExpression := Int(2).EQ(Int(3)) boolExpression := Int(2).EQ(Int(3))
assertExpressionSerialize(t, boolExpression, "($1 = $2)", int64(2), int64(3)) assertClauseSerialize(t, boolExpression, "($1 = $2)", int64(2), int64(3))
assertProjectionSerialize(t, boolExpression.AS("alias_eq_expression"), assertProjectionSerialize(t, boolExpression.AS("alias_eq_expression"),
`$1 = $2 AS "alias_eq_expression"`, int64(2), int64(3)) `$1 = $2 AS "alias_eq_expression"`, int64(2), int64(3))
assertExpressionSerialize(t, boolExpression.AND(Int(4).EQ(Int(5))), assertClauseSerialize(t, boolExpression.AND(Int(4).EQ(Int(5))),
"(($1 = $2) AND ($3 = $4))", int64(2), int64(3), int64(4), int64(5)) "(($1 = $2) AND ($3 = $4))", int64(2), int64(3), int64(4), int64(5))
assertExpressionSerialize(t, boolExpression.OR(Int(4).EQ(Int(5))), assertClauseSerialize(t, boolExpression.OR(Int(4).EQ(Int(5))),
"(($1 = $2) OR ($3 = $4))", int64(2), int64(3), int64(4), int64(5)) "(($1 = $2) OR ($3 = $4))", int64(2), int64(3), int64(4), int64(5))
} }
func TestBoolLiteral(t *testing.T) { func TestBoolLiteral(t *testing.T) {
assertExpressionSerialize(t, Bool(true), "$1", true) assertClauseSerialize(t, Bool(true), "$1", true)
assertExpressionSerialize(t, Bool(false), "$1", false) assertClauseSerialize(t, Bool(false), "$1", false)
} }
func TestExists(t *testing.T) { func TestExists(t *testing.T) {
assertExpressionSerialize(t, EXISTS( assertClauseSerialize(t, EXISTS(
table2. table2.
SELECT(Int(1)). SELECT(Int(1)).
WHERE(table1Col1.EQ(table2Col3)), WHERE(table1Col1.EQ(table2Col3)),

View file

@ -65,7 +65,7 @@ func (q *queryData) writeProjection(statement statementType, projections []proje
return err return err
} }
func (q *queryData) writeFrom(statement statementType, table tableInterface) error { func (q *queryData) writeFrom(statement statementType, table ReadableTable) error {
q.nextLine() q.nextLine()
q.writeString("FROM") q.writeString("FROM")

View file

@ -6,53 +6,31 @@ import (
"strings" "strings"
) )
type column interface { type Column interface {
Expression Expression
Name() string Name() string
TableName() string TableName() string
IsNullable() bool
DefaultAlias() projection DefaultAlias() projection
// Internal function for tracking tableName that a column belongs to // Internal function for tracking tableName that a column belongs to
// for the purpose of serialization // for the purpose of serialization
setTableName(table string) setTableName(table string)
} }
type NullableColumn bool
const (
Nullable NullableColumn = true
NotNullable NullableColumn = false
)
type Collation string
const (
UTF8CaseInsensitive Collation = "utf8_unicode_ci"
UTF8CaseSensitive Collation = "utf8_unicode"
UTF8Binary Collation = "utf8_bin"
)
// Representation of MySQL charsets
type Charset string
const (
UTF8 Charset = "utf8"
)
// The base type for real materialized columns. // The base type for real materialized columns.
type baseColumn struct { type baseColumn struct {
expressionInterfaceImpl expressionInterfaceImpl
name string name string
nullable NullableColumn isNullable bool
tableName string tableName string
} }
func newBaseColumn(name string, nullable NullableColumn, tableName string, parent column) baseColumn { func newBaseColumn(name string, isNullable bool, tableName string, parent Column) baseColumn {
bc := baseColumn{ bc := baseColumn{
name: name, name: name,
nullable: nullable, isNullable: isNullable,
tableName: tableName, tableName: tableName,
} }
@ -73,6 +51,10 @@ func (c *baseColumn) setTableName(table string) {
c.tableName = table c.tableName = table
} }
func (c *baseColumn) IsNullable() bool {
return c.isNullable
}
func (c *baseColumn) DefaultAlias() projection { func (c *baseColumn) DefaultAlias() projection {
return c.AS(c.tableName + "." + c.name) return c.AS(c.tableName + "." + c.name)
} }

View file

@ -7,10 +7,10 @@ type BoolColumn struct {
baseColumn baseColumn
} }
func NewBoolColumn(name string, nullable NullableColumn) *BoolColumn { func NewBoolColumn(name string, isNullable bool) *BoolColumn {
boolColumn := &BoolColumn{} boolColumn := &BoolColumn{}
boolColumn.baseColumn = newBaseColumn(name, nullable, "", boolColumn) boolColumn.baseColumn = newBaseColumn(name, isNullable, "", boolColumn)
boolColumn.boolInterfaceImpl.parent = boolColumn boolColumn.boolInterfaceImpl.parent = boolColumn
@ -23,13 +23,13 @@ type FloatColumn struct {
baseColumn baseColumn
} }
func NewFloatColumn(name string, nullable NullableColumn) *FloatColumn { func NewFloatColumn(name string, isNullable bool) *FloatColumn {
floatColumn := &FloatColumn{} floatColumn := &FloatColumn{}
floatColumn.floatInterfaceImpl.parent = floatColumn floatColumn.floatInterfaceImpl.parent = floatColumn
floatColumn.baseColumn = newBaseColumn(name, nullable, "", floatColumn) floatColumn.baseColumn = newBaseColumn(name, isNullable, "", floatColumn)
return floatColumn return floatColumn
} }
@ -43,12 +43,12 @@ type IntegerColumn struct {
// Representation of any integer column // Representation of any integer column
// This function will panic if name is not valid // This function will panic if name is not valid
func NewIntegerColumn(name string, nullable NullableColumn) *IntegerColumn { func NewIntegerColumn(name string, isNullable bool) *IntegerColumn {
integerColumn := &IntegerColumn{} integerColumn := &IntegerColumn{}
integerColumn.integerInterfaceImpl.parent = integerColumn integerColumn.integerInterfaceImpl.parent = integerColumn
integerColumn.baseColumn = newBaseColumn(name, nullable, "", integerColumn) integerColumn.baseColumn = newBaseColumn(name, isNullable, "", integerColumn)
return integerColumn return integerColumn
} }
@ -62,13 +62,13 @@ type StringColumn struct {
// Representation of any integer column // Representation of any integer column
// This function will panic if name is not valid // This function will panic if name is not valid
func NewStringColumn(name string, nullable NullableColumn) *StringColumn { func NewStringColumn(name string, isNullable bool) *StringColumn {
stringColumn := &StringColumn{} stringColumn := &StringColumn{}
stringColumn.stringInterfaceImpl.parent = stringColumn stringColumn.stringInterfaceImpl.parent = stringColumn
stringColumn.baseColumn = newBaseColumn(name, nullable, "", stringColumn) stringColumn.baseColumn = newBaseColumn(name, isNullable, "", stringColumn)
return stringColumn return stringColumn
} }
@ -82,12 +82,12 @@ type TimeColumn struct {
// Representation of any integer column // Representation of any integer column
// This function will panic if name is not valid // This function will panic if name is not valid
func NewTimeColumn(name string, nullable NullableColumn) *TimeColumn { func NewTimeColumn(name string, isNullable bool) *TimeColumn {
timeColumn := &TimeColumn{} timeColumn := &TimeColumn{}
timeColumn.timeInterfaceImpl.parent = timeColumn timeColumn.timeInterfaceImpl.parent = timeColumn
timeColumn.baseColumn = newBaseColumn(name, nullable, "", timeColumn) timeColumn.baseColumn = newBaseColumn(name, isNullable, "", timeColumn)
return timeColumn return timeColumn
} }
@ -101,12 +101,12 @@ type TimezColumn struct {
// Representation of any integer column // Representation of any integer column
// This function will panic if name is not valid // This function will panic if name is not valid
func NewTimezColumn(name string, nullable NullableColumn) *TimezColumn { func NewTimezColumn(name string, isNullable bool) *TimezColumn {
timezColumn := &TimezColumn{} timezColumn := &TimezColumn{}
timezColumn.timezInterfaceImpl.parent = timezColumn timezColumn.timezInterfaceImpl.parent = timezColumn
timezColumn.baseColumn = newBaseColumn(name, nullable, "", timezColumn) timezColumn.baseColumn = newBaseColumn(name, isNullable, "", timezColumn)
return timezColumn return timezColumn
} }
@ -120,12 +120,12 @@ type TimestampColumn struct {
// Representation of any integer column // Representation of any integer column
// This function will panic if name is not valid // This function will panic if name is not valid
func NewTimestampColumn(name string, nullable NullableColumn) *TimestampColumn { func NewTimestampColumn(name string, isNullable bool) *TimestampColumn {
timestampColumn := &TimestampColumn{} timestampColumn := &TimestampColumn{}
timestampColumn.timestampInterfaceImpl.parent = timestampColumn timestampColumn.timestampInterfaceImpl.parent = timestampColumn
timestampColumn.baseColumn = newBaseColumn(name, nullable, "", timestampColumn) timestampColumn.baseColumn = newBaseColumn(name, isNullable, "", timestampColumn)
return timestampColumn return timestampColumn
} }
@ -139,12 +139,12 @@ type TimestampzColumn struct {
// Representation of any integer column // Representation of any integer column
// This function will panic if name is not valid // This function will panic if name is not valid
func NewTimestampzColumn(name string, nullable NullableColumn) *TimestampzColumn { func NewTimestampzColumn(name string, isNullable bool) *TimestampzColumn {
timestampzColumn := &TimestampzColumn{} timestampzColumn := &TimestampzColumn{}
timestampzColumn.timestampzInterfaceImpl.parent = timestampzColumn timestampzColumn.timestampzInterfaceImpl.parent = timestampzColumn
timestampzColumn.baseColumn = newBaseColumn(name, nullable, "", timestampzColumn) timestampzColumn.baseColumn = newBaseColumn(name, isNullable, "", timestampzColumn)
return timestampzColumn return timestampzColumn
} }
@ -158,12 +158,12 @@ type DateColumn struct {
// Representation of any integer column // Representation of any integer column
// This function will panic if name is not valid // This function will panic if name is not valid
func NewDateColumn(name string, nullable NullableColumn) *DateColumn { func NewDateColumn(name string, isNullable bool) *DateColumn {
dateColumn := &DateColumn{} dateColumn := &DateColumn{}
dateColumn.dateInterfaceImpl.parent = dateColumn dateColumn.dateInterfaceImpl.parent = dateColumn
dateColumn.baseColumn = newBaseColumn(name, nullable, "", dateColumn) dateColumn.baseColumn = newBaseColumn(name, isNullable, "", dateColumn)
return dateColumn return dateColumn
} }

View file

@ -6,7 +6,7 @@ import (
) )
func TestNewBoolColumn(t *testing.T) { func TestNewBoolColumn(t *testing.T) {
boolColumn := NewBoolColumn("col", Nullable) boolColumn := NewBoolColumn("col", false)
out := queryData{} out := queryData{}
err := boolColumn.serialize(select_statement, &out) err := boolColumn.serialize(select_statement, &out)
@ -34,7 +34,7 @@ func TestNewBoolColumn(t *testing.T) {
} }
func TestNewIntColumn(t *testing.T) { func TestNewIntColumn(t *testing.T) {
integerColumn := NewIntegerColumn("col", Nullable) integerColumn := NewIntegerColumn("col", false)
out := queryData{} out := queryData{}
err := integerColumn.serialize(select_statement, &out) err := integerColumn.serialize(select_statement, &out)
@ -62,7 +62,7 @@ func TestNewIntColumn(t *testing.T) {
} }
func TestNewNumericColumnColumn(t *testing.T) { func TestNewNumericColumnColumn(t *testing.T) {
numericColumn := NewFloatColumn("col", Nullable) numericColumn := NewFloatColumn("col", false)
out := queryData{} out := queryData{}
err := numericColumn.serialize(select_statement, &out) err := numericColumn.serialize(select_statement, &out)

View file

@ -2,7 +2,7 @@ package sqlbuilder
import ( import (
"database/sql" "database/sql"
"github.com/dropbox/godropbox/errors" "errors"
"github.com/sub0zero/go-sqlbuilder/sqlbuilder/execution" "github.com/sub0zero/go-sqlbuilder/sqlbuilder/execution"
) )
@ -12,14 +12,14 @@ type DeleteStatement interface {
WHERE(expression BoolExpression) DeleteStatement WHERE(expression BoolExpression) DeleteStatement
} }
func newDeleteStatement(table writableTable) DeleteStatement { func newDeleteStatement(table WritableTable) DeleteStatement {
return &deleteStatementImpl{ return &deleteStatementImpl{
table: table, table: table,
} }
} }
type deleteStatementImpl struct { type deleteStatementImpl struct {
table writableTable table WritableTable
where BoolExpression where BoolExpression
} }
@ -30,7 +30,7 @@ func (d *deleteStatementImpl) WHERE(expression BoolExpression) DeleteStatement {
func (d *deleteStatementImpl) serializeImpl(out *queryData) error { func (d *deleteStatementImpl) serializeImpl(out *queryData) error {
if d == nil { if d == nil {
return errors.New("Delete statement. ") return errors.New("Delete expression. ")
} }
out.nextLine() out.nextLine()
out.writeString("DELETE FROM") out.writeString("DELETE FROM")

View file

@ -1,7 +1,7 @@
package sqlbuilder package sqlbuilder
import ( import (
"github.com/dropbox/godropbox/errors" "errors"
) )
// An Expression // An Expression
@ -139,10 +139,10 @@ func (c *binaryOpExpression) serialize(statement statementType, out *queryData,
return errors.New("Binary Expression is nil.") return errors.New("Binary Expression is nil.")
} }
if c.lhs == nil { if c.lhs == nil {
return errors.Newf("nil lhs.") return errors.New("nil lhs.")
} }
if c.rhs == nil { if c.rhs == nil {
return errors.Newf("nil rhs.") return errors.New("nil rhs.")
} }
wrap := !contains(options, NO_WRAP) wrap := !contains(options, NO_WRAP)
@ -191,7 +191,7 @@ func (p *prefixOpExpression) serialize(statement statementType, out *queryData,
out.writeString(p.operator + " ") out.writeString(p.operator + " ")
if p.expression == nil { if p.expression == nil {
return errors.Newf("nil prefix Expression.") return errors.New("nil prefix Expression.")
} }
if err := p.expression.serialize(statement, out); err != nil { if err := p.expression.serialize(statement, out); err != nil {
return err return err
@ -221,7 +221,7 @@ func (p *postfixOpExpression) serialize(statement statementType, out *queryData,
} }
if p.expression == nil { if p.expression == nil {
return errors.Newf("nil prefix Expression.") return errors.New("nil prefix Expression.")
} }
if err := p.expression.serialize(statement, out); err != nil { if err := p.expression.serialize(statement, out); err != nil {
return err return err

View file

@ -6,15 +6,24 @@ type expressionTable interface {
ReadableTable ReadableTable
RefIntColumnName(name string) *IntegerColumn RefIntColumnName(name string) *IntegerColumn
RefIntColumn(column column) *IntegerColumn RefIntColumn(column Column) *IntegerColumn
RefStringColumn(column column) *StringColumn RefStringColumn(column Column) *StringColumn
} }
type expressionTableImpl struct { type expressionTableImpl struct {
statement Expression readableTableInterfaceImpl
expression Expression
alias string alias string
} }
func newExpressionTable(expression Expression, alias string) expressionTable {
expTable := &expressionTableImpl{expression: expression, alias: alias}
expTable.readableTableInterfaceImpl.parent = expTable
return expTable
}
// Returns the tableName's name in the database // Returns the tableName's name in the database
func (e *expressionTableImpl) SchemaName() string { func (e *expressionTableImpl) SchemaName() string {
return "" return ""
@ -24,26 +33,22 @@ func (e *expressionTableImpl) TableName() string {
return e.alias return e.alias
} }
func (e *expressionTableImpl) Columns() []column {
return []column{}
}
func (e *expressionTableImpl) RefIntColumnName(name string) *IntegerColumn { func (e *expressionTableImpl) RefIntColumnName(name string) *IntegerColumn {
intColumn := NewIntegerColumn(name, NotNullable) intColumn := NewIntegerColumn(name, false)
intColumn.setTableName(e.alias) intColumn.setTableName(e.alias)
return intColumn return intColumn
} }
func (e *expressionTableImpl) RefIntColumn(column column) *IntegerColumn { func (e *expressionTableImpl) RefIntColumn(column Column) *IntegerColumn {
intColumn := NewIntegerColumn(column.TableName()+"."+column.Name(), NotNullable) intColumn := NewIntegerColumn(column.TableName()+"."+column.Name(), false)
intColumn.setTableName(e.alias) intColumn.setTableName(e.alias)
return intColumn return intColumn
} }
func (e *expressionTableImpl) RefStringColumn(column column) *StringColumn { func (e *expressionTableImpl) RefStringColumn(column Column) *StringColumn {
strColumn := NewStringColumn(column.TableName()+"."+column.Name(), NotNullable) strColumn := NewStringColumn(column.TableName()+"."+column.Name(), false)
strColumn.setTableName(e.alias) strColumn.setTableName(e.alias)
return strColumn return strColumn
} }
@ -53,7 +58,7 @@ func (e *expressionTableImpl) serialize(statement statementType, out *queryData,
return errors.New("Expression table is nil. ") return errors.New("Expression table is nil. ")
} }
//out.writeString("( ") //out.writeString("( ")
err := e.statement.serialize(statement, out) err := e.expression.serialize(statement, out)
if err != nil { if err != nil {
return err return err
@ -64,35 +69,3 @@ func (e *expressionTableImpl) serialize(statement statementType, out *queryData,
return nil return nil
} }
// Generates a select query on the current tableName.
func (e *expressionTableImpl) SELECT(projections ...projection) SelectStatement {
return newSelectStatement(e, projections)
}
// Creates a inner join tableName Expression using onCondition.
func (e *expressionTableImpl) INNER_JOIN(table ReadableTable, onCondition BoolExpression) ReadableTable {
return InnerJoinOn(e, table, onCondition)
}
//func (s *expressionTableImpl) InnerJoinUsing(table ReadableTable, col1 column, col2 column) ReadableTable {
// return INNER_JOIN(s, table, col1.EQ(col2))
//}
// Creates a left join tableName Expression using onCondition.
func (e *expressionTableImpl) LEFT_JOIN(table ReadableTable, onCondition BoolExpression) ReadableTable {
return LeftJoinOn(e, table, onCondition)
}
// Creates a right join tableName Expression using onCondition.
func (e *expressionTableImpl) RIGHT_JOIN(table ReadableTable, onCondition BoolExpression) ReadableTable {
return RightJoinOn(e, table, onCondition)
}
func (e *expressionTableImpl) FULL_JOIN(table ReadableTable, onCondition BoolExpression) ReadableTable {
return FullJoin(e, table, onCondition)
}
func (e *expressionTableImpl) CROSS_JOIN(table ReadableTable) ReadableTable {
return CrossJoin(e, table)
}

View file

@ -5,71 +5,71 @@ import (
) )
func TestExpressionIS_NULL(t *testing.T) { func TestExpressionIS_NULL(t *testing.T) {
assertExpressionSerialize(t, table2Col3.IS_NULL(), "table2.col3 IS NULL") assertClauseSerialize(t, table2Col3.IS_NULL(), "table2.col3 IS NULL")
assertExpressionSerialize(t, table2Col3.ADD(table2Col3).IS_NULL(), "(table2.col3 + table2.col3) IS NULL") assertClauseSerialize(t, table2Col3.ADD(table2Col3).IS_NULL(), "(table2.col3 + table2.col3) IS NULL")
} }
func TestExpressionIS_NOT_NULL(t *testing.T) { func TestExpressionIS_NOT_NULL(t *testing.T) {
assertExpressionSerialize(t, table2Col3.IS_NOT_NULL(), "table2.col3 IS NOT NULL") assertClauseSerialize(t, table2Col3.IS_NOT_NULL(), "table2.col3 IS NOT NULL")
assertExpressionSerialize(t, table2Col3.ADD(table2Col3).IS_NOT_NULL(), "(table2.col3 + table2.col3) IS NOT NULL") assertClauseSerialize(t, table2Col3.ADD(table2Col3).IS_NOT_NULL(), "(table2.col3 + table2.col3) IS NOT NULL")
} }
func TestExpressionIS_DISTINCT_FROM(t *testing.T) { func TestExpressionIS_DISTINCT_FROM(t *testing.T) {
assertExpressionSerialize(t, table2Col3.IS_DISTINCT_FROM(table2Col4), "(table2.col3 IS DISTINCT FROM table2.col4)") assertClauseSerialize(t, table2Col3.IS_DISTINCT_FROM(table2Col4), "(table2.col3 IS DISTINCT FROM table2.col4)")
assertExpressionSerialize(t, table2Col3.ADD(table2Col3).IS_DISTINCT_FROM(Int(23)), "((table2.col3 + table2.col3) IS DISTINCT FROM $1)", int64(23)) assertClauseSerialize(t, table2Col3.ADD(table2Col3).IS_DISTINCT_FROM(Int(23)), "((table2.col3 + table2.col3) IS DISTINCT FROM $1)", int64(23))
} }
func TestExpressionIS_NOT_DISTINCT_FROM(t *testing.T) { func TestExpressionIS_NOT_DISTINCT_FROM(t *testing.T) {
assertExpressionSerialize(t, table2Col3.IS_NOT_DISTINCT_FROM(table2Col4), "(table2.col3 IS NOT DISTINCT FROM table2.col4)") assertClauseSerialize(t, table2Col3.IS_NOT_DISTINCT_FROM(table2Col4), "(table2.col3 IS NOT DISTINCT FROM table2.col4)")
assertExpressionSerialize(t, table2Col3.ADD(table2Col3).IS_NOT_DISTINCT_FROM(Int(23)), "((table2.col3 + table2.col3) IS NOT DISTINCT FROM $1)", int64(23)) assertClauseSerialize(t, table2Col3.ADD(table2Col3).IS_NOT_DISTINCT_FROM(Int(23)), "((table2.col3 + table2.col3) IS NOT DISTINCT FROM $1)", int64(23))
} }
func TestExpressionCAST_TO_BOOL(t *testing.T) { func TestExpressionCAST_TO_BOOL(t *testing.T) {
assertExpressionSerialize(t, table2Col3.CAST_TO_BOOL(), "table2.col3::boolean") assertClauseSerialize(t, table2Col3.CAST_TO_BOOL(), "table2.col3::boolean")
assertExpressionSerialize(t, table2Col3.ADD(table2Col3).CAST_TO_BOOL(), "(table2.col3 + table2.col3)::boolean") assertClauseSerialize(t, table2Col3.ADD(table2Col3).CAST_TO_BOOL(), "(table2.col3 + table2.col3)::boolean")
} }
func TestExpressionCAST_TO_INTEGER(t *testing.T) { func TestExpressionCAST_TO_INTEGER(t *testing.T) {
assertExpressionSerialize(t, table2Col3.CAST_TO_INTEGER(), "table2.col3::integer") assertClauseSerialize(t, table2Col3.CAST_TO_INTEGER(), "table2.col3::integer")
} }
func TestExpressionCAST_TO_DOUBLE(t *testing.T) { func TestExpressionCAST_TO_DOUBLE(t *testing.T) {
assertExpressionSerialize(t, table2Col3.CAST_TO_DOUBLE(), "table2.col3::double precision") assertClauseSerialize(t, table2Col3.CAST_TO_DOUBLE(), "table2.col3::double precision")
} }
func TestExpressionCAST_TO_TEXT(t *testing.T) { func TestExpressionCAST_TO_TEXT(t *testing.T) {
assertExpressionSerialize(t, table2Col3.CAST_TO_TEXT(), "table2.col3::text") assertClauseSerialize(t, table2Col3.CAST_TO_TEXT(), "table2.col3::text")
} }
func TestExpressionCAST_TO_DATE(t *testing.T) { func TestExpressionCAST_TO_DATE(t *testing.T) {
assertExpressionSerialize(t, table2Col3.CAST_TO_DATE(), "table2.col3::date") assertClauseSerialize(t, table2Col3.CAST_TO_DATE(), "table2.col3::date")
} }
func TestExpressionCAST_TO_TIME(t *testing.T) { func TestExpressionCAST_TO_TIME(t *testing.T) {
assertExpressionSerialize(t, table2Col3.CAST_TO_TIME(), "table2.col3::time without time zone") assertClauseSerialize(t, table2Col3.CAST_TO_TIME(), "table2.col3::time without time zone")
} }
func TestExpressionCAST_TO_TIMEZ(t *testing.T) { func TestExpressionCAST_TO_TIMEZ(t *testing.T) {
assertExpressionSerialize(t, table2Col3.CAST_TO_TIMEZ(), "table2.col3::time with time zone") assertClauseSerialize(t, table2Col3.CAST_TO_TIMEZ(), "table2.col3::time with time zone")
} }
func TestExpressionCAST_TO_TIMESTAMP(t *testing.T) { func TestExpressionCAST_TO_TIMESTAMP(t *testing.T) {
assertExpressionSerialize(t, table2Col3.CAST_TO_TIMESTAMP(), "table2.col3::timestamp without time zone") assertClauseSerialize(t, table2Col3.CAST_TO_TIMESTAMP(), "table2.col3::timestamp without time zone")
} }
func TestExpressionCAST_TO_TIMESTAMPZ(t *testing.T) { func TestExpressionCAST_TO_TIMESTAMPZ(t *testing.T) {
assertExpressionSerialize(t, table2Col3.CAST_TO_TIMESTAMPZ(), "table2.col3::timestamp with time zone") assertClauseSerialize(t, table2Col3.CAST_TO_TIMESTAMPZ(), "table2.col3::timestamp with time zone")
} }
func TestIN(t *testing.T) { func TestIN(t *testing.T) {
assertExpressionSerialize(t, Float(1.11).IN(table1.SELECT(table1Col1)), assertClauseSerialize(t, Float(1.11).IN(table1.SELECT(table1Col1)),
`($1 IN (( `($1 IN ((
SELECT table1.col1 AS "table1.col1" SELECT table1.col1 AS "table1.col1"
FROM db.table1 FROM db.table1
)))`, float64(1.11)) )))`, float64(1.11))
assertExpressionSerialize(t, ROW(Int(12), table1Col1).IN(table2.SELECT(table2Col3, table3Col1)), assertClauseSerialize(t, ROW(Int(12), table1Col1).IN(table2.SELECT(table2Col3, table3Col1)),
`(ROW($1, table1.col1) IN (( `(ROW($1, table1.col1) IN ((
SELECT table2.col3 AS "table2.col3", SELECT table2.col3 AS "table2.col3",
table3.col1 AS "table3.col1" table3.col1 AS "table3.col1"
@ -79,13 +79,13 @@ func TestIN(t *testing.T) {
func TestNOT_IN(t *testing.T) { func TestNOT_IN(t *testing.T) {
assertExpressionSerialize(t, Float(1.11).NOT_IN(table1.SELECT(table1Col1)), assertClauseSerialize(t, Float(1.11).NOT_IN(table1.SELECT(table1Col1)),
`($1 NOT IN (( `($1 NOT IN ((
SELECT table1.col1 AS "table1.col1" SELECT table1.col1 AS "table1.col1"
FROM db.table1 FROM db.table1
)))`, float64(1.11)) )))`, float64(1.11))
assertExpressionSerialize(t, ROW(Int(12), table1Col1).NOT_IN(table2.SELECT(table2Col3, table3Col1)), assertClauseSerialize(t, ROW(Int(12), table1Col1).NOT_IN(table2.SELECT(table2Col3, table3Col1)),
`(ROW($1, table1.col1) NOT IN (( `(ROW($1, table1.col1) NOT IN ((
SELECT table2.col3 AS "table2.col3", SELECT table2.col3 AS "table2.col3",
table3.col1 AS "table3.col1" table3.col1 AS "table3.col1"

View file

@ -5,61 +5,61 @@ import (
) )
func TestFloatExpressionEQ(t *testing.T) { func TestFloatExpressionEQ(t *testing.T) {
assertExpressionSerialize(t, table1ColFloat.EQ(table2ColFloat), "(table1.colFloat = table2.colFloat)") assertClauseSerialize(t, table1ColFloat.EQ(table2ColFloat), "(table1.colFloat = table2.colFloat)")
assertExpressionSerialize(t, table1ColFloat.EQ(Float(2.11)), "(table1.colFloat = $1)", float64(2.11)) assertClauseSerialize(t, table1ColFloat.EQ(Float(2.11)), "(table1.colFloat = $1)", float64(2.11))
} }
func TestFloatExpressionNOT_EQ(t *testing.T) { func TestFloatExpressionNOT_EQ(t *testing.T) {
assertExpressionSerialize(t, table1ColFloat.NOT_EQ(table2ColFloat), "(table1.colFloat != table2.colFloat)") assertClauseSerialize(t, table1ColFloat.NOT_EQ(table2ColFloat), "(table1.colFloat != table2.colFloat)")
assertExpressionSerialize(t, table1ColFloat.NOT_EQ(Float(2.11)), "(table1.colFloat != $1)", float64(2.11)) assertClauseSerialize(t, table1ColFloat.NOT_EQ(Float(2.11)), "(table1.colFloat != $1)", float64(2.11))
} }
func TestFloatExpressionGT(t *testing.T) { func TestFloatExpressionGT(t *testing.T) {
assertExpressionSerialize(t, table1ColFloat.GT(table2ColFloat), "(table1.colFloat > table2.colFloat)") assertClauseSerialize(t, table1ColFloat.GT(table2ColFloat), "(table1.colFloat > table2.colFloat)")
assertExpressionSerialize(t, table1ColFloat.GT(Float(2.11)), "(table1.colFloat > $1)", float64(2.11)) assertClauseSerialize(t, table1ColFloat.GT(Float(2.11)), "(table1.colFloat > $1)", float64(2.11))
} }
func TestFloatExpressionGT_EQ(t *testing.T) { func TestFloatExpressionGT_EQ(t *testing.T) {
assertExpressionSerialize(t, table1ColFloat.GT_EQ(table2ColFloat), "(table1.colFloat >= table2.colFloat)") assertClauseSerialize(t, table1ColFloat.GT_EQ(table2ColFloat), "(table1.colFloat >= table2.colFloat)")
assertExpressionSerialize(t, table1ColFloat.GT_EQ(Float(2.11)), "(table1.colFloat >= $1)", float64(2.11)) assertClauseSerialize(t, table1ColFloat.GT_EQ(Float(2.11)), "(table1.colFloat >= $1)", float64(2.11))
} }
func TestFloatExpressionLT(t *testing.T) { func TestFloatExpressionLT(t *testing.T) {
assertExpressionSerialize(t, table1ColFloat.LT(table2ColFloat), "(table1.colFloat < table2.colFloat)") assertClauseSerialize(t, table1ColFloat.LT(table2ColFloat), "(table1.colFloat < table2.colFloat)")
assertExpressionSerialize(t, table1ColFloat.LT(Float(2.11)), "(table1.colFloat < $1)", float64(2.11)) assertClauseSerialize(t, table1ColFloat.LT(Float(2.11)), "(table1.colFloat < $1)", float64(2.11))
} }
func TestFloatExpressionLT_EQ(t *testing.T) { func TestFloatExpressionLT_EQ(t *testing.T) {
assertExpressionSerialize(t, table1ColFloat.LT_EQ(table2ColFloat), "(table1.colFloat <= table2.colFloat)") assertClauseSerialize(t, table1ColFloat.LT_EQ(table2ColFloat), "(table1.colFloat <= table2.colFloat)")
assertExpressionSerialize(t, table1ColFloat.LT_EQ(Float(2.11)), "(table1.colFloat <= $1)", float64(2.11)) assertClauseSerialize(t, table1ColFloat.LT_EQ(Float(2.11)), "(table1.colFloat <= $1)", float64(2.11))
} }
func TestFloatExpressionADD(t *testing.T) { func TestFloatExpressionADD(t *testing.T) {
assertExpressionSerialize(t, table1ColFloat.ADD(table2ColFloat), "(table1.colFloat + table2.colFloat)") assertClauseSerialize(t, table1ColFloat.ADD(table2ColFloat), "(table1.colFloat + table2.colFloat)")
assertExpressionSerialize(t, table1ColFloat.ADD(Float(2.11)), "(table1.colFloat + $1)", float64(2.11)) assertClauseSerialize(t, table1ColFloat.ADD(Float(2.11)), "(table1.colFloat + $1)", float64(2.11))
} }
func TestFloatExpressionSUB(t *testing.T) { func TestFloatExpressionSUB(t *testing.T) {
assertExpressionSerialize(t, table1ColFloat.SUB(table2ColFloat), "(table1.colFloat - table2.colFloat)") assertClauseSerialize(t, table1ColFloat.SUB(table2ColFloat), "(table1.colFloat - table2.colFloat)")
assertExpressionSerialize(t, table1ColFloat.SUB(Float(2.11)), "(table1.colFloat - $1)", float64(2.11)) assertClauseSerialize(t, table1ColFloat.SUB(Float(2.11)), "(table1.colFloat - $1)", float64(2.11))
} }
func TestFloatExpressionMUL(t *testing.T) { func TestFloatExpressionMUL(t *testing.T) {
assertExpressionSerialize(t, table1ColFloat.MUL(table2ColFloat), "(table1.colFloat * table2.colFloat)") assertClauseSerialize(t, table1ColFloat.MUL(table2ColFloat), "(table1.colFloat * table2.colFloat)")
assertExpressionSerialize(t, table1ColFloat.MUL(Float(2.11)), "(table1.colFloat * $1)", float64(2.11)) assertClauseSerialize(t, table1ColFloat.MUL(Float(2.11)), "(table1.colFloat * $1)", float64(2.11))
} }
func TestFloatExpressionDIV(t *testing.T) { func TestFloatExpressionDIV(t *testing.T) {
assertExpressionSerialize(t, table1ColFloat.DIV(table2ColFloat), "(table1.colFloat / table2.colFloat)") assertClauseSerialize(t, table1ColFloat.DIV(table2ColFloat), "(table1.colFloat / table2.colFloat)")
assertExpressionSerialize(t, table1ColFloat.DIV(Float(2.11)), "(table1.colFloat / $1)", float64(2.11)) assertClauseSerialize(t, table1ColFloat.DIV(Float(2.11)), "(table1.colFloat / $1)", float64(2.11))
} }
func TestFloatExpressionMOD(t *testing.T) { func TestFloatExpressionMOD(t *testing.T) {
assertExpressionSerialize(t, table1ColFloat.MOD(table2ColFloat), "(table1.colFloat % table2.colFloat)") assertClauseSerialize(t, table1ColFloat.MOD(table2ColFloat), "(table1.colFloat % table2.colFloat)")
assertExpressionSerialize(t, table1ColFloat.MOD(Float(2.11)), "(table1.colFloat % $1)", float64(2.11)) assertClauseSerialize(t, table1ColFloat.MOD(Float(2.11)), "(table1.colFloat % $1)", float64(2.11))
} }
func TestFloatExpressionPOW(t *testing.T) { func TestFloatExpressionPOW(t *testing.T) {
assertExpressionSerialize(t, table1ColFloat.POW(table2ColFloat), "(table1.colFloat ^ table2.colFloat)") assertClauseSerialize(t, table1ColFloat.POW(table2ColFloat), "(table1.colFloat ^ table2.colFloat)")
assertExpressionSerialize(t, table1ColFloat.POW(Float(2.11)), "(table1.colFloat ^ $1)", float64(2.11)) assertClauseSerialize(t, table1ColFloat.POW(Float(2.11)), "(table1.colFloat ^ $1)", float64(2.11))
} }

View file

@ -7,169 +7,169 @@ import (
func TestFuncAVG(t *testing.T) { func TestFuncAVG(t *testing.T) {
t.Run("float", func(t *testing.T) { t.Run("float", func(t *testing.T) {
assertExpressionSerialize(t, AVGf(table1ColFloat), "AVG(table1.colFloat)") assertClauseSerialize(t, AVGf(table1ColFloat), "AVG(table1.colFloat)")
}) })
t.Run("integer", func(t *testing.T) { t.Run("integer", func(t *testing.T) {
assertExpressionSerialize(t, AVGi(table1ColInt), "AVG(table1.colInt)") assertClauseSerialize(t, AVGi(table1ColInt), "AVG(table1.colInt)")
}) })
} }
func TestFuncBIT_AND(t *testing.T) { func TestFuncBIT_AND(t *testing.T) {
assertExpressionSerialize(t, BIT_AND(table1ColInt), "BIT_AND(table1.colInt)") assertClauseSerialize(t, BIT_AND(table1ColInt), "BIT_AND(table1.colInt)")
} }
func TestFuncBIT_OR(t *testing.T) { func TestFuncBIT_OR(t *testing.T) {
assertExpressionSerialize(t, BIT_OR(table1ColInt), "BIT_OR(table1.colInt)") assertClauseSerialize(t, BIT_OR(table1ColInt), "BIT_OR(table1.colInt)")
} }
func TestFuncBOOL_AND(t *testing.T) { func TestFuncBOOL_AND(t *testing.T) {
assertExpressionSerialize(t, BOOL_AND(table1ColBool), "BOOL_AND(table1.colBool)") assertClauseSerialize(t, BOOL_AND(table1ColBool), "BOOL_AND(table1.colBool)")
} }
func TestFuncBOOL_OR(t *testing.T) { func TestFuncBOOL_OR(t *testing.T) {
assertExpressionSerialize(t, BOOL_OR(table1ColBool), "BOOL_OR(table1.colBool)") assertClauseSerialize(t, BOOL_OR(table1ColBool), "BOOL_OR(table1.colBool)")
} }
func TestFuncEVERY(t *testing.T) { func TestFuncEVERY(t *testing.T) {
assertExpressionSerialize(t, EVERY(table1ColBool), "EVERY(table1.colBool)") assertClauseSerialize(t, EVERY(table1ColBool), "EVERY(table1.colBool)")
} }
func TestFuncMIN(t *testing.T) { func TestFuncMIN(t *testing.T) {
t.Run("float", func(t *testing.T) { t.Run("float", func(t *testing.T) {
assertExpressionSerialize(t, MINf(table1ColFloat), "MIN(table1.colFloat)") assertClauseSerialize(t, MINf(table1ColFloat), "MIN(table1.colFloat)")
}) })
t.Run("integer", func(t *testing.T) { t.Run("integer", func(t *testing.T) {
assertExpressionSerialize(t, MINi(table1ColInt), "MIN(table1.colInt)") assertClauseSerialize(t, MINi(table1ColInt), "MIN(table1.colInt)")
}) })
} }
func TestFuncMAX(t *testing.T) { func TestFuncMAX(t *testing.T) {
t.Run("float", func(t *testing.T) { t.Run("float", func(t *testing.T) {
assertExpressionSerialize(t, MAXf(table1ColFloat), "MAX(table1.colFloat)") assertClauseSerialize(t, MAXf(table1ColFloat), "MAX(table1.colFloat)")
assertExpressionSerialize(t, MAXf(Float(11.2222)), "MAX($1)", float64(11.2222)) assertClauseSerialize(t, MAXf(Float(11.2222)), "MAX($1)", float64(11.2222))
}) })
t.Run("integer", func(t *testing.T) { t.Run("integer", func(t *testing.T) {
assertExpressionSerialize(t, MAXi(table1ColInt), "MAX(table1.colInt)") assertClauseSerialize(t, MAXi(table1ColInt), "MAX(table1.colInt)")
assertExpressionSerialize(t, MAXi(Int(11)), "MAX($1)", int64(11)) assertClauseSerialize(t, MAXi(Int(11)), "MAX($1)", int64(11))
}) })
} }
func TestFuncSUM(t *testing.T) { func TestFuncSUM(t *testing.T) {
t.Run("float", func(t *testing.T) { t.Run("float", func(t *testing.T) {
assertExpressionSerialize(t, SUMf(table1ColFloat), "SUM(table1.colFloat)") assertClauseSerialize(t, SUMf(table1ColFloat), "SUM(table1.colFloat)")
assertExpressionSerialize(t, SUMf(Float(11.2222)), "SUM($1)", float64(11.2222)) assertClauseSerialize(t, SUMf(Float(11.2222)), "SUM($1)", float64(11.2222))
}) })
t.Run("integer", func(t *testing.T) { t.Run("integer", func(t *testing.T) {
assertExpressionSerialize(t, SUMi(table1ColInt), "SUM(table1.colInt)") assertClauseSerialize(t, SUMi(table1ColInt), "SUM(table1.colInt)")
assertExpressionSerialize(t, SUMi(Int(11)), "SUM($1)", int64(11)) assertClauseSerialize(t, SUMi(Int(11)), "SUM($1)", int64(11))
}) })
} }
func TestFuncCOUNT(t *testing.T) { func TestFuncCOUNT(t *testing.T) {
assertExpressionSerialize(t, COUNT(STAR), "COUNT(*)") assertClauseSerialize(t, COUNT(STAR), "COUNT(*)")
assertExpressionSerialize(t, COUNT(table1ColFloat), "COUNT(table1.colFloat)") assertClauseSerialize(t, COUNT(table1ColFloat), "COUNT(table1.colFloat)")
assertExpressionSerialize(t, COUNT(Float(11.2222)), "COUNT($1)", float64(11.2222)) assertClauseSerialize(t, COUNT(Float(11.2222)), "COUNT($1)", float64(11.2222))
} }
func TestFuncABS(t *testing.T) { func TestFuncABS(t *testing.T) {
t.Run("float", func(t *testing.T) { t.Run("float", func(t *testing.T) {
assertExpressionSerialize(t, ABSf(table1ColFloat), "ABS(table1.colFloat)") assertClauseSerialize(t, ABSf(table1ColFloat), "ABS(table1.colFloat)")
assertExpressionSerialize(t, ABSf(Float(11.2222)), "ABS($1)", float64(11.2222)) assertClauseSerialize(t, ABSf(Float(11.2222)), "ABS($1)", float64(11.2222))
}) })
t.Run("integer", func(t *testing.T) { t.Run("integer", func(t *testing.T) {
assertExpressionSerialize(t, ABSi(table1ColInt), "ABS(table1.colInt)") assertClauseSerialize(t, ABSi(table1ColInt), "ABS(table1.colInt)")
assertExpressionSerialize(t, ABSi(Int(11)), "ABS($1)", int64(11)) assertClauseSerialize(t, ABSi(Int(11)), "ABS($1)", int64(11))
}) })
} }
func TestFuncSQRT(t *testing.T) { func TestFuncSQRT(t *testing.T) {
t.Run("float", func(t *testing.T) { t.Run("float", func(t *testing.T) {
assertExpressionSerialize(t, SQRTf(table1ColFloat), "SQRT(table1.colFloat)") assertClauseSerialize(t, SQRTf(table1ColFloat), "SQRT(table1.colFloat)")
assertExpressionSerialize(t, SQRTf(Float(11.2222)), "SQRT($1)", float64(11.2222)) assertClauseSerialize(t, SQRTf(Float(11.2222)), "SQRT($1)", float64(11.2222))
}) })
t.Run("integer", func(t *testing.T) { t.Run("integer", func(t *testing.T) {
assertExpressionSerialize(t, SQRTi(table1ColInt), "SQRT(table1.colInt)") assertClauseSerialize(t, SQRTi(table1ColInt), "SQRT(table1.colInt)")
assertExpressionSerialize(t, SQRTi(Int(11)), "SQRT($1)", int64(11)) assertClauseSerialize(t, SQRTi(Int(11)), "SQRT($1)", int64(11))
}) })
} }
func TestFuncCBRT(t *testing.T) { func TestFuncCBRT(t *testing.T) {
t.Run("float", func(t *testing.T) { t.Run("float", func(t *testing.T) {
assertExpressionSerialize(t, CBRTf(table1ColFloat), "CBRT(table1.colFloat)") assertClauseSerialize(t, CBRTf(table1ColFloat), "CBRT(table1.colFloat)")
assertExpressionSerialize(t, CBRTf(Float(11.2222)), "CBRT($1)", float64(11.2222)) assertClauseSerialize(t, CBRTf(Float(11.2222)), "CBRT($1)", float64(11.2222))
}) })
t.Run("integer", func(t *testing.T) { t.Run("integer", func(t *testing.T) {
assertExpressionSerialize(t, CBRTi(table1ColInt), "CBRT(table1.colInt)") assertClauseSerialize(t, CBRTi(table1ColInt), "CBRT(table1.colInt)")
assertExpressionSerialize(t, CBRTi(Int(11)), "CBRT($1)", int64(11)) assertClauseSerialize(t, CBRTi(Int(11)), "CBRT($1)", int64(11))
}) })
} }
func TestFuncCEIL(t *testing.T) { func TestFuncCEIL(t *testing.T) {
assertExpressionSerialize(t, CEIL(table1ColFloat), "CEIL(table1.colFloat)") assertClauseSerialize(t, CEIL(table1ColFloat), "CEIL(table1.colFloat)")
assertExpressionSerialize(t, CEIL(Float(11.2222)), "CEIL($1)", float64(11.2222)) assertClauseSerialize(t, CEIL(Float(11.2222)), "CEIL($1)", float64(11.2222))
} }
func TestFuncFLOOR(t *testing.T) { func TestFuncFLOOR(t *testing.T) {
assertExpressionSerialize(t, FLOOR(table1ColFloat), "FLOOR(table1.colFloat)") assertClauseSerialize(t, FLOOR(table1ColFloat), "FLOOR(table1.colFloat)")
assertExpressionSerialize(t, FLOOR(Float(11.2222)), "FLOOR($1)", float64(11.2222)) assertClauseSerialize(t, FLOOR(Float(11.2222)), "FLOOR($1)", float64(11.2222))
} }
func TestFuncROUND(t *testing.T) { func TestFuncROUND(t *testing.T) {
assertExpressionSerialize(t, ROUND(table1ColFloat), "ROUND(table1.colFloat)") assertClauseSerialize(t, ROUND(table1ColFloat), "ROUND(table1.colFloat)")
assertExpressionSerialize(t, ROUND(Float(11.2222)), "ROUND($1)", float64(11.2222)) assertClauseSerialize(t, ROUND(Float(11.2222)), "ROUND($1)", float64(11.2222))
assertExpressionSerialize(t, ROUND(table1ColFloat, Int(2)), "ROUND(table1.colFloat, $1)", int64(2)) assertClauseSerialize(t, ROUND(table1ColFloat, Int(2)), "ROUND(table1.colFloat, $1)", int64(2))
assertExpressionSerialize(t, ROUND(Float(11.2222), Int(1)), "ROUND($1, $2)", float64(11.2222), int64(1)) assertClauseSerialize(t, ROUND(Float(11.2222), Int(1)), "ROUND($1, $2)", float64(11.2222), int64(1))
} }
func TestFuncSIGN(t *testing.T) { func TestFuncSIGN(t *testing.T) {
assertExpressionSerialize(t, SIGN(table1ColFloat), "SIGN(table1.colFloat)") assertClauseSerialize(t, SIGN(table1ColFloat), "SIGN(table1.colFloat)")
assertExpressionSerialize(t, SIGN(Float(11.2222)), "SIGN($1)", float64(11.2222)) assertClauseSerialize(t, SIGN(Float(11.2222)), "SIGN($1)", float64(11.2222))
} }
func TestFuncTRUNC(t *testing.T) { func TestFuncTRUNC(t *testing.T) {
assertExpressionSerialize(t, TRUNC(table1ColFloat), "TRUNC(table1.colFloat)") assertClauseSerialize(t, TRUNC(table1ColFloat), "TRUNC(table1.colFloat)")
assertExpressionSerialize(t, TRUNC(Float(11.2222)), "TRUNC($1)", float64(11.2222)) assertClauseSerialize(t, TRUNC(Float(11.2222)), "TRUNC($1)", float64(11.2222))
assertExpressionSerialize(t, TRUNC(table1ColFloat, Int(2)), "TRUNC(table1.colFloat, $1)", int64(2)) assertClauseSerialize(t, TRUNC(table1ColFloat, Int(2)), "TRUNC(table1.colFloat, $1)", int64(2))
assertExpressionSerialize(t, TRUNC(Float(11.2222), Int(1)), "TRUNC($1, $2)", float64(11.2222), int64(1)) assertClauseSerialize(t, TRUNC(Float(11.2222), Int(1)), "TRUNC($1, $2)", float64(11.2222), int64(1))
} }
func TestFuncLN(t *testing.T) { func TestFuncLN(t *testing.T) {
assertExpressionSerialize(t, LN(table1ColFloat), "LN(table1.colFloat)") assertClauseSerialize(t, LN(table1ColFloat), "LN(table1.colFloat)")
assertExpressionSerialize(t, LN(Float(11.2222)), "LN($1)", float64(11.2222)) assertClauseSerialize(t, LN(Float(11.2222)), "LN($1)", float64(11.2222))
} }
func TestFuncLOG(t *testing.T) { func TestFuncLOG(t *testing.T) {
assertExpressionSerialize(t, LOG(table1ColFloat), "LOG(table1.colFloat)") assertClauseSerialize(t, LOG(table1ColFloat), "LOG(table1.colFloat)")
assertExpressionSerialize(t, LOG(Float(11.2222)), "LOG($1)", float64(11.2222)) assertClauseSerialize(t, LOG(Float(11.2222)), "LOG($1)", float64(11.2222))
} }
func TestFuncCOALESCE(t *testing.T) { func TestFuncCOALESCE(t *testing.T) {
assertExpressionSerialize(t, COALESCE(table1ColFloat), "COALESCE(table1.colFloat)") assertClauseSerialize(t, COALESCE(table1ColFloat), "COALESCE(table1.colFloat)")
assertExpressionSerialize(t, COALESCE(Float(11.2222), NULL, String("str")), "COALESCE($1, NULL, $2)", float64(11.2222), "str") assertClauseSerialize(t, COALESCE(Float(11.2222), NULL, String("str")), "COALESCE($1, NULL, $2)", float64(11.2222), "str")
} }
func TestFuncNULLIF(t *testing.T) { func TestFuncNULLIF(t *testing.T) {
assertExpressionSerialize(t, NULLIF(table1ColFloat, table2ColInt), "NULLIF(table1.colFloat, table2.colInt)") assertClauseSerialize(t, NULLIF(table1ColFloat, table2ColInt), "NULLIF(table1.colFloat, table2.colInt)")
assertExpressionSerialize(t, NULLIF(Float(11.2222), NULL), "NULLIF($1, NULL)", float64(11.2222)) assertClauseSerialize(t, NULLIF(Float(11.2222), NULL), "NULLIF($1, NULL)", float64(11.2222))
} }
func TestFuncGREATEST(t *testing.T) { func TestFuncGREATEST(t *testing.T) {
assertExpressionSerialize(t, GREATEST(table1ColFloat), "GREATEST(table1.colFloat)") assertClauseSerialize(t, GREATEST(table1ColFloat), "GREATEST(table1.colFloat)")
assertExpressionSerialize(t, GREATEST(Float(11.2222), NULL, String("str")), "GREATEST($1, NULL, $2)", float64(11.2222), "str") assertClauseSerialize(t, GREATEST(Float(11.2222), NULL, String("str")), "GREATEST($1, NULL, $2)", float64(11.2222), "str")
} }
func TestFuncLEAST(t *testing.T) { func TestFuncLEAST(t *testing.T) {
assertExpressionSerialize(t, LEAST(table1ColFloat), "LEAST(table1.colFloat)") assertClauseSerialize(t, LEAST(table1ColFloat), "LEAST(table1.colFloat)")
assertExpressionSerialize(t, LEAST(Float(11.2222), NULL, String("str")), "LEAST($1, NULL, $2)", float64(11.2222), "str") assertClauseSerialize(t, LEAST(Float(11.2222), NULL, String("str")), "LEAST($1, NULL, $2)", float64(11.2222), "str")
} }
func TestInterval(t *testing.T) { func TestInterval(t *testing.T) {

View file

@ -2,7 +2,7 @@ package sqlbuilder
import ( import (
"database/sql" "database/sql"
"github.com/dropbox/godropbox/errors" "errors"
"github.com/serenize/snaker" "github.com/serenize/snaker"
"github.com/sub0zero/go-sqlbuilder/sqlbuilder/execution" "github.com/sub0zero/go-sqlbuilder/sqlbuilder/execution"
"reflect" "reflect"
@ -22,7 +22,7 @@ type InsertStatement interface {
QUERY(selectStatement SelectStatement) InsertStatement QUERY(selectStatement SelectStatement) InsertStatement
} }
func newInsertStatement(t writableTable, columns ...column) InsertStatement { func newInsertStatement(t WritableTable, columns ...Column) InsertStatement {
return &insertStatementImpl{ return &insertStatementImpl{
table: t, table: t,
columns: columns, columns: columns,
@ -30,8 +30,8 @@ func newInsertStatement(t writableTable, columns ...column) InsertStatement {
} }
type insertStatementImpl struct { type insertStatementImpl struct {
table writableTable table WritableTable
columns []column columns []Column
rows [][]clause rows [][]clause
query SelectStatement query SelectStatement
returning []projection returning []projection
@ -136,7 +136,7 @@ func (s *insertStatementImpl) Sql() (sql string, args []interface{}, err error)
queryData.writeString("INSERT INTO") queryData.writeString("INSERT INTO")
if s.table == nil { if s.table == nil {
return "", nil, errors.Newf("nil tableName.") return "", nil, errors.New("nil tableName.")
} }
err = s.table.serialize(insert_statement, queryData) err = s.table.serialize(insert_statement, queryData)

View file

@ -5,71 +5,71 @@ import (
) )
func TestIntegerExpressionEQ(t *testing.T) { func TestIntegerExpressionEQ(t *testing.T) {
assertExpressionSerialize(t, table1ColInt.EQ(table2ColInt), "(table1.colInt = table2.colInt)") assertClauseSerialize(t, table1ColInt.EQ(table2ColInt), "(table1.colInt = table2.colInt)")
assertExpressionSerialize(t, table1ColInt.EQ(Int(11)), "(table1.colInt = $1)", int64(11)) assertClauseSerialize(t, table1ColInt.EQ(Int(11)), "(table1.colInt = $1)", int64(11))
} }
func TestIntegerExpressionNOT_EQ(t *testing.T) { func TestIntegerExpressionNOT_EQ(t *testing.T) {
assertExpressionSerialize(t, table1ColInt.NOT_EQ(table2ColInt), "(table1.colInt != table2.colInt)") assertClauseSerialize(t, table1ColInt.NOT_EQ(table2ColInt), "(table1.colInt != table2.colInt)")
assertExpressionSerialize(t, table1ColInt.NOT_EQ(Int(11)), "(table1.colInt != $1)", int64(11)) assertClauseSerialize(t, table1ColInt.NOT_EQ(Int(11)), "(table1.colInt != $1)", int64(11))
} }
func TestIntegerExpressionGT(t *testing.T) { func TestIntegerExpressionGT(t *testing.T) {
assertExpressionSerialize(t, table1ColInt.GT(table2ColInt), "(table1.colInt > table2.colInt)") assertClauseSerialize(t, table1ColInt.GT(table2ColInt), "(table1.colInt > table2.colInt)")
assertExpressionSerialize(t, table1ColInt.GT(Int(11)), "(table1.colInt > $1)", int64(11)) assertClauseSerialize(t, table1ColInt.GT(Int(11)), "(table1.colInt > $1)", int64(11))
} }
func TestIntegerExpressionGT_EQ(t *testing.T) { func TestIntegerExpressionGT_EQ(t *testing.T) {
assertExpressionSerialize(t, table1ColInt.GT_EQ(table2ColInt), "(table1.colInt >= table2.colInt)") assertClauseSerialize(t, table1ColInt.GT_EQ(table2ColInt), "(table1.colInt >= table2.colInt)")
assertExpressionSerialize(t, table1ColInt.GT_EQ(Int(11)), "(table1.colInt >= $1)", int64(11)) assertClauseSerialize(t, table1ColInt.GT_EQ(Int(11)), "(table1.colInt >= $1)", int64(11))
} }
func TestIntegerExpressionLT(t *testing.T) { func TestIntegerExpressionLT(t *testing.T) {
assertExpressionSerialize(t, table1ColInt.LT(table2ColInt), "(table1.colInt < table2.colInt)") assertClauseSerialize(t, table1ColInt.LT(table2ColInt), "(table1.colInt < table2.colInt)")
assertExpressionSerialize(t, table1ColInt.LT(Int(11)), "(table1.colInt < $1)", int64(11)) assertClauseSerialize(t, table1ColInt.LT(Int(11)), "(table1.colInt < $1)", int64(11))
} }
func TestIntegerExpressionLT_EQ(t *testing.T) { func TestIntegerExpressionLT_EQ(t *testing.T) {
assertExpressionSerialize(t, table1ColInt.LT_EQ(table2ColInt), "(table1.colInt <= table2.colInt)") assertClauseSerialize(t, table1ColInt.LT_EQ(table2ColInt), "(table1.colInt <= table2.colInt)")
assertExpressionSerialize(t, table1ColInt.LT_EQ(Int(11)), "(table1.colInt <= $1)", int64(11)) assertClauseSerialize(t, table1ColInt.LT_EQ(Int(11)), "(table1.colInt <= $1)", int64(11))
} }
func TestIntegerExpressionADD(t *testing.T) { func TestIntegerExpressionADD(t *testing.T) {
assertExpressionSerialize(t, table1ColInt.ADD(table2ColInt), "(table1.colInt + table2.colInt)") assertClauseSerialize(t, table1ColInt.ADD(table2ColInt), "(table1.colInt + table2.colInt)")
assertExpressionSerialize(t, table1ColInt.ADD(Int(11)), "(table1.colInt + $1)", int64(11)) assertClauseSerialize(t, table1ColInt.ADD(Int(11)), "(table1.colInt + $1)", int64(11))
} }
func TestIntegerExpressionSUB(t *testing.T) { func TestIntegerExpressionSUB(t *testing.T) {
assertExpressionSerialize(t, table1ColInt.SUB(table2ColInt), "(table1.colInt - table2.colInt)") assertClauseSerialize(t, table1ColInt.SUB(table2ColInt), "(table1.colInt - table2.colInt)")
assertExpressionSerialize(t, table1ColInt.SUB(Int(11)), "(table1.colInt - $1)", int64(11)) assertClauseSerialize(t, table1ColInt.SUB(Int(11)), "(table1.colInt - $1)", int64(11))
} }
func TestIntegerExpressionMUL(t *testing.T) { func TestIntegerExpressionMUL(t *testing.T) {
assertExpressionSerialize(t, table1ColInt.MUL(table2ColInt), "(table1.colInt * table2.colInt)") assertClauseSerialize(t, table1ColInt.MUL(table2ColInt), "(table1.colInt * table2.colInt)")
assertExpressionSerialize(t, table1ColInt.MUL(Int(11)), "(table1.colInt * $1)", int64(11)) assertClauseSerialize(t, table1ColInt.MUL(Int(11)), "(table1.colInt * $1)", int64(11))
} }
func TestIntegerExpressionDIV(t *testing.T) { func TestIntegerExpressionDIV(t *testing.T) {
assertExpressionSerialize(t, table1ColInt.DIV(table2ColInt), "(table1.colInt / table2.colInt)") assertClauseSerialize(t, table1ColInt.DIV(table2ColInt), "(table1.colInt / table2.colInt)")
assertExpressionSerialize(t, table1ColInt.DIV(Int(11)), "(table1.colInt / $1)", int64(11)) assertClauseSerialize(t, table1ColInt.DIV(Int(11)), "(table1.colInt / $1)", int64(11))
} }
func TestIntExpressionMOD(t *testing.T) { func TestIntExpressionMOD(t *testing.T) {
assertExpressionSerialize(t, table1ColInt.MOD(table2ColInt), "(table1.colInt % table2.colInt)") assertClauseSerialize(t, table1ColInt.MOD(table2ColInt), "(table1.colInt % table2.colInt)")
assertExpressionSerialize(t, table1ColInt.MOD(Int(11)), "(table1.colInt % $1)", int64(11)) assertClauseSerialize(t, table1ColInt.MOD(Int(11)), "(table1.colInt % $1)", int64(11))
} }
func TestIntExpressionPOW(t *testing.T) { func TestIntExpressionPOW(t *testing.T) {
assertExpressionSerialize(t, table1ColInt.POW(table2ColInt), "(table1.colInt ^ table2.colInt)") assertClauseSerialize(t, table1ColInt.POW(table2ColInt), "(table1.colInt ^ table2.colInt)")
assertExpressionSerialize(t, table1ColInt.POW(Int(11)), "(table1.colInt ^ $1)", int64(11)) assertClauseSerialize(t, table1ColInt.POW(Int(11)), "(table1.colInt ^ $1)", int64(11))
} }
func TestIntExpressionBIT_SHIFT_LEFT(t *testing.T) { func TestIntExpressionBIT_SHIFT_LEFT(t *testing.T) {
assertExpressionSerialize(t, table1ColInt.BIT_SHIFT_LEFT(table2ColInt), "(table1.colInt << table2.colInt)") assertClauseSerialize(t, table1ColInt.BIT_SHIFT_LEFT(table2ColInt), "(table1.colInt << table2.colInt)")
assertExpressionSerialize(t, table1ColInt.BIT_SHIFT_LEFT(Int(11)), "(table1.colInt << $1)", int64(11)) assertClauseSerialize(t, table1ColInt.BIT_SHIFT_LEFT(Int(11)), "(table1.colInt << $1)", int64(11))
} }
func TestIntExpressionBIT_SHIFT_RIGHT(t *testing.T) { func TestIntExpressionBIT_SHIFT_RIGHT(t *testing.T) {
assertExpressionSerialize(t, table1ColInt.BIT_SHIFT_RIGHT(table2ColInt), "(table1.colInt >> table2.colInt)") assertClauseSerialize(t, table1ColInt.BIT_SHIFT_RIGHT(table2ColInt), "(table1.colInt >> table2.colInt)")
assertExpressionSerialize(t, table1ColInt.BIT_SHIFT_RIGHT(Int(11)), "(table1.colInt >> $1)", int64(11)) assertClauseSerialize(t, table1ColInt.BIT_SHIFT_RIGHT(Int(11)), "(table1.colInt >> $1)", int64(11))
} }

View file

@ -3,5 +3,5 @@ package sqlbuilder
import "testing" import "testing"
func TestRawExpression(t *testing.T) { func TestRawExpression(t *testing.T) {
assertExpressionSerialize(t, RAW("current_database()"), "current_database()") assertClauseSerialize(t, RAW("current_database()"), "current_database()")
} }

View file

@ -27,12 +27,12 @@ type LockStatement interface {
} }
type lockStatementImpl struct { type lockStatementImpl struct {
tables []tableInterface tables []WritableTable
lockMode lockMode lockMode lockMode
nowait bool nowait bool
} }
func LOCK(tables ...tableInterface) LockStatement { func LOCK(tables ...WritableTable) LockStatement {
return &lockStatementImpl{ return &lockStatementImpl{
tables: tables, tables: tables,
} }

View file

@ -49,47 +49,6 @@ func GT_EQ(lhs, rhs Expression) BoolExpression {
return newBinaryBoolExpression(lhs, rhs, ">=") return newBinaryBoolExpression(lhs, rhs, ">=")
} }
func IS_TRUE(expr BoolExpression) BoolExpression {
return newPostifxBoolExpression(expr, "IS TRUE")
}
func IS_NOT_TRUE(expr BoolExpression) BoolExpression {
return newPostifxBoolExpression(expr, "IS NOT TRUE")
}
func IS_FALSE(expr BoolExpression) BoolExpression {
return newPostifxBoolExpression(expr, "IS FALSE")
}
func IS_NOT_FALSE(expr BoolExpression) BoolExpression {
return newPostifxBoolExpression(expr, "IS NOT FALSE")
}
func IS_UNKNOWN(expr BoolExpression) BoolExpression {
return newPostifxBoolExpression(expr, "IS UNKNOWN")
}
func IS_NOT_UNKNOWN(expr BoolExpression) BoolExpression {
return newPostifxBoolExpression(expr, "IS NOT UNKNOWN")
}
func And(lhs, rhs Expression) BoolExpression {
return newBinaryBoolExpression(lhs, rhs, "AND")
}
// Returns a representation of "c[0] OR ... OR c[n-1]" for c in clauses
func Or(lhs, rhs Expression) BoolExpression {
return newBinaryBoolExpression(lhs, rhs, "OR")
}
func Regexp(lhs, rhs Expression) BoolExpression {
return newBinaryBoolExpression(lhs, rhs, "REGEXP")
}
func RegexpL(lhs Expression, val string) BoolExpression {
return Regexp(lhs, literal(val))
}
func EXISTS(subQuery SelectStatement) BoolExpression { func EXISTS(subQuery SelectStatement) BoolExpression {
return newPrefixBoolExpression(subQuery, "EXISTS") return newPrefixBoolExpression(subQuery, "EXISTS")
} }

View file

@ -5,9 +5,9 @@ import "testing"
func TestOperatorNOT(t *testing.T) { func TestOperatorNOT(t *testing.T) {
notExpression := NOT(Int(2).EQ(Int(1))) notExpression := NOT(Int(2).EQ(Int(1)))
assertExpressionSerialize(t, notExpression, "NOT ($1 = $2)", int64(2), int64(1)) assertClauseSerialize(t, notExpression, "NOT ($1 = $2)", int64(2), int64(1))
assertProjectionSerialize(t, notExpression.AS("alias_not_expression"), `NOT ($1 = $2) AS "alias_not_expression"`, int64(2), int64(1)) assertProjectionSerialize(t, notExpression.AS("alias_not_expression"), `NOT ($1 = $2) AS "alias_not_expression"`, int64(2), int64(1))
assertExpressionSerialize(t, notExpression.AND(Int(4).EQ(Int(5))), `(NOT ($1 = $2) AND ($3 = $4))`, int64(2), int64(1), int64(4), int64(5)) assertClauseSerialize(t, notExpression.AND(Int(4).EQ(Int(5))), `(NOT ($1 = $2) AND ($3 = $4))`, int64(2), int64(1), int64(4), int64(5))
} }
func TestCase1(t *testing.T) { func TestCase1(t *testing.T) {
@ -15,7 +15,7 @@ func TestCase1(t *testing.T) {
WHEN(table3Col1.EQ(Int(1))).THEN(table3Col1.ADD(Int(1))). WHEN(table3Col1.EQ(Int(1))).THEN(table3Col1.ADD(Int(1))).
WHEN(table3Col1.EQ(Int(2))).THEN(table3Col1.ADD(Int(2))) WHEN(table3Col1.EQ(Int(2))).THEN(table3Col1.ADD(Int(2)))
assertExpressionSerialize(t, query, `(CASE WHEN table3.col1 = $1 THEN table3.col1 + $2 WHEN table3.col1 = $3 THEN table3.col1 + $4 END)`, assertClauseSerialize(t, query, `(CASE WHEN table3.col1 = $1 THEN table3.col1 + $2 WHEN table3.col1 = $3 THEN table3.col1 + $4 END)`,
int64(1), int64(1), int64(2), int64(2)) int64(1), int64(1), int64(2), int64(2))
} }
@ -25,6 +25,6 @@ func TestCase2(t *testing.T) {
WHEN(Int(2)).THEN(table3Col1.ADD(Int(2))). WHEN(Int(2)).THEN(table3Col1.ADD(Int(2))).
ELSE(Int(0)) ELSE(Int(0))
assertExpressionSerialize(t, query, `(CASE table3.col1 WHEN $1 THEN table3.col1 + $2 WHEN $3 THEN table3.col1 + $4 ELSE $5 END)`, assertClauseSerialize(t, query, `(CASE table3.col1 WHEN $1 THEN table3.col1 + $2 WHEN $3 THEN table3.col1 + $4 ELSE $5 END)`,
int64(1), int64(1), int64(2), int64(2), int64(0)) int64(1), int64(1), int64(2), int64(2), int64(0))
} }

View file

@ -1,6 +1,6 @@
package sqlbuilder package sqlbuilder
import "github.com/dropbox/godropbox/errors" import "errors"
type OrderByClause interface { type OrderByClause interface {
serializeAsOrderBy(statement statementType, out *queryData) error serializeAsOrderBy(statement statementType, out *queryData) error
@ -13,7 +13,7 @@ type orderByClauseImpl struct {
func (o *orderByClauseImpl) serializeAsOrderBy(statement statementType, out *queryData) error { func (o *orderByClauseImpl) serializeAsOrderBy(statement statementType, out *queryData) error {
if o.expression == nil { if o.expression == nil {
return errors.Newf("nil orderBy by clause.") return errors.New("nil orderBy by clause.")
} }
if err := o.expression.serializeAsOrderBy(statement, out); err != nil { if err := o.expression.serializeAsOrderBy(statement, out); err != nil {

View file

@ -6,7 +6,7 @@ type projection interface {
//------------------------------------------------------// //------------------------------------------------------//
// Dummy type for select * AllColumns // Dummy type for select * AllColumns
type ColumnList []column type ColumnList []Column
func (cl ColumnList) isProjectionType() {} func (cl ColumnList) isProjectionType() {}

View file

@ -2,7 +2,7 @@ package sqlbuilder
import ( import (
"database/sql" "database/sql"
"github.com/dropbox/godropbox/errors" "errors"
"github.com/sub0zero/go-sqlbuilder/sqlbuilder/execution" "github.com/sub0zero/go-sqlbuilder/sqlbuilder/execution"
) )
@ -30,7 +30,7 @@ func SELECT(projection ...projection) SelectStatement {
return newSelectStatement(nil, projection) return newSelectStatement(nil, projection)
} }
// NOTE: SelectStatement purposely does not implement the Table interface since // NOTE: SelectStatement purposely does not implement the tableImpl interface since
// mysql's subquery performance is horrible. // mysql's subquery performance is horrible.
type selectStatementImpl struct { type selectStatementImpl struct {
expressionInterfaceImpl expressionInterfaceImpl
@ -53,7 +53,7 @@ func defaultProjectionAliasing(projections []projection) []projection {
aliasedProjections := []projection{} aliasedProjections := []projection{}
for _, projection := range projections { for _, projection := range projections {
if column, ok := projection.(column); ok { if column, ok := projection.(Column); ok {
aliasedProjections = append(aliasedProjections, column.DefaultAlias()) aliasedProjections = append(aliasedProjections, column.DefaultAlias())
} else if columnList, ok := projection.(ColumnList); ok { } else if columnList, ok := projection.(ColumnList); ok {
aliasedProjections = append(aliasedProjections, columnList.DefaultAlias()...) aliasedProjections = append(aliasedProjections, columnList.DefaultAlias()...)
@ -87,7 +87,7 @@ func (s *selectStatementImpl) FROM(table ReadableTable) SelectStatement {
func (s *selectStatementImpl) serialize(statement statementType, out *queryData, options ...serializeOption) error { func (s *selectStatementImpl) serialize(statement statementType, out *queryData, options ...serializeOption) error {
if s == nil { if s == nil {
return errors.New("Select statement is nil. ") return errors.New("Select expression is nil. ")
} }
out.writeString("(") out.writeString("(")
@ -107,7 +107,7 @@ func (s *selectStatementImpl) serialize(statement statementType, out *queryData,
func (s *selectStatementImpl) serializeImpl(out *queryData) error { func (s *selectStatementImpl) serializeImpl(out *queryData) error {
if s == nil { if s == nil {
return errors.New("Select statement is nil. ") return errors.New("Select expression is nil. ")
} }
out.nextLine() out.nextLine()
@ -205,10 +205,7 @@ func (s *selectStatementImpl) DebugSql() (query string, err error) {
} }
func (s *selectStatementImpl) AsTable(alias string) expressionTable { func (s *selectStatementImpl) AsTable(alias string) expressionTable {
return &expressionTableImpl{ return newExpressionTable(s.parent, alias)
statement: s,
alias: alias,
}
} }
func (s *selectStatementImpl) WHERE(expression BoolExpression) SelectStatement { func (s *selectStatementImpl) WHERE(expression BoolExpression) SelectStatement {

View file

@ -2,7 +2,7 @@ package sqlbuilder
import ( import (
"database/sql" "database/sql"
"github.com/dropbox/godropbox/errors" "errors"
"github.com/sub0zero/go-sqlbuilder/sqlbuilder/execution" "github.com/sub0zero/go-sqlbuilder/sqlbuilder/execution"
) )
@ -92,15 +92,12 @@ func (us *setStatementImpl) OFFSET(offset int64) SetStatement {
} }
func (us *setStatementImpl) AsTable(alias string) expressionTable { func (us *setStatementImpl) AsTable(alias string) expressionTable {
return &expressionTableImpl{ return newExpressionTable(us.parent, alias)
statement: us,
alias: alias,
}
} }
func (s *setStatementImpl) serialize(statement statementType, out *queryData, options ...serializeOption) error { func (s *setStatementImpl) serialize(statement statementType, out *queryData, options ...serializeOption) error {
if s == nil { if s == nil {
return errors.New("Set statement is nil. ") return errors.New("Set expression is nil. ")
} }
if s.orderBy != nil || s.limit >= 0 || s.offset >= 0 { if s.orderBy != nil || s.limit >= 0 || s.offset >= 0 {
@ -125,11 +122,11 @@ func (s *setStatementImpl) serialize(statement statementType, out *queryData, op
func (s *setStatementImpl) serializeImpl(out *queryData) error { func (s *setStatementImpl) serializeImpl(out *queryData) error {
if s == nil { if s == nil {
return errors.New("Set statement is nil. ") return errors.New("Set expression is nil. ")
} }
if len(s.selects) < 2 { if len(s.selects) < 2 {
return errors.Newf("UNION Statement must have at least two SELECT statements.") return errors.New("UNION Statement must have at least two SELECT statements.")
} }
out.nextLine() out.nextLine()

View file

@ -7,7 +7,7 @@ import (
gc "gopkg.in/check.v1" gc "gopkg.in/check.v1"
"github.com/dropbox/godropbox/errors" "errors"
) )
type StmtSuite struct { type StmtSuite struct {

View file

@ -6,62 +6,62 @@ import (
func TestStringEQ(t *testing.T) { func TestStringEQ(t *testing.T) {
exp := table3StrCol.EQ(table2ColStr) exp := table3StrCol.EQ(table2ColStr)
assertExpressionSerialize(t, exp, "(table3.col2 = table2.colStr)") assertClauseSerialize(t, exp, "(table3.col2 = table2.colStr)")
exp = table3StrCol.EQ(String("JOHN")) exp = table3StrCol.EQ(String("JOHN"))
assertExpressionSerialize(t, exp, "(table3.col2 = $1)", "JOHN") assertClauseSerialize(t, exp, "(table3.col2 = $1)", "JOHN")
} }
func TestStringNOT_EQ(t *testing.T) { func TestStringNOT_EQ(t *testing.T) {
exp := table3StrCol.NOT_EQ(table2ColStr) exp := table3StrCol.NOT_EQ(table2ColStr)
assertExpressionSerialize(t, exp, "(table3.col2 != table2.colStr)") assertClauseSerialize(t, exp, "(table3.col2 != table2.colStr)")
assertExpressionSerialize(t, table3StrCol.NOT_EQ(String("JOHN")), "(table3.col2 != $1)", "JOHN") assertClauseSerialize(t, table3StrCol.NOT_EQ(String("JOHN")), "(table3.col2 != $1)", "JOHN")
} }
func TestStringGT(t *testing.T) { func TestStringGT(t *testing.T) {
exp := table3StrCol.GT(table2ColStr) exp := table3StrCol.GT(table2ColStr)
assertExpressionSerialize(t, exp, "(table3.col2 > table2.colStr)") assertClauseSerialize(t, exp, "(table3.col2 > table2.colStr)")
assertExpressionSerialize(t, table3StrCol.GT(String("JOHN")), "(table3.col2 > $1)", "JOHN") assertClauseSerialize(t, table3StrCol.GT(String("JOHN")), "(table3.col2 > $1)", "JOHN")
} }
func TestStringGT_EQ(t *testing.T) { func TestStringGT_EQ(t *testing.T) {
exp := table3StrCol.GT_EQ(table2ColStr) exp := table3StrCol.GT_EQ(table2ColStr)
assertExpressionSerialize(t, exp, "(table3.col2 >= table2.colStr)") assertClauseSerialize(t, exp, "(table3.col2 >= table2.colStr)")
assertExpressionSerialize(t, table3StrCol.GT_EQ(String("JOHN")), "(table3.col2 >= $1)", "JOHN") assertClauseSerialize(t, table3StrCol.GT_EQ(String("JOHN")), "(table3.col2 >= $1)", "JOHN")
} }
func TestStringLT(t *testing.T) { func TestStringLT(t *testing.T) {
exp := table3StrCol.LT(table2ColStr) exp := table3StrCol.LT(table2ColStr)
assertExpressionSerialize(t, exp, "(table3.col2 < table2.colStr)") assertClauseSerialize(t, exp, "(table3.col2 < table2.colStr)")
assertExpressionSerialize(t, table3StrCol.LT(String("JOHN")), "(table3.col2 < $1)", "JOHN") assertClauseSerialize(t, table3StrCol.LT(String("JOHN")), "(table3.col2 < $1)", "JOHN")
} }
func TestStringLT_EQ(t *testing.T) { func TestStringLT_EQ(t *testing.T) {
exp := table3StrCol.LT_EQ(table2ColStr) exp := table3StrCol.LT_EQ(table2ColStr)
assertExpressionSerialize(t, exp, "(table3.col2 <= table2.colStr)") assertClauseSerialize(t, exp, "(table3.col2 <= table2.colStr)")
assertExpressionSerialize(t, table3StrCol.LT_EQ(String("JOHN")), "(table3.col2 <= $1)", "JOHN") assertClauseSerialize(t, table3StrCol.LT_EQ(String("JOHN")), "(table3.col2 <= $1)", "JOHN")
} }
func TestStringCONCAT(t *testing.T) { func TestStringCONCAT(t *testing.T) {
assertExpressionSerialize(t, table3StrCol.CONCAT(table2ColStr), "(table3.col2 || table2.colStr)") assertClauseSerialize(t, table3StrCol.CONCAT(table2ColStr), "(table3.col2 || table2.colStr)")
assertExpressionSerialize(t, table3StrCol.CONCAT(String("JOHN")), "(table3.col2 || $1)", "JOHN") assertClauseSerialize(t, table3StrCol.CONCAT(String("JOHN")), "(table3.col2 || $1)", "JOHN")
} }
func TestStringLIKE(t *testing.T) { func TestStringLIKE(t *testing.T) {
assertExpressionSerialize(t, table3StrCol.LIKE(table2ColStr), "(table3.col2 LIKE table2.colStr)") assertClauseSerialize(t, table3StrCol.LIKE(table2ColStr), "(table3.col2 LIKE table2.colStr)")
assertExpressionSerialize(t, table3StrCol.LIKE(String("JOHN")), "(table3.col2 LIKE $1)", "JOHN") assertClauseSerialize(t, table3StrCol.LIKE(String("JOHN")), "(table3.col2 LIKE $1)", "JOHN")
} }
func TestStringNOT_LIKE(t *testing.T) { func TestStringNOT_LIKE(t *testing.T) {
assertExpressionSerialize(t, table3StrCol.NOT_LIKE(table2ColStr), "(table3.col2 NOT LIKE table2.colStr)") assertClauseSerialize(t, table3StrCol.NOT_LIKE(table2ColStr), "(table3.col2 NOT LIKE table2.colStr)")
assertExpressionSerialize(t, table3StrCol.NOT_LIKE(String("JOHN")), "(table3.col2 NOT LIKE $1)", "JOHN") assertClauseSerialize(t, table3StrCol.NOT_LIKE(String("JOHN")), "(table3.col2 NOT LIKE $1)", "JOHN")
} }
func TestStringSIMILAR_TO(t *testing.T) { func TestStringSIMILAR_TO(t *testing.T) {
assertExpressionSerialize(t, table3StrCol.SIMILAR_TO(table2ColStr), "(table3.col2 SIMILAR TO table2.colStr)") assertClauseSerialize(t, table3StrCol.SIMILAR_TO(table2ColStr), "(table3.col2 SIMILAR TO table2.colStr)")
assertExpressionSerialize(t, table3StrCol.SIMILAR_TO(String("JOHN")), "(table3.col2 SIMILAR TO $1)", "JOHN") assertClauseSerialize(t, table3StrCol.SIMILAR_TO(String("JOHN")), "(table3.col2 SIMILAR TO $1)", "JOHN")
} }
func TestStringNOT_SIMILAR_TO(t *testing.T) { func TestStringNOT_SIMILAR_TO(t *testing.T) {
assertExpressionSerialize(t, table3StrCol.NOT_SIMILAR_TO(table2ColStr), "(table3.col2 NOT SIMILAR TO table2.colStr)") assertClauseSerialize(t, table3StrCol.NOT_SIMILAR_TO(table2ColStr), "(table3.col2 NOT SIMILAR TO table2.colStr)")
assertExpressionSerialize(t, table3StrCol.NOT_SIMILAR_TO(String("JOHN")), "(table3.col2 NOT SIMILAR TO $1)", "JOHN") assertClauseSerialize(t, table3StrCol.NOT_SIMILAR_TO(String("JOHN")), "(table3.col2 NOT SIMILAR TO $1)", "JOHN")
} }

View file

@ -3,22 +3,10 @@
package sqlbuilder package sqlbuilder
import ( import (
"github.com/dropbox/godropbox/errors" "errors"
) )
type tableInterface interface { type readableTable interface {
clause
SchemaName() string
TableName() string
Columns() []column
}
// The sql tableName read interface. NOTE: NATURAL JOINs, and join "USING" clause
// are not supported.
type ReadableTable interface {
tableInterface
// Generates a select query on the current tableName. // Generates a select query on the current tableName.
SELECT(projections ...projection) SelectStatement SELECT(projections ...projection) SelectStatement
@ -38,20 +26,87 @@ type ReadableTable interface {
// The sql tableName write interface. // The sql tableName write interface.
type writableTable interface { type writableTable interface {
tableInterface INSERT(columns ...Column) InsertStatement
UPDATE(columns ...Column) UpdateStatement
INSERT(columns ...column) InsertStatement
UPDATE(columns ...column) UpdateStatement
DELETE() DeleteStatement DELETE() DeleteStatement
LOCK() LockStatement LOCK() LockStatement
} }
// Defines a physical tableName in the database that is both readable and writable. type ReadableTable interface {
// This function will panic if name is not valid readableTable
func NewTable(schemaName, name string, columns ...column) *Table { clause
}
t := &Table{ type WritableTable interface {
writableTable
clause
}
type Table interface {
readableTable
writableTable
clause
SchemaName() string
TableName() string
AS(alias string)
}
type readableTableInterfaceImpl struct {
parent ReadableTable
}
// Generates a select query on the current tableName.
func (r *readableTableInterfaceImpl) SELECT(projections ...projection) SelectStatement {
return newSelectStatement(r.parent, projections)
}
// Creates a inner join tableName Expression using onCondition.
func (r *readableTableInterfaceImpl) INNER_JOIN(table ReadableTable, onCondition BoolExpression) ReadableTable {
return newJoinTable(r.parent, table, innerJoin, onCondition)
}
// Creates a left join tableName Expression using onCondition.
func (r *readableTableInterfaceImpl) LEFT_JOIN(table ReadableTable, onCondition BoolExpression) ReadableTable {
return newJoinTable(r.parent, table, leftJoin, onCondition)
}
// Creates a right join tableName Expression using onCondition.
func (r *readableTableInterfaceImpl) RIGHT_JOIN(table ReadableTable, onCondition BoolExpression) ReadableTable {
return newJoinTable(r.parent, table, rightJoin, onCondition)
}
func (r *readableTableInterfaceImpl) FULL_JOIN(table ReadableTable, onCondition BoolExpression) ReadableTable {
return newJoinTable(r.parent, table, fullJoin, onCondition)
}
func (r *readableTableInterfaceImpl) CROSS_JOIN(table ReadableTable) ReadableTable {
return newJoinTable(r.parent, table, crossJoin, nil)
}
type writableTableInterfaceImpl struct {
parent WritableTable
}
func (w *writableTableInterfaceImpl) INSERT(columns ...Column) InsertStatement {
return newInsertStatement(w.parent, columns...)
}
func (w *writableTableInterfaceImpl) UPDATE(columns ...Column) UpdateStatement {
return newUpdateStatement(w.parent, columns)
}
func (w *writableTableInterfaceImpl) DELETE() DeleteStatement {
return newDeleteStatement(w.parent)
}
func (w *writableTableInterfaceImpl) LOCK() LockStatement {
return LOCK(w.parent)
}
func NewTable(schemaName, name string, columns ...Column) Table {
t := &tableImpl{
schemaName: schemaName, schemaName: schemaName,
name: name, name: name,
columns: columns, columns: columns,
@ -60,25 +115,23 @@ func NewTable(schemaName, name string, columns ...column) *Table {
c.setTableName(name) c.setTableName(name)
} }
t.readableTableInterfaceImpl.parent = t
t.writableTableInterfaceImpl.parent = t
return t return t
} }
type Table struct { type tableImpl struct {
readableTableInterfaceImpl
writableTableInterfaceImpl
schemaName string schemaName string
name string name string
alias string alias string
columns []column columns []Column
} }
func (t *Table) Column(name string) column { func (t *tableImpl) AS(alias string) {
return &baseColumn{
name: name,
nullable: NotNullable,
tableName: t.name,
}
}
func (t *Table) SetAlias(alias string) {
t.alias = alias t.alias = alias
for _, c := range t.columns { for _, c := range t.columns {
@ -87,29 +140,22 @@ func (t *Table) SetAlias(alias string) {
} }
// Returns the tableName's name in the database // Returns the tableName's name in the database
func (t *Table) SchemaName() string { func (t *tableImpl) SchemaName() string {
return t.schemaName return t.schemaName
} }
// Returns the tableName's name in the database // Returns the tableName's name in the database
func (t *Table) TableName() string { func (t *tableImpl) TableName() string {
return t.name return t.name
} }
func (t *Table) SchemaTableName() string { func (t *tableImpl) SchemaTableName() string {
return t.schemaName return t.schemaName
} }
// Returns a list of the tableName's columns func (t *tableImpl) serialize(statement statementType, out *queryData, options ...serializeOption) error {
func (t *Table) Columns() []column {
return t.columns
}
// Generates the sql string for the current tableName Expression. Note: the
// generated string may not be a valid/executable sql Statement.
func (t *Table) serialize(statement statementType, out *queryData, options ...serializeOption) error {
if t == nil { if t == nil {
return errors.Newf("Table is nil. ") return errors.New("tableImpl is nil. ")
} }
out.writeString(t.schemaName) out.writeString(t.schemaName)
@ -124,71 +170,20 @@ func (t *Table) serialize(statement statementType, out *queryData, options ...se
return nil return nil
} }
// Generates a select query on the current tableName.
func (t *Table) SELECT(projections ...projection) SelectStatement {
return newSelectStatement(t, projections)
}
// Creates a inner join tableName Expression using onCondition.
func (t *Table) INNER_JOIN(
table ReadableTable,
onCondition BoolExpression) ReadableTable {
return InnerJoinOn(t, table, onCondition)
}
// Creates a left join tableName Expression using onCondition.
func (t *Table) LEFT_JOIN(
table ReadableTable,
onCondition BoolExpression) ReadableTable {
return LeftJoinOn(t, table, onCondition)
}
// Creates a right join tableName Expression using onCondition.
func (t *Table) RIGHT_JOIN(
table ReadableTable,
onCondition BoolExpression) ReadableTable {
return RightJoinOn(t, table, onCondition)
}
func (t *Table) FULL_JOIN(table ReadableTable, onCondition BoolExpression) ReadableTable {
return FullJoin(t, table, onCondition)
}
func (t *Table) CROSS_JOIN(table ReadableTable) ReadableTable {
return CrossJoin(t, table)
}
func (t *Table) INSERT(columns ...column) InsertStatement {
return newInsertStatement(t, columns...)
}
func (t *Table) UPDATE(columns ...column) UpdateStatement {
return newUpdateStatement(t, columns)
}
func (t *Table) DELETE() DeleteStatement {
return newDeleteStatement(t)
}
func (t *Table) LOCK() LockStatement {
return LOCK(t)
}
type joinType int type joinType int
const ( const (
INNER_JOIN joinType = iota innerJoin joinType = iota
LEFT_JOIN leftJoin
RIGHT_JOIN rightJoin
FULL_JOIN fullJoin
CROSS_JOIN crossJoin
) )
// Join expressions are pseudo readable tables. // Join expressions are pseudo readable tables.
type joinTable struct { type joinTable struct {
readableTableInterfaceImpl
lhs ReadableTable lhs ReadableTable
rhs ReadableTable rhs ReadableTable
join_type joinType join_type joinType
@ -201,51 +196,16 @@ func newJoinTable(
join_type joinType, join_type joinType,
onCondition BoolExpression) ReadableTable { onCondition BoolExpression) ReadableTable {
return &joinTable{ joinTable := &joinTable{
lhs: lhs, lhs: lhs,
rhs: rhs, rhs: rhs,
join_type: join_type, join_type: join_type,
onCondition: onCondition, onCondition: onCondition,
} }
}
func InnerJoinOn( joinTable.readableTableInterfaceImpl.parent = joinTable
lhs ReadableTable,
rhs ReadableTable,
onCondition BoolExpression) ReadableTable {
return newJoinTable(lhs, rhs, INNER_JOIN, onCondition) return joinTable
}
func LeftJoinOn(
lhs ReadableTable,
rhs ReadableTable,
onCondition BoolExpression) ReadableTable {
return newJoinTable(lhs, rhs, LEFT_JOIN, onCondition)
}
func RightJoinOn(
lhs ReadableTable,
rhs ReadableTable,
onCondition BoolExpression) ReadableTable {
return newJoinTable(lhs, rhs, RIGHT_JOIN, onCondition)
}
func FullJoin(
lhs ReadableTable,
rhs ReadableTable,
onCondition BoolExpression) ReadableTable {
return newJoinTable(lhs, rhs, FULL_JOIN, onCondition)
}
func CrossJoin(
lhs ReadableTable,
rhs ReadableTable) ReadableTable {
return newJoinTable(lhs, rhs, CROSS_JOIN, nil)
} }
func (t *joinTable) SchemaName() string { func (t *joinTable) SchemaName() string {
@ -256,33 +216,13 @@ func (t *joinTable) TableName() string {
return "" return ""
} }
func (t *joinTable) Columns() []column {
columns := make([]column, 0)
columns = append(columns, t.lhs.Columns()...)
columns = append(columns, t.rhs.Columns()...)
return columns
}
func (t *joinTable) Column(name string) column {
return &baseColumn{
name: name,
nullable: NotNullable,
}
}
func (t *joinTable) serialize(statement statementType, out *queryData, options ...serializeOption) (err error) { func (t *joinTable) serialize(statement statementType, out *queryData, options ...serializeOption) (err error) {
if t == nil { if t == nil {
return errors.New("Join table is nil. ") return errors.New("Join table is nil. ")
} }
if t.lhs == nil {
return errors.Newf("nil lhs.") if isNil(t.lhs) {
} return errors.New("left hand side of join operation is nil table")
if t.rhs == nil {
return errors.Newf("nil rhs.")
}
if t.onCondition == nil && t.join_type != CROSS_JOIN {
return errors.Newf("nil onCondition.")
} }
if err = t.lhs.serialize(statement, out); err != nil { if err = t.lhs.serialize(statement, out); err != nil {
@ -292,22 +232,30 @@ func (t *joinTable) serialize(statement statementType, out *queryData, options .
out.nextLine() out.nextLine()
switch t.join_type { switch t.join_type {
case INNER_JOIN: case innerJoin:
out.writeString("JOIN") out.writeString("INNER JOIN")
case LEFT_JOIN: case leftJoin:
out.writeString("LEFT JOIN") out.writeString("LEFT JOIN")
case RIGHT_JOIN: case rightJoin:
out.writeString("RIGHT JOIN") out.writeString("RIGHT JOIN")
case FULL_JOIN: case fullJoin:
out.writeString("FULL JOIN") out.writeString("FULL JOIN")
case CROSS_JOIN: case crossJoin:
out.writeString("CROSS JOIN") out.writeString("CROSS JOIN")
} }
if isNil(t.rhs) {
return errors.New("right hand side of join operation is nil table")
}
if err = t.rhs.serialize(statement, out); err != nil { if err = t.rhs.serialize(statement, out); err != nil {
return return
} }
if t.onCondition == nil && t.join_type != crossJoin {
return errors.New("join condition is nil")
}
if t.onCondition != nil { if t.onCondition != nil {
out.writeString("ON") out.writeString("ON")
if err = t.onCondition.serialize(statement, out); err != nil { if err = t.onCondition.serialize(statement, out); err != nil {
@ -317,36 +265,3 @@ func (t *joinTable) serialize(statement statementType, out *queryData, options .
return nil return nil
} }
func (t *joinTable) SELECT(projections ...projection) SelectStatement {
return newSelectStatement(t, projections)
}
func (t *joinTable) INNER_JOIN(
table ReadableTable,
onCondition BoolExpression) ReadableTable {
return InnerJoinOn(t, table, onCondition)
}
func (t *joinTable) LEFT_JOIN(
table ReadableTable,
onCondition BoolExpression) ReadableTable {
return LeftJoinOn(t, table, onCondition)
}
func (t *joinTable) FULL_JOIN(table ReadableTable, onCondition BoolExpression) ReadableTable {
return FullJoin(t, table, onCondition)
}
func (t *joinTable) CROSS_JOIN(table ReadableTable) ReadableTable {
return CrossJoin(t, table)
}
func (t *joinTable) RIGHT_JOIN(
table ReadableTable,
onCondition BoolExpression) ReadableTable {
return RightJoinOn(t, table, onCondition)
}

View file

@ -1,188 +1,101 @@
// +build disabled
package sqlbuilder package sqlbuilder
import ( import (
"bytes" "testing"
gc "gopkg.in/check.v1"
) )
type TableSuite struct { func TestJoinNilInputs(t *testing.T) {
assertClauseSerializeErr(t, table2.INNER_JOIN(nil, table1ColBool.EQ(table2ColBool)),
"right hand side of join operation is nil table")
assertClauseSerializeErr(t, table2.INNER_JOIN(table1, nil),
"join condition is nil")
} }
var _ = gc.Suite(&TableSuite{}) func TestINNER_JOIN(t *testing.T) {
assertClauseSerialize(t, table1.
// NOTE: tables / columns are defined in statement_test.go INNER_JOIN(table2, table1ColInt.EQ(table2ColInt)),
`db.table1
func (s *TableSuite) TestBasicColumns(c *gc.C) { INNER JOIN db.table2 ON (table1.colInt = table2.colInt)`)
cols := table1.Columns() assertClauseSerialize(t, table1.
INNER_JOIN(table2, table1ColInt.EQ(table2ColInt)).
c.Assert(len(cols), gc.Equals, 4) INNER_JOIN(table3, table1ColInt.EQ(table3ColInt)),
c.Assert(cols[0], gc.Equals, table1Col1) `db.table1
c.Assert(cols[1], gc.Equals, table1ColFloat) INNER JOIN db.table2 ON (table1.colInt = table2.colInt)
c.Assert(cols[2], gc.Equals, table1Col3) INNER JOIN db.table3 ON (table1.colInt = table3.colInt)`)
c.Assert(cols[3], gc.Equals, table1ColTime) assertClauseSerialize(t, table1.
INNER_JOIN(table2, table1ColInt.EQ(Int(1))).
INNER_JOIN(table3, table1ColInt.EQ(Int(2))),
`db.table1
INNER JOIN db.table2 ON (table1.colInt = $1)
INNER JOIN db.table3 ON (table1.colInt = $2)`, int64(1), int64(2))
} }
func (s *TableSuite) TestCValidLookup(c *gc.C) { func TestLEFT_JOIN(t *testing.T) {
col := table1.C("col1") assertClauseSerialize(t, table1.
LEFT_JOIN(table2, table1ColInt.EQ(table2ColInt)),
buf := &bytes.Buffer{} `db.table1
LEFT JOIN db.table2 ON (table1.colInt = table2.colInt)`)
err := col.SerializeSql(buf) assertClauseSerialize(t, table1.
c.Assert(err, gc.IsNil) LEFT_JOIN(table2, table1ColInt.EQ(table2ColInt)).
LEFT_JOIN(table3, table1ColInt.EQ(table3ColInt)),
sql := buf.String() `db.table1
c.Assert(sql, gc.Equals, "table1.col1") LEFT JOIN db.table2 ON (table1.colInt = table2.colInt)
LEFT JOIN db.table3 ON (table1.colInt = table3.colInt)`)
assertClauseSerialize(t, table1.
LEFT_JOIN(table2, table1ColInt.EQ(Int(1))).
LEFT_JOIN(table3, table1ColInt.EQ(Int(2))),
`db.table1
LEFT JOIN db.table2 ON (table1.colInt = $1)
LEFT JOIN db.table3 ON (table1.colInt = $2)`, int64(1), int64(2))
} }
func (s *TableSuite) TestCInvalidLookup(c *gc.C) { func TestRIGHT_JOIN(t *testing.T) {
col := table1.C("foo") assertClauseSerialize(t, table1.
RIGHT_JOIN(table2, table1ColInt.EQ(table2ColInt)),
buf := &bytes.Buffer{} `db.table1
RIGHT JOIN db.table2 ON (table1.colInt = table2.colInt)`)
err := col.SerializeSql(buf) assertClauseSerialize(t, table1.
c.Assert(err, gc.NotNil) RIGHT_JOIN(table2, table1ColInt.EQ(table2ColInt)).
RIGHT_JOIN(table3, table1ColInt.EQ(table3ColInt)),
`db.table1
RIGHT JOIN db.table2 ON (table1.colInt = table2.colInt)
RIGHT JOIN db.table3 ON (table1.colInt = table3.colInt)`)
assertClauseSerialize(t, table1.
RIGHT_JOIN(table2, table1ColInt.EQ(Int(1))).
RIGHT_JOIN(table3, table1ColInt.EQ(Int(2))),
`db.table1
RIGHT JOIN db.table2 ON (table1.colInt = $1)
RIGHT JOIN db.table3 ON (table1.colInt = $2)`, int64(1), int64(2))
} }
func (s *TableSuite) TestJoinNilLeftTable(c *gc.C) { func TestFULL_JOIN(t *testing.T) {
join := InnerJoinOn(nil, table2, EqL(table2Col3, 123)) assertClauseSerialize(t, table1.
FULL_JOIN(table2, table1ColInt.EQ(table2ColInt)),
buf := &bytes.Buffer{} `db.table1
FULL JOIN db.table2 ON (table1.colInt = table2.colInt)`)
err := join.serialize("", buf) assertClauseSerialize(t, table1.
c.Assert(err, gc.NotNil) FULL_JOIN(table2, table1ColInt.EQ(table2ColInt)).
FULL_JOIN(table3, table1ColInt.EQ(table3ColInt)),
`db.table1
FULL JOIN db.table2 ON (table1.colInt = table2.colInt)
FULL JOIN db.table3 ON (table1.colInt = table3.colInt)`)
assertClauseSerialize(t, table1.
FULL_JOIN(table2, table1ColInt.EQ(Int(1))).
FULL_JOIN(table3, table1ColInt.EQ(Int(2))),
`db.table1
FULL JOIN db.table2 ON (table1.colInt = $1)
FULL JOIN db.table3 ON (table1.colInt = $2)`, int64(1), int64(2))
} }
func (s *TableSuite) TestJoinNilRightTable(c *gc.C) { func TestCROSS_JOIN(t *testing.T) {
join := InnerJoinOn(table1, nil, EqL(table2Col3, 123)) assertClauseSerialize(t, table1.
CROSS_JOIN(table2),
buf := &bytes.Buffer{} `db.table1
CROSS JOIN db.table2`)
err := join.serialize("", buf) assertClauseSerialize(t, table1.
c.Assert(err, gc.NotNil) CROSS_JOIN(table2).
} CROSS_JOIN(table3),
`db.table1
func (s *TableSuite) TestJoinNilOnCondition(c *gc.C) { CROSS JOIN db.table2
join := InnerJoinOn(table1, table2, nil) CROSS JOIN db.table3`)
buf := &bytes.Buffer{}
err := join.serialize("", buf)
c.Assert(err, gc.NotNil)
}
func (s *TableSuite) TestInnerJoin(c *gc.C) {
join := table1.InnerJoinOn(table2, EQ(table1Col3, table2Col3))
buf := &bytes.Buffer{}
err := join.SerializeSql(buf)
c.Assert(err, gc.IsNil)
sql := buf.String()
c.Assert(
sql,
gc.Equals,
"db.table1 JOIN db.table2 ON table1.col3=table2.col3")
}
func (s *TableSuite) TestLeftJoin(c *gc.C) {
join := table1.LEFT_JOIN(table2, EQ(table1Col3, table2Col3))
buf := &bytes.Buffer{}
err := join.serialize("", buf)
c.Assert(err, gc.IsNil)
sql := buf.String()
c.Assert(
sql,
gc.Equals,
"db.table1 LEFT JOIN db.table2 "+
"ON table1.col3=table2.col3")
}
func (s *TableSuite) TestRightJoin(c *gc.C) {
join := table1.RIGHT_JOIN(table2, EQ(table1Col3, table2Col3))
buf := &bytes.Buffer{}
err := join.serialize("", buf)
c.Assert(err, gc.IsNil)
sql := buf.String()
c.Assert(
sql,
gc.Equals,
"db.table1 RIGHT JOIN db.table2 "+
"ON table1.col3=table2.col3")
}
//func (s *TableSuite) TestJoinColumns(c *gc.C) {
// join := table1.RIGHT_JOIN(table2, EQ(table1Col3, table2Col3))
//
// cols := join.Columns()
// c.Assert(len(cols), gc.Equals, 6)
// c.Assert(cols[0], gc.Equals, table1Col1)
// c.Assert(cols[1], gc.Equals, table1ColFloat)
// c.Assert(cols[2], gc.Equals, table1Col3)
// c.Assert(cols[3], gc.Equals, table1ColTime)
// c.Assert(cols[4], gc.Equals, table2Col3)
// c.Assert(cols[5], gc.Equals, table2Col4)
//}
func (s *TableSuite) TestNestedInnerJoin(c *gc.C) {
join1 := table1.InnerJoinOn(table2, EQ(table1Col3, table2Col3))
join2 := join1.InnerJoinOn(table3, EQ(table1Col1, table3Col1))
buf := &bytes.Buffer{}
err := join2.SerializeSql(buf)
c.Assert(err, gc.IsNil)
sql := buf.String()
c.Assert(
sql,
gc.Equals,
"db.table1 "+
"JOIN db.table2 ON table1.col3=table2.col3 "+
"JOIN db.table3 ON table1.col1=table3.col1")
}
func (s *TableSuite) TestNestedLeftJoin(c *gc.C) {
join1 := table1.InnerJoinOn(table2, EQ(table1Col3, table2Col3))
join2 := join1.LeftJoinOn(table3, EQ(table1Col1, table3Col1))
buf := &bytes.Buffer{}
err := join2.SerializeSql(buf)
c.Assert(err, gc.IsNil)
sql := buf.String()
c.Assert(
sql,
gc.Equals,
"db.table1 "+
"JOIN db.table2 ON table1.col3=table2.col3 "+
"LEFT JOIN db.table3 ON table1.col1=table3.col1")
}
func (s *TableSuite) TestNestedRightJoin(c *gc.C) {
join1 := table1.InnerJoinOn(table2, EQ(table1Col3, table2Col3))
join2 := join1.RightJoinOn(table3, EQ(table1Col1, table3Col1))
buf := &bytes.Buffer{}
err := join2.SerializeSql(buf)
c.Assert(err, gc.IsNil)
sql := buf.String()
c.Assert(
sql,
gc.Equals,
"db.table1 "+
"JOIN db.table2 ON table1.col3=table2.col3 "+
"RIGHT JOIN db.table3 ON table1.col1=table3.col1")
} }

View file

@ -1,16 +1,17 @@
package sqlbuilder package sqlbuilder
import ( import (
"fmt"
"gotest.tools/assert" "gotest.tools/assert"
"testing" "testing"
) )
var table1Col1 = NewIntegerColumn("col1", Nullable) var table1Col1 = NewIntegerColumn("col1", true)
var table1ColInt = NewIntegerColumn("colInt", Nullable) var table1ColInt = NewIntegerColumn("colInt", true)
var table1ColFloat = NewFloatColumn("colFloat", Nullable) var table1ColFloat = NewFloatColumn("colFloat", true)
var table1Col3 = NewIntegerColumn("col3", Nullable) var table1Col3 = NewIntegerColumn("col3", true)
var table1ColTime = NewTimeColumn("colTime", Nullable) var table1ColTime = NewTimeColumn("colTime", true)
var table1ColBool = NewBoolColumn("colBool", Nullable) var table1ColBool = NewBoolColumn("colBool", true)
var table1 = NewTable( var table1 = NewTable(
"db", "db",
@ -22,13 +23,13 @@ var table1 = NewTable(
table1ColTime, table1ColTime,
table1ColBool) table1ColBool)
var table2Col3 = NewIntegerColumn("col3", Nullable) var table2Col3 = NewIntegerColumn("col3", true)
var table2Col4 = NewIntegerColumn("col4", Nullable) var table2Col4 = NewIntegerColumn("col4", true)
var table2ColInt = NewIntegerColumn("colInt", Nullable) var table2ColInt = NewIntegerColumn("colInt", true)
var table2ColFloat = NewFloatColumn("colFloat", Nullable) var table2ColFloat = NewFloatColumn("colFloat", true)
var table2ColStr = NewStringColumn("colStr", Nullable) var table2ColStr = NewStringColumn("colStr", true)
var table2ColBool = NewBoolColumn("colBool", Nullable) var table2ColBool = NewBoolColumn("colBool", true)
var table2ColTime = NewTimeColumn("colTime", Nullable) var table2ColTime = NewTimeColumn("colTime", true)
var table2 = NewTable( var table2 = NewTable(
"db", "db",
@ -41,17 +42,19 @@ var table2 = NewTable(
table2ColBool, table2ColBool,
table2ColTime) table2ColTime)
var table3Col1 = NewIntegerColumn("col1", Nullable) var table3Col1 = NewIntegerColumn("col1", true)
var table3StrCol = NewStringColumn("col2", Nullable) var table3ColInt = NewIntegerColumn("colInt", true)
var table3StrCol = NewStringColumn("col2", true)
var table3 = NewTable( var table3 = NewTable(
"db", "db",
"table3", "table3",
table3Col1, table3Col1,
table3ColInt,
table3StrCol) table3StrCol)
func assertExpressionSerialize(t *testing.T, expression Expression, query string, args ...interface{}) { func assertClauseSerialize(t *testing.T, clause clause, query string, args ...interface{}) {
out := queryData{} out := queryData{}
err := expression.serialize(select_statement, &out) err := clause.serialize(select_statement, &out)
assert.NilError(t, err) assert.NilError(t, err)
@ -59,6 +62,15 @@ func assertExpressionSerialize(t *testing.T, expression Expression, query string
assert.DeepEqual(t, out.args, args) assert.DeepEqual(t, out.args, args)
} }
func assertClauseSerializeErr(t *testing.T, clause clause, errString string) {
out := queryData{}
err := clause.serialize(select_statement, &out)
fmt.Println(err)
assert.Assert(t, err != nil)
assert.Equal(t, err.Error(), errString)
}
func assertProjectionSerialize(t *testing.T, projection projection, query string, args ...interface{}) { func assertProjectionSerialize(t *testing.T, projection projection, query string, args ...interface{}) {
out := queryData{} out := queryData{}
err := projection.serializeForProjection(select_statement, &out) err := projection.serializeForProjection(select_statement, &out)

View file

@ -5,31 +5,31 @@ import (
) )
func TestTimeExpressionEQ(t *testing.T) { func TestTimeExpressionEQ(t *testing.T) {
assertExpressionSerialize(t, table1ColTime.EQ(table2ColTime), "(table1.colTime = table2.colTime)") assertClauseSerialize(t, table1ColTime.EQ(table2ColTime), "(table1.colTime = table2.colTime)")
assertExpressionSerialize(t, table1ColTime.EQ(Time(10, 20, 0, 0)), "(table1.colTime = $1::time without time zone)", "10:20:00.000") assertClauseSerialize(t, table1ColTime.EQ(Time(10, 20, 0, 0)), "(table1.colTime = $1::time without time zone)", "10:20:00.000")
} }
func TestTimeExpressionNOT_EQ(t *testing.T) { func TestTimeExpressionNOT_EQ(t *testing.T) {
assertExpressionSerialize(t, table1ColTime.NOT_EQ(table2ColTime), "(table1.colTime != table2.colTime)") assertClauseSerialize(t, table1ColTime.NOT_EQ(table2ColTime), "(table1.colTime != table2.colTime)")
assertExpressionSerialize(t, table1ColTime.NOT_EQ(Time(10, 20, 0, 0)), "(table1.colTime != $1::time without time zone)", "10:20:00.000") assertClauseSerialize(t, table1ColTime.NOT_EQ(Time(10, 20, 0, 0)), "(table1.colTime != $1::time without time zone)", "10:20:00.000")
} }
func TestTimeExpressionLT(t *testing.T) { func TestTimeExpressionLT(t *testing.T) {
assertExpressionSerialize(t, table1ColTime.LT(table2ColTime), "(table1.colTime < table2.colTime)") assertClauseSerialize(t, table1ColTime.LT(table2ColTime), "(table1.colTime < table2.colTime)")
assertExpressionSerialize(t, table1ColTime.LT(Time(10, 20, 0, 0)), "(table1.colTime < $1::time without time zone)", "10:20:00.000") assertClauseSerialize(t, table1ColTime.LT(Time(10, 20, 0, 0)), "(table1.colTime < $1::time without time zone)", "10:20:00.000")
} }
func TestTimeExpressionLT_EQ(t *testing.T) { func TestTimeExpressionLT_EQ(t *testing.T) {
assertExpressionSerialize(t, table1ColTime.LT_EQ(table2ColTime), "(table1.colTime <= table2.colTime)") assertClauseSerialize(t, table1ColTime.LT_EQ(table2ColTime), "(table1.colTime <= table2.colTime)")
assertExpressionSerialize(t, table1ColTime.LT_EQ(Time(10, 20, 0, 0)), "(table1.colTime <= $1::time without time zone)", "10:20:00.000") assertClauseSerialize(t, table1ColTime.LT_EQ(Time(10, 20, 0, 0)), "(table1.colTime <= $1::time without time zone)", "10:20:00.000")
} }
func TestTimeExpressionGT(t *testing.T) { func TestTimeExpressionGT(t *testing.T) {
assertExpressionSerialize(t, table1ColTime.GT(table2ColTime), "(table1.colTime > table2.colTime)") assertClauseSerialize(t, table1ColTime.GT(table2ColTime), "(table1.colTime > table2.colTime)")
assertExpressionSerialize(t, table1ColTime.GT(Time(10, 20, 0, 0)), "(table1.colTime > $1::time without time zone)", "10:20:00.000") assertClauseSerialize(t, table1ColTime.GT(Time(10, 20, 0, 0)), "(table1.colTime > $1::time without time zone)", "10:20:00.000")
} }
func TestTimeExpressionGT_EQ(t *testing.T) { func TestTimeExpressionGT_EQ(t *testing.T) {
assertExpressionSerialize(t, table1ColTime.GT_EQ(table2ColTime), "(table1.colTime >= table2.colTime)") assertClauseSerialize(t, table1ColTime.GT_EQ(table2ColTime), "(table1.colTime >= table2.colTime)")
assertExpressionSerialize(t, table1ColTime.GT_EQ(Time(10, 20, 0, 0)), "(table1.colTime >= $1::time without time zone)", "10:20:00.000") assertClauseSerialize(t, table1ColTime.GT_EQ(Time(10, 20, 0, 0)), "(table1.colTime >= $1::time without time zone)", "10:20:00.000")
} }

View file

@ -2,7 +2,7 @@ package sqlbuilder
import ( import (
"database/sql" "database/sql"
"github.com/dropbox/godropbox/errors" "errors"
"github.com/sub0zero/go-sqlbuilder/sqlbuilder/execution" "github.com/sub0zero/go-sqlbuilder/sqlbuilder/execution"
) )
@ -14,7 +14,7 @@ type UpdateStatement interface {
RETURNING(projections ...projection) UpdateStatement RETURNING(projections ...projection) UpdateStatement
} }
func newUpdateStatement(table writableTable, columns []column) UpdateStatement { func newUpdateStatement(table WritableTable, columns []Column) UpdateStatement {
return &updateStatementImpl{ return &updateStatementImpl{
table: table, table: table,
columns: columns, columns: columns,
@ -22,8 +22,8 @@ func newUpdateStatement(table writableTable, columns []column) UpdateStatement {
} }
type updateStatementImpl struct { type updateStatementImpl struct {
table writableTable table WritableTable
columns []column columns []Column
updateValues []clause updateValues []clause
where BoolExpression where BoolExpression
returning []projection returning []projection

View file

@ -4,6 +4,7 @@ import (
"database/sql" "database/sql"
"errors" "errors"
"github.com/sub0zero/go-sqlbuilder/sqlbuilder/execution" "github.com/sub0zero/go-sqlbuilder/sqlbuilder/execution"
"reflect"
) )
func serializeOrderByClauseList(statement statementType, orderByClauses []OrderByClause, out *queryData) error { func serializeOrderByClauseList(statement statementType, orderByClauses []OrderByClause, out *queryData) error {
@ -97,7 +98,7 @@ func serializeProjectionList(statement statementType, projections []projection,
return nil return nil
} }
func serializeColumnList(statement statementType, columns []column, out *queryData) error { func serializeColumnList(statement statementType, columns []Column, out *queryData) error {
for i, col := range columns { for i, col := range columns {
if i > 0 { if i > 0 {
out.writeByte(',') out.writeByte(',')
@ -113,6 +114,10 @@ func serializeColumnList(statement statementType, columns []column, out *queryDa
return nil return nil
} }
func isNil(v interface{}) bool {
return v == nil || (reflect.ValueOf(v).Kind() == reflect.Ptr && reflect.ValueOf(v).IsNil())
}
//func stringExpressionListToExpressionList(stringExpressions []StringExpression) []Expression{ //func stringExpressionListToExpressionList(stringExpressions []StringExpression) []Expression{
// var ret []Expression // var ret []Expression
// //

View file

@ -63,7 +63,7 @@ SELECT payment.payment_id AS "payment.payment_id",
customer.last_update AS "customer.last_update", customer.last_update AS "customer.last_update",
customer.active AS "customer.active" customer.active AS "customer.active"
FROM dvds.payment FROM dvds.payment
JOIN dvds.customer ON (payment.customer_id = customer.customer_id) INNER JOIN dvds.customer ON (payment.customer_id = customer.customer_id)
ORDER BY payment.payment_id ASC ORDER BY payment.payment_id ASC
LIMIT 30; LIMIT 30;
` `
@ -197,11 +197,11 @@ SELECT film_actor.actor_id AS "film_actor.actor_id",
rental.staff_id AS "rental.staff_id", rental.staff_id AS "rental.staff_id",
rental.last_update AS "rental.last_update" rental.last_update AS "rental.last_update"
FROM dvds.film_actor FROM dvds.film_actor
JOIN dvds.actor ON (film_actor.actor_id = actor.actor_id) INNER JOIN dvds.actor ON (film_actor.actor_id = actor.actor_id)
JOIN dvds.film ON (film_actor.film_id = film.film_id) INNER JOIN dvds.film ON (film_actor.film_id = film.film_id)
JOIN dvds.language ON (film.language_id = language.language_id) INNER JOIN dvds.language ON (film.language_id = language.language_id)
JOIN dvds.inventory ON (inventory.film_id = film.film_id) INNER JOIN dvds.inventory ON (inventory.film_id = film.film_id)
JOIN dvds.rental ON (rental.inventory_id = inventory.inventory_id) INNER JOIN dvds.rental ON (rental.inventory_id = inventory.inventory_id)
ORDER BY film.film_id ASC ORDER BY film.film_id ASC
LIMIT 50; LIMIT 50;
` `
@ -272,7 +272,7 @@ SELECT language.language_id AS "language.language_id",
film.special_features AS "film.special_features", film.special_features AS "film.special_features",
film.fulltext AS "film.fulltext" film.fulltext AS "film.fulltext"
FROM dvds.film FROM dvds.film
JOIN dvds.language ON (film.language_id = language.language_id) INNER JOIN dvds.language ON (film.language_id = language.language_id)
WHERE film.rating = 'NC-17' WHERE film.rating = 'NC-17'
LIMIT 15; LIMIT 15;
` `
@ -569,7 +569,7 @@ SELECT f1.film_id AS "f1.film_id",
f2.special_features AS "f2.special_features", f2.special_features AS "f2.special_features",
f2.fulltext AS "f2.fulltext" f2.fulltext AS "f2.fulltext"
FROM dvds.film AS f1 FROM dvds.film AS f1
JOIN dvds.film AS f2 ON ((f1.film_id < f2.film_id) AND (f1.length = f2.length)) INNER JOIN dvds.film AS f2 ON ((f1.film_id < f2.film_id) AND (f1.length = f2.length))
ORDER BY f1.film_id ASC; ORDER BY f1.film_id ASC;
` `
f1 := Film.AS("f1") f1 := Film.AS("f1")
@ -606,7 +606,7 @@ SELECT f1.title AS "thesame_length_films.title1",
f2.title AS "thesame_length_films.title2", f2.title AS "thesame_length_films.title2",
f1.length AS "thesame_length_films.length" f1.length AS "thesame_length_films.length"
FROM dvds.film AS f1 FROM dvds.film AS f1
JOIN dvds.film AS f2 ON ((f1.film_id != f2.film_id) AND (f1.length = f2.length)) INNER JOIN dvds.film AS f2 ON ((f1.film_id != f2.film_id) AND (f1.length = f2.length))
ORDER BY f1.length ASC, f1.title ASC, f2.title ASC ORDER BY f1.length ASC, f1.title ASC, f2.title ASC
LIMIT 1000; LIMIT 1000;
` `
@ -682,8 +682,8 @@ LIMIT 1000;
// manager := Staff.AS("manager") // manager := Staff.AS("manager")
// //
// query := Staff. // query := Staff.
// INNER_JOIN(Address, Staff.AddressID.EQ(Address.AddressID)). // innerJoin(Address, Staff.AddressID.EQ(Address.AddressID)).
// INNER_JOIN(manager, Staff.StaffID.EQ(manager.StaffID)). // innerJoin(manager, Staff.StaffID.EQ(manager.StaffID)).
// SELECT(Staff.StaffID, Staff.FirstName, Staff.LastName, Address.AllColumns, manager.StaffID, manager.FirstName). // SELECT(Staff.StaffID, Staff.FirstName, Staff.LastName, Address.AllColumns, manager.StaffID, manager.FirstName).
// DISTINCT() // DISTINCT()
// //
@ -717,7 +717,7 @@ func TestSubQuery(t *testing.T) {
//avrgCustomer := NumExp(Customer.SELECT(Customer.LastName).LIMIT(1)) //avrgCustomer := NumExp(Customer.SELECT(Customer.LastName).LIMIT(1))
// //
//Customer. //Customer.
// INNER_JOIN(selectStmtTable, Customer.LastName.EQ(selectStmtTable.RefStringColumn(Actor.FirstName))). // innerJoin(selectStmtTable, Customer.LastName.EQ(selectStmtTable.RefStringColumn(Actor.FirstName))).
// SELECT(Customer.AllColumns, selectStmtTable.RefIntColumnName("first_name")). // SELECT(Customer.AllColumns, selectStmtTable.RefIntColumnName("first_name")).
// WHERE(Actor.LastName.Neq(avrgCustomer)) // WHERE(Actor.LastName.Neq(avrgCustomer))
@ -732,8 +732,8 @@ SELECT actor.actor_id AS "actor.actor_id",
films."film.title" AS "film.title", films."film.title" AS "film.title",
films."film.rating" AS "film.rating" films."film.rating" AS "film.rating"
FROM dvds.actor FROM dvds.actor
JOIN dvds.film_actor ON (actor.actor_id = film_actor.film_id) INNER JOIN dvds.film_actor ON (actor.actor_id = film_actor.film_id)
JOIN ( INNER JOIN (
SELECT film.film_id AS "film.film_id", SELECT film.film_id AS "film.film_id",
film.title AS "film.title", film.title AS "film.title",
film.rating AS "film.rating" film.rating AS "film.rating"
@ -918,7 +918,7 @@ SELECT customer.customer_id AS "customer.customer_id",
customer.active AS "customer.active", customer.active AS "customer.active",
customer_payment_sum.amount_sum AS "customer_with_amounts.amount_sum" customer_payment_sum.amount_sum AS "customer_with_amounts.amount_sum"
FROM dvds.customer FROM dvds.customer
JOIN ( INNER JOIN (
SELECT payment.customer_id AS "payment.customer_id", SELECT payment.customer_id AS "payment.customer_id",
SUM(payment.amount) AS "amount_sum" SUM(payment.amount) AS "amount_sum"
FROM dvds.payment FROM dvds.payment