Column types refactoring.
This commit is contained in:
parent
38007810c1
commit
033ab1d0da
19 changed files with 746 additions and 396 deletions
|
|
@ -20,9 +20,9 @@ func NewAlias(expression Expression, alias string) *Alias {
|
|||
}
|
||||
}
|
||||
|
||||
func (a *Alias) SerializeSql(out *bytes.Buffer) error {
|
||||
func (a *Alias) SerializeSql(out *bytes.Buffer, options ...serializeOption) error {
|
||||
|
||||
err := a.expression.SerializeSql(out)
|
||||
err := a.expression.SerializeSql(out, ALIASED)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -11,6 +11,11 @@ import (
|
|||
type BoolExpression interface {
|
||||
Expression
|
||||
|
||||
Eq(expression BoolExpression) BoolExpression
|
||||
NotEq(expression BoolExpression) BoolExpression
|
||||
GtEq(rhs Expression) BoolExpression
|
||||
LtEq(rhs Expression) BoolExpression
|
||||
|
||||
And(expression BoolExpression) BoolExpression
|
||||
Or(expression BoolExpression) BoolExpression
|
||||
IsTrue() BoolExpression
|
||||
|
|
@ -21,6 +26,22 @@ type boolInterfaceImpl struct {
|
|||
parent BoolExpression
|
||||
}
|
||||
|
||||
func (b *boolInterfaceImpl) Eq(expression BoolExpression) BoolExpression {
|
||||
return Eq(b.parent, expression)
|
||||
}
|
||||
|
||||
func (b *boolInterfaceImpl) NotEq(expression BoolExpression) BoolExpression {
|
||||
return Neq(b.parent, expression)
|
||||
}
|
||||
|
||||
func (b *boolInterfaceImpl) GtEq(rhs Expression) BoolExpression {
|
||||
return Gte(b.parent, rhs)
|
||||
}
|
||||
|
||||
func (b *boolInterfaceImpl) LtEq(rhs Expression) BoolExpression {
|
||||
return Lte(b.parent, rhs)
|
||||
}
|
||||
|
||||
func (b *boolInterfaceImpl) And(expression BoolExpression) BoolExpression {
|
||||
return And(b.parent, expression)
|
||||
}
|
||||
|
|
@ -42,7 +63,7 @@ type boolLiteralExpression struct {
|
|||
literalExpression
|
||||
}
|
||||
|
||||
func NewBoolLiteralExpression(value bool) BoolExpression {
|
||||
func newBoolLiteralExpression(value bool) BoolExpression {
|
||||
boolLiteralExpression := boolLiteralExpression{}
|
||||
|
||||
sqlValue, err := sqltypes.BuildValue(value)
|
||||
|
|
@ -57,15 +78,17 @@ func NewBoolLiteralExpression(value bool) BoolExpression {
|
|||
|
||||
//---------------------------------------------------//
|
||||
type binaryBoolExpression struct {
|
||||
expressionInterfaceImpl
|
||||
boolInterfaceImpl
|
||||
|
||||
binaryExpression
|
||||
}
|
||||
|
||||
func NewBinaryBoolExpression(lhs, rhs Expression, operator []byte) BoolExpression {
|
||||
func newBinaryBoolExpression(lhs, rhs Expression, operator []byte) BoolExpression {
|
||||
boolExpression := binaryBoolExpression{}
|
||||
|
||||
boolExpression.binaryExpression = *NewBinaryExpression(lhs, rhs, operator, &boolExpression)
|
||||
boolExpression.binaryExpression = newBinaryExpression(lhs, rhs, operator)
|
||||
boolExpression.expressionInterfaceImpl.parent = &boolExpression
|
||||
boolExpression.boolInterfaceImpl.parent = &boolExpression
|
||||
|
||||
return &boolExpression
|
||||
|
|
@ -73,15 +96,17 @@ func NewBinaryBoolExpression(lhs, rhs Expression, operator []byte) BoolExpressio
|
|||
|
||||
//---------------------------------------------------//
|
||||
type prefixBoolExpression struct {
|
||||
expressionInterfaceImpl
|
||||
boolInterfaceImpl
|
||||
|
||||
prefixExpression
|
||||
}
|
||||
|
||||
func NewPrefixBoolExpression(expression Expression, operator []byte) BoolExpression {
|
||||
func newPrefixBoolExpression(expression Expression, operator []byte) BoolExpression {
|
||||
boolExpression := prefixBoolExpression{}
|
||||
boolExpression.prefixExpression = *NewPrefixExpression(expression, operator, &boolExpression)
|
||||
boolExpression.prefixExpression = newPrefixExpression(expression, operator)
|
||||
|
||||
boolExpression.expressionInterfaceImpl.parent = &boolExpression
|
||||
boolExpression.boolInterfaceImpl.parent = &boolExpression
|
||||
|
||||
return &boolExpression
|
||||
|
|
@ -89,6 +114,7 @@ func NewPrefixBoolExpression(expression Expression, operator []byte) BoolExpress
|
|||
|
||||
//---------------------------------------------------//
|
||||
type conjunctBoolExpression struct {
|
||||
expressionInterfaceImpl
|
||||
boolInterfaceImpl
|
||||
|
||||
conjunctExpression
|
||||
|
|
@ -103,8 +129,8 @@ func NewConjunctBoolExpression(operator []byte, expressions ...BoolExpression) B
|
|||
},
|
||||
}
|
||||
|
||||
//boolExpression.expressionInterfaceImpl.parent = &boolExpression
|
||||
//boolExpression.boolInterfaceImpl.parent = &boolExpression
|
||||
boolExpression.expressionInterfaceImpl.parent = &boolExpression
|
||||
boolExpression.boolInterfaceImpl.parent = &boolExpression
|
||||
|
||||
return &boolExpression
|
||||
}
|
||||
|
|
@ -120,7 +146,7 @@ type inExpression struct {
|
|||
err error
|
||||
}
|
||||
|
||||
func (c *inExpression) SerializeSql(out *bytes.Buffer) error {
|
||||
func (c *inExpression) SerializeSql(out *bytes.Buffer, options ...serializeOption) error {
|
||||
if c.err != nil {
|
||||
return errors.Wrap(c.err, "Invalid IN expression")
|
||||
}
|
||||
|
|
@ -159,9 +185,9 @@ func (c *inExpression) SerializeSql(out *bytes.Buffer) error {
|
|||
func Eq(lhs, rhs Expression) BoolExpression {
|
||||
lit, ok := rhs.(*literalExpression)
|
||||
if ok && sqltypes.Value(lit.value).IsNull() {
|
||||
return NewBinaryBoolExpression(lhs, rhs, []byte(" IS "))
|
||||
return newBinaryBoolExpression(lhs, rhs, []byte(" IS "))
|
||||
}
|
||||
return NewBinaryBoolExpression(lhs, rhs, []byte(" = "))
|
||||
return newBinaryBoolExpression(lhs, rhs, []byte(" = "))
|
||||
}
|
||||
|
||||
// Returns a representation of "a=b", where b is a literal
|
||||
|
|
@ -173,9 +199,9 @@ func EqL(lhs Expression, val interface{}) BoolExpression {
|
|||
func Neq(lhs, rhs Expression) BoolExpression {
|
||||
lit, ok := rhs.(*literalExpression)
|
||||
if ok && sqltypes.Value(lit.value).IsNull() {
|
||||
return NewBinaryBoolExpression(lhs, rhs, []byte(" IS NOT "))
|
||||
return newBinaryBoolExpression(lhs, rhs, []byte(" IS NOT "))
|
||||
}
|
||||
return NewBinaryBoolExpression(lhs, rhs, []byte("!="))
|
||||
return newBinaryBoolExpression(lhs, rhs, []byte("!="))
|
||||
}
|
||||
|
||||
// Returns a representation of "a!=b", where b is a literal
|
||||
|
|
@ -185,7 +211,7 @@ func NeqL(lhs Expression, val interface{}) BoolExpression {
|
|||
|
||||
// Returns a representation of "a<b"
|
||||
func Lt(lhs Expression, rhs Expression) BoolExpression {
|
||||
return NewBinaryBoolExpression(lhs, rhs, []byte("<"))
|
||||
return newBinaryBoolExpression(lhs, rhs, []byte("<"))
|
||||
}
|
||||
|
||||
// Returns a representation of "a<b", where b is a literal
|
||||
|
|
@ -195,7 +221,7 @@ func LtL(lhs Expression, val interface{}) BoolExpression {
|
|||
|
||||
// Returns a representation of "a<=b"
|
||||
func Lte(lhs, rhs Expression) BoolExpression {
|
||||
return NewBinaryBoolExpression(lhs, rhs, []byte("<="))
|
||||
return newBinaryBoolExpression(lhs, rhs, []byte("<="))
|
||||
}
|
||||
|
||||
// Returns a representation of "a<=b", where b is a literal
|
||||
|
|
@ -205,7 +231,7 @@ func LteL(lhs Expression, val interface{}) BoolExpression {
|
|||
|
||||
// Returns a representation of "a>b"
|
||||
func Gt(lhs, rhs Expression) BoolExpression {
|
||||
return NewBinaryBoolExpression(lhs, rhs, []byte(">"))
|
||||
return newBinaryBoolExpression(lhs, rhs, []byte(">"))
|
||||
}
|
||||
|
||||
// Returns a representation of "a>b", where b is a literal
|
||||
|
|
@ -215,7 +241,7 @@ func GtL(lhs Expression, val interface{}) BoolExpression {
|
|||
|
||||
// Returns a representation of "a>=b"
|
||||
func Gte(lhs, rhs Expression) BoolExpression {
|
||||
return NewBinaryBoolExpression(lhs, rhs, []byte(">="))
|
||||
return newBinaryBoolExpression(lhs, rhs, []byte(">="))
|
||||
}
|
||||
|
||||
// Returns a representation of "a>=b", where b is a literal
|
||||
|
|
@ -225,11 +251,11 @@ func GteL(lhs Expression, val interface{}) BoolExpression {
|
|||
|
||||
// Returns a representation of "not expr"
|
||||
func Not(expr BoolExpression) BoolExpression {
|
||||
return NewPrefixBoolExpression(expr, []byte(" NOT "))
|
||||
return newPrefixBoolExpression(expr, []byte(" NOT "))
|
||||
}
|
||||
|
||||
func IsTrue(expr BoolExpression) BoolExpression {
|
||||
return NewPrefixBoolExpression(expr, []byte(" IS TRUE "))
|
||||
return newPrefixBoolExpression(expr, []byte(" IS TRUE "))
|
||||
}
|
||||
|
||||
// Returns a representation of "c[0] AND ... AND c[n-1]" for c in clauses
|
||||
|
|
@ -243,7 +269,7 @@ func Or(expressions ...BoolExpression) BoolExpression {
|
|||
}
|
||||
|
||||
func Like(lhs, rhs Expression) BoolExpression {
|
||||
return NewBinaryBoolExpression(lhs, rhs, []byte(" LIKE "))
|
||||
return newBinaryBoolExpression(lhs, rhs, []byte(" LIKE "))
|
||||
}
|
||||
|
||||
func LikeL(lhs Expression, val string) BoolExpression {
|
||||
|
|
@ -251,7 +277,7 @@ func LikeL(lhs Expression, val string) BoolExpression {
|
|||
}
|
||||
|
||||
func Regexp(lhs, rhs Expression) BoolExpression {
|
||||
return NewBinaryBoolExpression(lhs, rhs, []byte(" REGEXP "))
|
||||
return newBinaryBoolExpression(lhs, rhs, []byte(" REGEXP "))
|
||||
}
|
||||
|
||||
func RegexpL(lhs Expression, val string) BoolExpression {
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ func TestUnaryIsTrueExpression(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestBoolLiteral(t *testing.T) {
|
||||
literal := NewBoolLiteralExpression(true)
|
||||
literal := newBoolLiteralExpression(true)
|
||||
|
||||
out := bytes.Buffer{}
|
||||
err := literal.SerializeSql(&out)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,22 @@ package sqlbuilder
|
|||
|
||||
import "bytes"
|
||||
|
||||
type serializeOption int
|
||||
|
||||
const (
|
||||
ALIASED = iota
|
||||
FOR_PROJECTION
|
||||
)
|
||||
|
||||
type Clause interface {
|
||||
SerializeSql(out *bytes.Buffer) error
|
||||
SerializeSql(out *bytes.Buffer, options ...serializeOption) error
|
||||
}
|
||||
|
||||
func contains(s []serializeOption, e serializeOption) bool {
|
||||
for _, a := range s {
|
||||
if a == e {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ import (
|
|||
"bytes"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/dropbox/godropbox/errors"
|
||||
)
|
||||
|
||||
// XXX: Maybe add UIntColumn
|
||||
|
|
@ -15,31 +13,29 @@ import (
|
|||
// Representation of a tableName for query generation
|
||||
type Column interface {
|
||||
Expression
|
||||
isProjectionInterface
|
||||
|
||||
Name() string
|
||||
|
||||
TableName() string
|
||||
// Serialization for use in column lists
|
||||
SerializeSqlForColumnList(out *bytes.Buffer) error
|
||||
|
||||
// Internal function for tracking tableName that a column belongs to
|
||||
// for the purpose of serialization
|
||||
setTableName(table string) error
|
||||
|
||||
Eq(rhs Expression) BoolExpression
|
||||
Neq(rhs Expression) BoolExpression
|
||||
|
||||
Gte(rhs Expression) BoolExpression
|
||||
GteLiteral(rhs interface{}) BoolExpression
|
||||
|
||||
Lte(rhs Expression) BoolExpression
|
||||
LteLiteral(rhs interface{}) BoolExpression
|
||||
|
||||
Asc() OrderByClause
|
||||
Desc() OrderByClause
|
||||
}
|
||||
|
||||
type columnInterfaceImpl struct {
|
||||
parent Column
|
||||
}
|
||||
|
||||
func (c *columnInterfaceImpl) Asc() OrderByClause {
|
||||
return &orderByClause{expression: c.parent, ascent: true}
|
||||
}
|
||||
|
||||
func (c *columnInterfaceImpl) Desc() OrderByClause {
|
||||
return &orderByClause{expression: c.parent, ascent: false}
|
||||
}
|
||||
|
||||
type NullableColumn bool
|
||||
|
||||
const (
|
||||
|
|
@ -47,10 +43,10 @@ const (
|
|||
NotNullable NullableColumn = false
|
||||
)
|
||||
|
||||
// A column that can be refer to outside of the projection list
|
||||
type NonAliasColumn interface {
|
||||
Column
|
||||
}
|
||||
//// A column that can be refer to outside of the projection list
|
||||
//type NonAliasColumn interface {
|
||||
// Column
|
||||
//}
|
||||
|
||||
type Collation string
|
||||
|
||||
|
|
@ -70,19 +66,25 @@ const (
|
|||
// The base type for real materialized columns.
|
||||
type baseColumn struct {
|
||||
expressionInterfaceImpl
|
||||
isProjection
|
||||
columnInterfaceImpl
|
||||
|
||||
name string
|
||||
nullable NullableColumn
|
||||
tableName string
|
||||
alias string
|
||||
}
|
||||
|
||||
//func (c *baseColumn) As(alias string) Projection {
|
||||
// newBaseColumn := *c
|
||||
// newBaseColumn.alias = alias
|
||||
//
|
||||
// return &newBaseColumn
|
||||
//}
|
||||
func newBaseColumn(name string, nullable NullableColumn, tableName string, parent Column) baseColumn {
|
||||
bc := baseColumn{
|
||||
name: name,
|
||||
nullable: nullable,
|
||||
tableName: tableName,
|
||||
}
|
||||
|
||||
bc.expressionInterfaceImpl.parent = parent
|
||||
bc.columnInterfaceImpl.parent = parent
|
||||
|
||||
return bc
|
||||
}
|
||||
|
||||
func (c *baseColumn) Name() string {
|
||||
return c.name
|
||||
|
|
@ -97,20 +99,7 @@ func (c *baseColumn) setTableName(table string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *baseColumn) SerializeSqlForColumnList(out *bytes.Buffer) error {
|
||||
|
||||
c.SerializeSql(out)
|
||||
|
||||
if c.alias != "" {
|
||||
_, _ = out.WriteString(" AS \"" + c.alias + "\"")
|
||||
} else if c.tableName != "" {
|
||||
_, _ = out.WriteString(" AS \"" + c.tableName + "." + c.name + "\"")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c baseColumn) SerializeSql(out *bytes.Buffer) error {
|
||||
func (c baseColumn) SerializeSql(out *bytes.Buffer, options ...serializeOption) error {
|
||||
if c.tableName != "" {
|
||||
_, _ = out.WriteString(c.tableName)
|
||||
_, _ = out.WriteString(".")
|
||||
|
|
@ -125,190 +114,163 @@ func (c baseColumn) SerializeSql(out *bytes.Buffer) error {
|
|||
out.WriteString("\"")
|
||||
}
|
||||
|
||||
if contains(options, FOR_PROJECTION) && !contains(options, ALIASED) && c.tableName != "" {
|
||||
_, _ = out.WriteString(" AS \"" + c.tableName + "." + c.name + "\"")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *baseColumn) Eq(rhs Expression) BoolExpression {
|
||||
return Eq(c, rhs)
|
||||
}
|
||||
//
|
||||
//type bytesColumn struct {
|
||||
// baseColumn
|
||||
//}
|
||||
//
|
||||
//// Representation of VARBINARY/BLOB columns
|
||||
//// This function will panic if name is not valid
|
||||
//func BytesColumn(name string, nullable NullableColumn) Column {
|
||||
// if !validIdentifierName(name) {
|
||||
// panic("Invalid column name in bytes column")
|
||||
// }
|
||||
// bc := &bytesColumn{}
|
||||
// bc.name = name
|
||||
// bc.nullable = nullable
|
||||
// return bc
|
||||
//}
|
||||
//
|
||||
//type stringColumn struct {
|
||||
// baseColumn
|
||||
// charset Charset
|
||||
// collation Collation
|
||||
//}
|
||||
//
|
||||
//// Representation of VARCHAR/TEXT columns
|
||||
//// This function will panic if name is not valid
|
||||
//func StrColumn(
|
||||
// name string,
|
||||
// charset Charset,
|
||||
// collation Collation,
|
||||
// nullable NullableColumn) Column {
|
||||
//
|
||||
// if !validIdentifierName(name) {
|
||||
// panic("Invalid column name in str column")
|
||||
// }
|
||||
// sc := &stringColumn{charset: charset, collation: collation}
|
||||
// sc.name = name
|
||||
// sc.nullable = nullable
|
||||
// return sc
|
||||
//}
|
||||
//
|
||||
//type dateTimeColumn struct {
|
||||
// baseColumn
|
||||
//}
|
||||
//
|
||||
//// Representation of DateTime columns
|
||||
//// This function will panic if name is not valid
|
||||
//func DateTimeColumn(name string, nullable NullableColumn) Column {
|
||||
// if !validIdentifierName(name) {
|
||||
// panic("Invalid column name in datetime column")
|
||||
// }
|
||||
// dc := &dateTimeColumn{}
|
||||
// dc.name = name
|
||||
// dc.nullable = nullable
|
||||
// return dc
|
||||
//}
|
||||
|
||||
func (c *baseColumn) Neq(rhs Expression) BoolExpression {
|
||||
return Neq(c, rhs)
|
||||
}
|
||||
//type IntegerColumn struct {
|
||||
// baseColumn
|
||||
//}
|
||||
//
|
||||
//// Representation of any integer column
|
||||
//// This function will panic if name is not valid
|
||||
//func IntColumn(name string, nullable NullableColumn) *IntegerColumn {
|
||||
// if !validIdentifierName(name) {
|
||||
// panic("Invalid column name in int column")
|
||||
// }
|
||||
// ic := &IntegerColumn{}
|
||||
// ic.name = name
|
||||
// ic.nullable = nullable
|
||||
// return ic
|
||||
//}
|
||||
|
||||
func (c *baseColumn) Gte(rhs Expression) BoolExpression {
|
||||
return Gte(c, rhs)
|
||||
}
|
||||
|
||||
func (c *baseColumn) GteLiteral(rhs interface{}) BoolExpression {
|
||||
return Gte(c, Literal(rhs))
|
||||
}
|
||||
|
||||
func (c *baseColumn) Lte(rhs Expression) BoolExpression {
|
||||
return Lte(c, rhs)
|
||||
}
|
||||
|
||||
func (c *baseColumn) LteLiteral(literal interface{}) BoolExpression {
|
||||
return Lte(c, Literal(literal))
|
||||
}
|
||||
|
||||
func (c *baseColumn) Asc() OrderByClause {
|
||||
return Asc(c)
|
||||
}
|
||||
|
||||
func (c *baseColumn) Desc() OrderByClause {
|
||||
return Desc(c)
|
||||
}
|
||||
|
||||
type bytesColumn struct {
|
||||
baseColumn
|
||||
}
|
||||
|
||||
// Representation of VARBINARY/BLOB columns
|
||||
// This function will panic if name is not valid
|
||||
func BytesColumn(name string, nullable NullableColumn) NonAliasColumn {
|
||||
if !validIdentifierName(name) {
|
||||
panic("Invalid column name in bytes column")
|
||||
}
|
||||
bc := &bytesColumn{}
|
||||
bc.name = name
|
||||
bc.nullable = nullable
|
||||
return bc
|
||||
}
|
||||
|
||||
type stringColumn struct {
|
||||
baseColumn
|
||||
charset Charset
|
||||
collation Collation
|
||||
}
|
||||
|
||||
// Representation of VARCHAR/TEXT columns
|
||||
// This function will panic if name is not valid
|
||||
func StrColumn(
|
||||
name string,
|
||||
charset Charset,
|
||||
collation Collation,
|
||||
nullable NullableColumn) NonAliasColumn {
|
||||
|
||||
if !validIdentifierName(name) {
|
||||
panic("Invalid column name in str column")
|
||||
}
|
||||
sc := &stringColumn{charset: charset, collation: collation}
|
||||
sc.name = name
|
||||
sc.nullable = nullable
|
||||
return sc
|
||||
}
|
||||
|
||||
type dateTimeColumn struct {
|
||||
baseColumn
|
||||
}
|
||||
|
||||
// Representation of DateTime columns
|
||||
// This function will panic if name is not valid
|
||||
func DateTimeColumn(name string, nullable NullableColumn) NonAliasColumn {
|
||||
if !validIdentifierName(name) {
|
||||
panic("Invalid column name in datetime column")
|
||||
}
|
||||
dc := &dateTimeColumn{}
|
||||
dc.name = name
|
||||
dc.nullable = nullable
|
||||
return dc
|
||||
}
|
||||
|
||||
type IntegerColumn struct {
|
||||
baseColumn
|
||||
}
|
||||
|
||||
// Representation of any integer column
|
||||
// This function will panic if name is not valid
|
||||
func IntColumn(name string, nullable NullableColumn) *IntegerColumn {
|
||||
if !validIdentifierName(name) {
|
||||
panic("Invalid column name in int column")
|
||||
}
|
||||
ic := &IntegerColumn{}
|
||||
ic.name = name
|
||||
ic.nullable = nullable
|
||||
return ic
|
||||
}
|
||||
|
||||
type doubleColumn struct {
|
||||
baseColumn
|
||||
}
|
||||
|
||||
// Representation of any double column
|
||||
// This function will panic if name is not valid
|
||||
func DoubleColumn(name string, nullable NullableColumn) NonAliasColumn {
|
||||
if !validIdentifierName(name) {
|
||||
panic("Invalid column name in int column")
|
||||
}
|
||||
ic := &doubleColumn{}
|
||||
ic.name = name
|
||||
ic.nullable = nullable
|
||||
return ic
|
||||
}
|
||||
|
||||
type booleanColumn struct {
|
||||
baseColumn
|
||||
|
||||
// XXX: Maybe allow isBoolExpression (for now, not included because
|
||||
// the deferred lookup equivalent can never be isBoolExpression)
|
||||
}
|
||||
//type doubleColumn struct {
|
||||
// baseColumn
|
||||
//}
|
||||
//
|
||||
//// Representation of any double column
|
||||
//// This function will panic if name is not valid
|
||||
//func DoubleColumn(name string, nullable NullableColumn) Column {
|
||||
// if !validIdentifierName(name) {
|
||||
// panic("Invalid column name in int column")
|
||||
// }
|
||||
// ic := &doubleColumn{}
|
||||
// ic.name = name
|
||||
// ic.nullable = nullable
|
||||
// return ic
|
||||
//}
|
||||
//
|
||||
//type booleanColumn struct {
|
||||
// baseColumn
|
||||
//
|
||||
// // XXX: Maybe allow isBoolExpression (for now, not included because
|
||||
// // the deferred lookup equivalent can never be isBoolExpression)
|
||||
//}
|
||||
|
||||
// Representation of TINYINT used as a bool
|
||||
// This function will panic if name is not valid
|
||||
func BoolColumn(name string, nullable NullableColumn) NonAliasColumn {
|
||||
if !validIdentifierName(name) {
|
||||
panic("Invalid column name in bool column")
|
||||
}
|
||||
bc := &booleanColumn{}
|
||||
bc.name = name
|
||||
bc.nullable = nullable
|
||||
return bc
|
||||
}
|
||||
//func NewBoolColumn(name string, nullable NullableColumn) Column {
|
||||
// if !validIdentifierName(name) {
|
||||
// panic("Invalid column name in bool column")
|
||||
// }
|
||||
// bc := &booleanColumn{}
|
||||
// bc.name = name
|
||||
// bc.nullable = nullable
|
||||
// return bc
|
||||
//}
|
||||
//
|
||||
//type aliasColumn struct {
|
||||
// baseColumn
|
||||
// expression Expression
|
||||
//}
|
||||
//
|
||||
//func (c *aliasColumn) SerializeSql(out *bytes.Buffer) error {
|
||||
// _ = out.WriteByte('`')
|
||||
// _, _ = out.WriteString(c.name)
|
||||
// _ = out.WriteByte('`')
|
||||
// return nil
|
||||
//}
|
||||
//
|
||||
//func (c *aliasColumn) SerializeSqlForColumnList(out *bytes.Buffer) error {
|
||||
// if !validIdentifierName(c.name) {
|
||||
// return errors.Newf(
|
||||
// "Invalid alias name `%s`. Generated sql: %s",
|
||||
// c.name,
|
||||
// out.String())
|
||||
// }
|
||||
// if c.expression == nil {
|
||||
// return errors.Newf(
|
||||
// "Cannot alias a nil expression. Generated sql: %s",
|
||||
// out.String())
|
||||
// }
|
||||
//
|
||||
// _ = out.WriteByte('(')
|
||||
// if c.expression == nil {
|
||||
// return errors.Newf("nil alias clause. Generate sql: %s", out.String())
|
||||
// }
|
||||
// if err := c.expression.SerializeSql(out); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// _, _ = out.WriteString(") AS \"")
|
||||
// _, _ = out.WriteString(c.name)
|
||||
// _ = out.WriteByte('"')
|
||||
// return nil
|
||||
//}
|
||||
|
||||
type aliasColumn struct {
|
||||
baseColumn
|
||||
expression Expression
|
||||
}
|
||||
|
||||
func (c *aliasColumn) SerializeSql(out *bytes.Buffer) error {
|
||||
_ = out.WriteByte('`')
|
||||
_, _ = out.WriteString(c.name)
|
||||
_ = out.WriteByte('`')
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *aliasColumn) SerializeSqlForColumnList(out *bytes.Buffer) error {
|
||||
if !validIdentifierName(c.name) {
|
||||
return errors.Newf(
|
||||
"Invalid alias name `%s`. Generated sql: %s",
|
||||
c.name,
|
||||
out.String())
|
||||
}
|
||||
if c.expression == nil {
|
||||
return errors.Newf(
|
||||
"Cannot alias a nil expression. Generated sql: %s",
|
||||
out.String())
|
||||
}
|
||||
|
||||
_ = out.WriteByte('(')
|
||||
if c.expression == nil {
|
||||
return errors.Newf("nil alias clause. Generate sql: %s", out.String())
|
||||
}
|
||||
if err := c.expression.SerializeSql(out); err != nil {
|
||||
return err
|
||||
}
|
||||
_, _ = out.WriteString(") AS \"")
|
||||
_, _ = out.WriteString(c.name)
|
||||
_ = out.WriteByte('"')
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *aliasColumn) setTableName(table string) error {
|
||||
return errors.Newf(
|
||||
"Alias column '%s' should never have setTableName called on it",
|
||||
c.name)
|
||||
}
|
||||
//func (c *aliasColumn) setTableName(table string) error {
|
||||
// return errors.Newf(
|
||||
// "Alias column '%s' should never have setTableName called on it",
|
||||
// c.name)
|
||||
//}
|
||||
|
||||
// Representation of aliased clauses (expression AS name)
|
||||
//func Alias(name string, c Expression) Column {
|
||||
|
|
|
|||
65
sqlbuilder/column_types.go
Normal file
65
sqlbuilder/column_types.go
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
package sqlbuilder
|
||||
|
||||
//------------------------------------------------------//
|
||||
type BoolColumn struct {
|
||||
boolInterfaceImpl
|
||||
|
||||
baseColumn
|
||||
}
|
||||
|
||||
func NewBoolColumn(name string, nullable NullableColumn) *BoolColumn {
|
||||
if !validIdentifierName(name) {
|
||||
panic("Invalid column name in bool column")
|
||||
}
|
||||
boolColumn := &BoolColumn{}
|
||||
boolColumn.baseColumn = newBaseColumn(name, nullable, "", boolColumn)
|
||||
|
||||
boolColumn.boolInterfaceImpl.parent = boolColumn
|
||||
|
||||
return boolColumn
|
||||
}
|
||||
|
||||
//------------------------------------------------------//
|
||||
type NumericColumn struct {
|
||||
numericInterfaceImpl
|
||||
baseColumn
|
||||
}
|
||||
|
||||
func NewNumericColumn(name string, nullable NullableColumn) *NumericColumn {
|
||||
if !validIdentifierName(name) {
|
||||
panic("Invalid column name")
|
||||
}
|
||||
|
||||
numericColumn := &NumericColumn{}
|
||||
|
||||
numericColumn.numericInterfaceImpl.parent = numericColumn
|
||||
|
||||
numericColumn.baseColumn = newBaseColumn(name, nullable, "", numericColumn)
|
||||
|
||||
return numericColumn
|
||||
}
|
||||
|
||||
//------------------------------------------------------//
|
||||
type IntegerColumn struct {
|
||||
numericInterfaceImpl
|
||||
integerInterfaceImpl
|
||||
|
||||
baseColumn
|
||||
}
|
||||
|
||||
// Representation of any integer column
|
||||
// This function will panic if name is not valid
|
||||
func NewIntegerColumn(name string, nullable NullableColumn) *IntegerColumn {
|
||||
if !validIdentifierName(name) {
|
||||
panic("Invalid column name")
|
||||
}
|
||||
|
||||
integerColumn := &IntegerColumn{}
|
||||
|
||||
integerColumn.numericInterfaceImpl.parent = integerColumn
|
||||
integerColumn.integerInterfaceImpl.parent = integerColumn
|
||||
|
||||
integerColumn.baseColumn = newBaseColumn(name, nullable, "", integerColumn)
|
||||
|
||||
return integerColumn
|
||||
}
|
||||
97
sqlbuilder/column_types_test.go
Normal file
97
sqlbuilder/column_types_test.go
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
package sqlbuilder
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"gotest.tools/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewBoolColumn(t *testing.T) {
|
||||
boolColumn := NewBoolColumn("col", Nullable)
|
||||
|
||||
out := bytes.Buffer{}
|
||||
err := boolColumn.SerializeSql(&out)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, out.String(), "col")
|
||||
|
||||
out.Reset()
|
||||
err = boolColumn.SerializeSql(&out, FOR_PROJECTION)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, out.String(), "col")
|
||||
|
||||
out.Reset()
|
||||
err = boolColumn.setTableName("table1")
|
||||
assert.NilError(t, err)
|
||||
err = boolColumn.SerializeSql(&out, FOR_PROJECTION)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, out.String(), `table1.col AS "table1.col"`)
|
||||
|
||||
out.Reset()
|
||||
err = boolColumn.setTableName("table1")
|
||||
assert.NilError(t, err)
|
||||
aliasedBoolColumn := boolColumn.As("alias1")
|
||||
err = aliasedBoolColumn.SerializeSql(&out, FOR_PROJECTION)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, out.String(), `table1.col AS "alias1"`)
|
||||
}
|
||||
|
||||
func TestNewIntColumn(t *testing.T) {
|
||||
integerColumn := NewIntegerColumn("col", Nullable)
|
||||
|
||||
out := bytes.Buffer{}
|
||||
err := integerColumn.SerializeSql(&out)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, out.String(), "col")
|
||||
|
||||
out.Reset()
|
||||
err = integerColumn.SerializeSql(&out, FOR_PROJECTION)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, out.String(), "col")
|
||||
|
||||
out.Reset()
|
||||
err = integerColumn.setTableName("table1")
|
||||
assert.NilError(t, err)
|
||||
err = integerColumn.SerializeSql(&out, FOR_PROJECTION)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, out.String(), `table1.col AS "table1.col"`)
|
||||
|
||||
out.Reset()
|
||||
err = integerColumn.setTableName("table1")
|
||||
assert.NilError(t, err)
|
||||
aliasedBoolColumn := integerColumn.As("alias1")
|
||||
err = aliasedBoolColumn.SerializeSql(&out, FOR_PROJECTION)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, out.String(), `table1.col AS "alias1"`)
|
||||
}
|
||||
|
||||
func TestNewNumericColumnColumn(t *testing.T) {
|
||||
numericColumn := NewNumericColumn("col", Nullable)
|
||||
|
||||
out := bytes.Buffer{}
|
||||
err := numericColumn.SerializeSql(&out)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, out.String(), "col")
|
||||
|
||||
out.Reset()
|
||||
err = numericColumn.SerializeSql(&out, FOR_PROJECTION)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, out.String(), "col")
|
||||
|
||||
out.Reset()
|
||||
err = numericColumn.setTableName("table1")
|
||||
assert.NilError(t, err)
|
||||
err = numericColumn.SerializeSql(&out, FOR_PROJECTION)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, out.String(), `table1.col AS "table1.col"`)
|
||||
|
||||
out.Reset()
|
||||
err = numericColumn.setTableName("table1")
|
||||
assert.NilError(t, err)
|
||||
aliasedBoolColumn := numericColumn.As("alias1")
|
||||
err = aliasedBoolColumn.SerializeSql(&out, FOR_PROJECTION)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, out.String(), `table1.col AS "alias1"`)
|
||||
}
|
||||
|
|
@ -12,7 +12,7 @@ type Expression interface {
|
|||
|
||||
As(alias string) Clause
|
||||
IsDistinct(expression Expression) BoolExpression
|
||||
IsNull(expression Expression) BoolExpression
|
||||
IsNull() BoolExpression
|
||||
}
|
||||
|
||||
type expressionInterfaceImpl struct {
|
||||
|
|
@ -27,31 +27,27 @@ func (e *expressionInterfaceImpl) IsDistinct(expression Expression) BoolExpressi
|
|||
return nil
|
||||
}
|
||||
|
||||
func (e *expressionInterfaceImpl) IsNull(expression Expression) BoolExpression {
|
||||
func (e *expressionInterfaceImpl) IsNull() BoolExpression {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Representation of binary operations (e.g. comparisons, arithmetic)
|
||||
type binaryExpression struct {
|
||||
expressionInterfaceImpl
|
||||
lhs, rhs Expression
|
||||
operator []byte
|
||||
}
|
||||
|
||||
func NewBinaryExpression(lhs, rhs Expression, operator []byte, parent ...Expression) *binaryExpression {
|
||||
func newBinaryExpression(lhs, rhs Expression, operator []byte, parent ...Expression) binaryExpression {
|
||||
binaryExpression := binaryExpression{
|
||||
lhs: lhs,
|
||||
rhs: rhs,
|
||||
operator: operator,
|
||||
}
|
||||
if len(parent) > 0 {
|
||||
binaryExpression.parent = parent[0]
|
||||
}
|
||||
|
||||
return &binaryExpression
|
||||
return binaryExpression
|
||||
}
|
||||
|
||||
func (c *binaryExpression) SerializeSql(out *bytes.Buffer) (err error) {
|
||||
func (c *binaryExpression) SerializeSql(out *bytes.Buffer, options ...serializeOption) (err error) {
|
||||
if c.lhs == nil {
|
||||
return errors.Newf("nil lhs. Generated sql: %s", out.String())
|
||||
}
|
||||
|
|
@ -73,25 +69,20 @@ func (c *binaryExpression) SerializeSql(out *bytes.Buffer) (err error) {
|
|||
|
||||
// A not expression which negates a expression value
|
||||
type prefixExpression struct {
|
||||
expressionInterfaceImpl
|
||||
|
||||
expression Expression
|
||||
operator []byte
|
||||
}
|
||||
|
||||
func NewPrefixExpression(expression Expression, operator []byte, parent ...Expression) *prefixExpression {
|
||||
func newPrefixExpression(expression Expression, operator []byte) prefixExpression {
|
||||
prefixExpression := prefixExpression{
|
||||
expression: expression,
|
||||
operator: operator,
|
||||
}
|
||||
if len(parent) > 0 {
|
||||
prefixExpression.parent = parent[0]
|
||||
}
|
||||
|
||||
return &prefixExpression
|
||||
return prefixExpression
|
||||
}
|
||||
|
||||
func (p *prefixExpression) SerializeSql(out *bytes.Buffer) (err error) {
|
||||
func (p *prefixExpression) SerializeSql(out *bytes.Buffer, options ...serializeOption) (err error) {
|
||||
_, _ = out.Write(p.operator)
|
||||
|
||||
if p.expression == nil {
|
||||
|
|
@ -106,12 +97,11 @@ func (p *prefixExpression) SerializeSql(out *bytes.Buffer) (err error) {
|
|||
|
||||
// Representation of n-ary conjunctions (AND/OR)
|
||||
type conjunctExpression struct {
|
||||
expressionInterfaceImpl
|
||||
expressions []BoolExpression
|
||||
conjunction []byte
|
||||
}
|
||||
|
||||
func (conj *conjunctExpression) SerializeSql(out *bytes.Buffer) (err error) {
|
||||
func (conj *conjunctExpression) SerializeSql(out *bytes.Buffer, options ...serializeOption) (err error) {
|
||||
if len(conj.expressions) == 0 {
|
||||
return errors.Newf(
|
||||
"Empty conjunction. Generated sql: %s",
|
||||
|
|
@ -154,7 +144,38 @@ func NewLiteralExpression(value sqltypes.Value) *literalExpression {
|
|||
return &exp
|
||||
}
|
||||
|
||||
func (c literalExpression) SerializeSql(out *bytes.Buffer) error {
|
||||
func (c literalExpression) SerializeSql(out *bytes.Buffer, options ...serializeOption) error {
|
||||
sqltypes.Value(c.value).EncodeSql(out)
|
||||
return nil
|
||||
}
|
||||
|
||||
//------------------------------------------------------//
|
||||
// Dummy type for select *
|
||||
type ColumnList []Column
|
||||
|
||||
func (cl ColumnList) SerializeSql(out *bytes.Buffer, options ...serializeOption) error {
|
||||
for i, column := range cl {
|
||||
err := column.SerializeSql(out)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if i != len(cl)-1 {
|
||||
out.WriteString(", ")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e ColumnList) As(alias string) Clause {
|
||||
panic("Invalid usage")
|
||||
}
|
||||
|
||||
func (e ColumnList) IsDistinct(expression Expression) BoolExpression {
|
||||
panic("Invalid usage")
|
||||
}
|
||||
|
||||
func (e ColumnList) IsNull(expression Expression) BoolExpression {
|
||||
panic("Invalid usage")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ type orderByClause struct {
|
|||
ascent bool
|
||||
}
|
||||
|
||||
func (o *orderByClause) SerializeSql(out *bytes.Buffer) error {
|
||||
func (o *orderByClause) SerializeSql(out *bytes.Buffer, options ...serializeOption) error {
|
||||
if o.expression == nil {
|
||||
return errors.Newf(
|
||||
"nil order by clause. Generated sql: %s",
|
||||
|
|
@ -82,7 +82,7 @@ type arithmeticExpression struct {
|
|||
operator []byte
|
||||
}
|
||||
|
||||
func (arith *arithmeticExpression) SerializeSql(out *bytes.Buffer) (err error) {
|
||||
func (arith *arithmeticExpression) SerializeSql(out *bytes.Buffer, options ...serializeOption) (err error) {
|
||||
if len(arith.expressions) == 0 {
|
||||
return errors.Newf(
|
||||
"Empty arithmetic expression. Generated sql: %s",
|
||||
|
|
@ -115,7 +115,7 @@ type tupleExpression struct {
|
|||
elements listClause
|
||||
}
|
||||
|
||||
func (tuple *tupleExpression) SerializeSql(out *bytes.Buffer) error {
|
||||
func (tuple *tupleExpression) SerializeSql(out *bytes.Buffer, options ...serializeOption) error {
|
||||
if len(tuple.elements.clauses) < 1 {
|
||||
return errors.Newf("Tuples must include at least one element")
|
||||
}
|
||||
|
|
@ -141,7 +141,7 @@ type listClause struct {
|
|||
includeParentheses bool
|
||||
}
|
||||
|
||||
func (list *listClause) SerializeSql(out *bytes.Buffer) error {
|
||||
func (list *listClause) SerializeSql(out *bytes.Buffer, options ...serializeOption) error {
|
||||
if list.includeParentheses {
|
||||
_ = out.WriteByte('(')
|
||||
}
|
||||
|
|
@ -162,7 +162,7 @@ type funcExpression struct {
|
|||
args *listClause
|
||||
}
|
||||
|
||||
func (c *funcExpression) SerializeSql(out *bytes.Buffer) (err error) {
|
||||
func (c *funcExpression) SerializeSql(out *bytes.Buffer, options ...serializeOption) (err error) {
|
||||
if !validIdentifierName(c.funcName) {
|
||||
return errors.Newf(
|
||||
"Invalid function name: %s. Generated sql: %s",
|
||||
|
|
@ -205,7 +205,7 @@ type intervalExpression struct {
|
|||
|
||||
var intervalSep = ":"
|
||||
|
||||
func (c *intervalExpression) SerializeSql(out *bytes.Buffer) (err error) {
|
||||
func (c *intervalExpression) SerializeSql(out *bytes.Buffer, options ...serializeOption) (err error) {
|
||||
hours := c.duration / time.Hour
|
||||
minutes := (c.duration % time.Hour) / time.Minute
|
||||
sec := (c.duration % time.Minute) / time.Second
|
||||
|
|
@ -336,7 +336,7 @@ type ifExpression struct {
|
|||
falseExpression Expression
|
||||
}
|
||||
|
||||
func (exp *ifExpression) SerializeSql(out *bytes.Buffer) error {
|
||||
func (exp *ifExpression) SerializeSql(out *bytes.Buffer, options ...serializeOption) error {
|
||||
_, _ = out.WriteString("IF(")
|
||||
_ = exp.conditional.SerializeSql(out)
|
||||
_, _ = out.WriteString(",")
|
||||
|
|
|
|||
|
|
@ -3,15 +3,13 @@ package sqlbuilder
|
|||
import "bytes"
|
||||
|
||||
type FuncExpression struct {
|
||||
isProjection
|
||||
|
||||
name string
|
||||
expression Expression
|
||||
|
||||
alias string
|
||||
}
|
||||
|
||||
func (f *FuncExpression) As(alias string) Projection {
|
||||
func (f *FuncExpression) As(alias string) Clause {
|
||||
newFuncExpression := *f
|
||||
|
||||
newFuncExpression.alias = alias
|
||||
|
|
@ -19,7 +17,7 @@ func (f *FuncExpression) As(alias string) Projection {
|
|||
return &newFuncExpression
|
||||
}
|
||||
|
||||
func (f *FuncExpression) SerializeSql(out *bytes.Buffer) error {
|
||||
func (f *FuncExpression) SerializeSql(out *bytes.Buffer, options ...serializeOption) error {
|
||||
out.WriteString(f.name)
|
||||
out.WriteString("(")
|
||||
err := f.expression.SerializeSql(out)
|
||||
|
|
@ -37,9 +35,9 @@ func (f *FuncExpression) SerializeSql(out *bytes.Buffer) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (f *FuncExpression) SerializeSqlForColumnList(out *bytes.Buffer) error {
|
||||
return f.SerializeSql(out)
|
||||
}
|
||||
//func (f *FuncExpression) SerializeSqlForColumnList(out *bytes.Buffer) error {
|
||||
// return f.SerializeSql(out)
|
||||
//}
|
||||
|
||||
func MAX(expression Expression) *FuncExpression {
|
||||
return &FuncExpression{
|
||||
|
|
|
|||
82
sqlbuilder/integer_expression.go
Normal file
82
sqlbuilder/integer_expression.go
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
package sqlbuilder
|
||||
|
||||
type IntegerExpression interface {
|
||||
NumericExpression
|
||||
|
||||
//AddInt(value int) IntegerExpression
|
||||
//AddInt64(value int) IntegerExpression
|
||||
|
||||
BitAnd(expression IntegerExpression) IntegerExpression
|
||||
BitOr(expression IntegerExpression) IntegerExpression
|
||||
BitXor(expression IntegerExpression) IntegerExpression
|
||||
BitNot() IntegerExpression
|
||||
}
|
||||
|
||||
type integerInterfaceImpl struct {
|
||||
parent IntegerExpression
|
||||
}
|
||||
|
||||
//func (i *integerInterfaceImpl) AddInt(expression IntegerExpression) IntegerExpression {
|
||||
// return NewBinaryIntegerExpression(i.parent, expression, " & ")
|
||||
//}
|
||||
//
|
||||
//func (i *integerInterfaceImpl) AddInt64(expression IntegerExpression) IntegerExpression {
|
||||
// return NewBinaryIntegerExpression(i.parent, expression, " & ")
|
||||
//}
|
||||
|
||||
func (i *integerInterfaceImpl) BitAnd(expression IntegerExpression) IntegerExpression {
|
||||
return NewBinaryIntegerExpression(i.parent, expression, " & ")
|
||||
}
|
||||
|
||||
func (i *integerInterfaceImpl) BitOr(expression IntegerExpression) IntegerExpression {
|
||||
return NewBinaryIntegerExpression(i.parent, expression, " | ")
|
||||
}
|
||||
|
||||
func (i *integerInterfaceImpl) BitXor(expression IntegerExpression) IntegerExpression {
|
||||
return NewBinaryIntegerExpression(i.parent, expression, " # ")
|
||||
}
|
||||
|
||||
func (i *integerInterfaceImpl) BitNot() IntegerExpression {
|
||||
return NewPrefixIntegerExpression(i.parent, " ~")
|
||||
}
|
||||
|
||||
//---------------------------------------------------//
|
||||
type binaryIntegerExpression struct {
|
||||
expressionInterfaceImpl
|
||||
numericInterfaceImpl
|
||||
integerInterfaceImpl
|
||||
|
||||
binaryExpression
|
||||
}
|
||||
|
||||
func NewBinaryIntegerExpression(lhs, rhs IntegerExpression, operator string) IntegerExpression {
|
||||
integerExpression := binaryIntegerExpression{}
|
||||
|
||||
integerExpression.expressionInterfaceImpl.parent = &integerExpression
|
||||
integerExpression.numericInterfaceImpl.parent = &integerExpression
|
||||
integerExpression.integerInterfaceImpl.parent = &integerExpression
|
||||
|
||||
integerExpression.binaryExpression = newBinaryExpression(lhs, rhs, []byte(operator))
|
||||
|
||||
return &integerExpression
|
||||
}
|
||||
|
||||
//---------------------------------------------------//
|
||||
type prefixIntegerExpression struct {
|
||||
expressionInterfaceImpl
|
||||
numericInterfaceImpl
|
||||
integerInterfaceImpl
|
||||
|
||||
prefixExpression
|
||||
}
|
||||
|
||||
func NewPrefixIntegerExpression(expression IntegerExpression, operator string) IntegerExpression {
|
||||
integerExpression := prefixIntegerExpression{}
|
||||
integerExpression.prefixExpression = newPrefixExpression(expression, []byte(operator))
|
||||
|
||||
integerExpression.expressionInterfaceImpl.parent = &integerExpression
|
||||
integerExpression.numericInterfaceImpl.parent = &integerExpression
|
||||
integerExpression.integerInterfaceImpl.parent = &integerExpression
|
||||
|
||||
return &integerExpression
|
||||
}
|
||||
94
sqlbuilder/numeric_expression.go
Normal file
94
sqlbuilder/numeric_expression.go
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
package sqlbuilder
|
||||
|
||||
import (
|
||||
"github.com/dropbox/godropbox/database/sqltypes"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type NumericExpression interface {
|
||||
Expression
|
||||
|
||||
Eq(expression NumericExpression) BoolExpression
|
||||
NotEq(expression NumericExpression) BoolExpression
|
||||
GtEq(rhs NumericExpression) BoolExpression
|
||||
LtEq(rhs NumericExpression) BoolExpression
|
||||
|
||||
Add(expression NumericExpression) NumericExpression
|
||||
Sub(expression NumericExpression) NumericExpression
|
||||
Mul(expression NumericExpression) NumericExpression
|
||||
Div(expression NumericExpression) NumericExpression
|
||||
}
|
||||
|
||||
type numericInterfaceImpl struct {
|
||||
parent NumericExpression
|
||||
}
|
||||
|
||||
func (n *numericInterfaceImpl) Eq(expression NumericExpression) BoolExpression {
|
||||
return Eq(n.parent, expression)
|
||||
}
|
||||
|
||||
func (n *numericInterfaceImpl) NotEq(expression NumericExpression) BoolExpression {
|
||||
return Neq(n.parent, expression)
|
||||
}
|
||||
|
||||
func (n *numericInterfaceImpl) GtEq(expression NumericExpression) BoolExpression {
|
||||
return Gte(n.parent, expression)
|
||||
}
|
||||
|
||||
func (n *numericInterfaceImpl) LtEq(expression NumericExpression) BoolExpression {
|
||||
return Lte(n.parent, expression)
|
||||
}
|
||||
|
||||
func (n *numericInterfaceImpl) Add(expression NumericExpression) NumericExpression {
|
||||
return newBinaryNumericExpression(n.parent, expression, []byte(" + "))
|
||||
}
|
||||
|
||||
func (n *numericInterfaceImpl) Sub(expression NumericExpression) NumericExpression {
|
||||
return newBinaryNumericExpression(n.parent, expression, []byte(" - "))
|
||||
}
|
||||
|
||||
func (n *numericInterfaceImpl) Mul(expression NumericExpression) NumericExpression {
|
||||
return newBinaryNumericExpression(n.parent, expression, []byte(" * "))
|
||||
}
|
||||
|
||||
func (n *numericInterfaceImpl) Div(expression NumericExpression) NumericExpression {
|
||||
return newBinaryNumericExpression(n.parent, expression, []byte(" / "))
|
||||
}
|
||||
|
||||
//---------------------------------------------------//
|
||||
type numericLiteral struct {
|
||||
numericInterfaceImpl
|
||||
literalExpression
|
||||
}
|
||||
|
||||
func NewNumericLiteral(value interface{}) NumericExpression {
|
||||
numericLiteral := numericLiteral{}
|
||||
|
||||
sqlValue, err := sqltypes.BuildValue(value)
|
||||
if err != nil {
|
||||
panic(errors.Wrap(err, "Invalid literal value"))
|
||||
}
|
||||
numericLiteral.literalExpression = *NewLiteralExpression(sqlValue)
|
||||
numericLiteral.numericInterfaceImpl.parent = &numericLiteral
|
||||
|
||||
return &numericLiteral
|
||||
}
|
||||
|
||||
//---------------------------------------------------//
|
||||
type binaryNumericExpression struct {
|
||||
expressionInterfaceImpl
|
||||
numericInterfaceImpl
|
||||
|
||||
binaryExpression
|
||||
}
|
||||
|
||||
func newBinaryNumericExpression(lhs, rhs Expression, operator []byte) NumericExpression {
|
||||
numericExpression := binaryNumericExpression{}
|
||||
|
||||
numericExpression.binaryExpression = newBinaryExpression(lhs, rhs, operator)
|
||||
|
||||
numericExpression.expressionInterfaceImpl.parent = &numericExpression
|
||||
numericExpression.numericInterfaceImpl.parent = &numericExpression
|
||||
|
||||
return &numericExpression
|
||||
}
|
||||
|
|
@ -36,7 +36,7 @@ type selectStatementImpl struct {
|
|||
expressionInterfaceImpl
|
||||
|
||||
table ReadableTable
|
||||
projections []Projection
|
||||
projections []Expression
|
||||
where BoolExpression
|
||||
group *listClause
|
||||
having BoolExpression
|
||||
|
|
@ -50,7 +50,7 @@ type selectStatementImpl struct {
|
|||
|
||||
func newSelectStatement(
|
||||
table ReadableTable,
|
||||
projections []Projection) SelectStatement {
|
||||
projections []Expression) SelectStatement {
|
||||
|
||||
return &selectStatementImpl{
|
||||
table: table,
|
||||
|
|
@ -63,7 +63,7 @@ func newSelectStatement(
|
|||
}
|
||||
}
|
||||
|
||||
func (s *selectStatementImpl) SerializeSql(out *bytes.Buffer) error {
|
||||
func (s *selectStatementImpl) SerializeSql(out *bytes.Buffer, options ...serializeOption) error {
|
||||
str, err := s.String()
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -210,7 +210,7 @@ func (q *selectStatementImpl) String() (sql string, err error) {
|
|||
"nil column selected. Generated sql: %s",
|
||||
buf.String())
|
||||
}
|
||||
if err = col.SerializeSqlForColumnList(buf); err != nil {
|
||||
if err = col.SerializeSql(buf, FOR_PROJECTION); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,22 +4,22 @@ import "bytes"
|
|||
|
||||
type SelectStatementTable struct {
|
||||
statement SelectStatement
|
||||
columns []NonAliasColumn
|
||||
columns []Column
|
||||
alias string
|
||||
}
|
||||
|
||||
func (s *SelectStatementTable) Columns() []NonAliasColumn {
|
||||
func (s *SelectStatementTable) Columns() []Column {
|
||||
return s.columns
|
||||
}
|
||||
|
||||
func (s *SelectStatementTable) Column(name string) NonAliasColumn {
|
||||
func (s *SelectStatementTable) Column(name string) Column {
|
||||
return &baseColumn{
|
||||
name: name,
|
||||
tableName: s.alias,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SelectStatementTable) ColumnFrom(column NonAliasColumn) NonAliasColumn {
|
||||
func (s *SelectStatementTable) ColumnFrom(column Column) Column {
|
||||
return &baseColumn{
|
||||
name: column.TableName() + "." + column.Name(),
|
||||
tableName: s.alias,
|
||||
|
|
@ -43,7 +43,7 @@ func (s *SelectStatementTable) SerializeSql(out *bytes.Buffer) error {
|
|||
}
|
||||
|
||||
// Generates a select query on the current tableName.
|
||||
func (s *SelectStatementTable) Select(projections ...Projection) SelectStatement {
|
||||
func (s *SelectStatementTable) Select(projections ...Expression) SelectStatement {
|
||||
return newSelectStatement(s, projections)
|
||||
}
|
||||
|
||||
|
|
@ -52,9 +52,9 @@ func (s *SelectStatementTable) InnerJoinOn(table ReadableTable, onCondition Bool
|
|||
return InnerJoinOn(s, table, onCondition)
|
||||
}
|
||||
|
||||
func (s *SelectStatementTable) InnerJoinUsing(table ReadableTable, col1 Column, col2 Column) ReadableTable {
|
||||
return InnerJoinOn(s, table, col1.Eq(col2))
|
||||
}
|
||||
//func (s *SelectStatementTable) InnerJoinUsing(table ReadableTable, col1 Column, col2 Column) ReadableTable {
|
||||
// return InnerJoinOn(s, table, col1.Eq(col2))
|
||||
//}
|
||||
|
||||
// Creates a left join tableName expression using onCondition.
|
||||
func (s *SelectStatementTable) LeftJoinOn(table ReadableTable, onCondition BoolExpression) ReadableTable {
|
||||
|
|
@ -66,8 +66,8 @@ func (s *SelectStatementTable) RightJoinOn(table ReadableTable, onCondition Bool
|
|||
return RightJoinOn(s, table, onCondition)
|
||||
}
|
||||
|
||||
func (s *SelectStatementTable) FullJoin(table ReadableTable, col1 Column, col2 Column) ReadableTable {
|
||||
return FullJoin(s, table, col1.Eq(col2))
|
||||
func (s *SelectStatementTable) FullJoin(table ReadableTable, onCondition BoolExpression) ReadableTable {
|
||||
return FullJoin(s, table, onCondition)
|
||||
}
|
||||
|
||||
func (s *SelectStatementTable) CrossJoin(table ReadableTable) ReadableTable {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ type InsertStatement interface {
|
|||
|
||||
// Add a row of values to the insert statement.
|
||||
Add(row ...Expression) InsertStatement
|
||||
AddOnDuplicateKeyUpdate(col NonAliasColumn, expr Expression) InsertStatement
|
||||
AddOnDuplicateKeyUpdate(col Column, expr Expression) InsertStatement
|
||||
Comment(comment string) InsertStatement
|
||||
IgnoreDuplicates(ignore bool) InsertStatement
|
||||
}
|
||||
|
|
@ -48,7 +48,7 @@ type UnionStatement interface {
|
|||
type UpdateStatement interface {
|
||||
Statement
|
||||
|
||||
Set(column NonAliasColumn, expression Expression) UpdateStatement
|
||||
Set(column Column, expression Expression) UpdateStatement
|
||||
Where(expression BoolExpression) UpdateStatement
|
||||
OrderBy(clauses ...OrderByClause) UpdateStatement
|
||||
Limit(limit int64) UpdateStatement
|
||||
|
|
@ -178,7 +178,7 @@ func (us *unionStatementImpl) String() (sql string, err error) {
|
|||
}
|
||||
|
||||
// Union statements in MySQL require that the same number of columns in each subquery
|
||||
var projections []Projection
|
||||
var projections []Expression
|
||||
|
||||
for _, statement := range us.selects {
|
||||
// do a type assertion to get at the underlying struct
|
||||
|
|
@ -267,7 +267,7 @@ func (us *unionStatementImpl) String() (sql string, err error) {
|
|||
|
||||
func newInsertStatement(
|
||||
t WritableTable,
|
||||
columns ...NonAliasColumn) InsertStatement {
|
||||
columns ...Column) InsertStatement {
|
||||
|
||||
return &insertStatementImpl{
|
||||
table: t,
|
||||
|
|
@ -278,13 +278,13 @@ func newInsertStatement(
|
|||
}
|
||||
|
||||
type columnAssignment struct {
|
||||
col NonAliasColumn
|
||||
col Column
|
||||
expr Expression
|
||||
}
|
||||
|
||||
type insertStatementImpl struct {
|
||||
table WritableTable
|
||||
columns []NonAliasColumn
|
||||
columns []Column
|
||||
rows [][]Expression
|
||||
onDuplicateKeyUpdates []columnAssignment
|
||||
comment string
|
||||
|
|
@ -303,7 +303,7 @@ func (s *insertStatementImpl) Add(
|
|||
}
|
||||
|
||||
func (s *insertStatementImpl) AddOnDuplicateKeyUpdate(
|
||||
col NonAliasColumn,
|
||||
col Column,
|
||||
expr Expression) InsertStatement {
|
||||
|
||||
s.onDuplicateKeyUpdates = append(
|
||||
|
|
@ -361,7 +361,7 @@ func (s *insertStatementImpl) String() (sql string, err error) {
|
|||
buf.String())
|
||||
}
|
||||
|
||||
if err = col.SerializeSqlForColumnList(buf); err != nil {
|
||||
if err = col.SerializeSql(buf, FOR_PROJECTION); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
@ -413,12 +413,11 @@ func (s *insertStatementImpl) String() (sql string, err error) {
|
|||
|
||||
if colExpr.col == nil {
|
||||
return "", errors.Newf(
|
||||
("nil column in on duplicate key update list. " +
|
||||
"Generated sql: %s"),
|
||||
"nil column in on duplicate key update list. "+"Generated sql: %s",
|
||||
buf.String())
|
||||
}
|
||||
|
||||
if err = colExpr.col.SerializeSqlForColumnList(buf); err != nil {
|
||||
if err = colExpr.col.SerializeSql(buf, FOR_PROJECTION); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -426,8 +425,7 @@ func (s *insertStatementImpl) String() (sql string, err error) {
|
|||
|
||||
if colExpr.expr == nil {
|
||||
return "", errors.Newf(
|
||||
("nil expression in on duplicate key update list. " +
|
||||
"Generated sql: %s"),
|
||||
"nil expression in on duplicate key update list. "+"Generated sql: %s",
|
||||
buf.String())
|
||||
}
|
||||
|
||||
|
|
@ -447,14 +445,14 @@ func (s *insertStatementImpl) String() (sql string, err error) {
|
|||
func newUpdateStatement(table WritableTable) UpdateStatement {
|
||||
return &updateStatementImpl{
|
||||
table: table,
|
||||
updateValues: make(map[NonAliasColumn]Expression),
|
||||
updateValues: make(map[Column]Expression),
|
||||
limit: -1,
|
||||
}
|
||||
}
|
||||
|
||||
type updateStatementImpl struct {
|
||||
table WritableTable
|
||||
updateValues map[NonAliasColumn]Expression
|
||||
updateValues map[Column]Expression
|
||||
where BoolExpression
|
||||
order *listClause
|
||||
limit int64
|
||||
|
|
@ -466,7 +464,7 @@ func (u *updateStatementImpl) Execute(db *sql.DB, data interface{}) error {
|
|||
}
|
||||
|
||||
func (u *updateStatementImpl) Set(
|
||||
column NonAliasColumn,
|
||||
column Column,
|
||||
expression Expression) UpdateStatement {
|
||||
|
||||
u.updateValues[column] = expression
|
||||
|
|
|
|||
|
|
@ -12,22 +12,21 @@ import (
|
|||
// are not supported.
|
||||
type ReadableTable interface {
|
||||
// Returns the list of columns that are in the current tableName expression.
|
||||
Columns() []NonAliasColumn
|
||||
Columns() []Column
|
||||
|
||||
Column(name string) NonAliasColumn
|
||||
Column(name string) Column
|
||||
|
||||
// Generates the sql string for the current tableName expression. Note: the
|
||||
// generated string may not be a valid/executable sql statement.
|
||||
// The database is the name of the database the tableName is on
|
||||
SerializeSql(out *bytes.Buffer) error
|
||||
|
||||
// Generates a select query on the current tableName.
|
||||
Select(projections ...Projection) SelectStatement
|
||||
Select(projections ...Expression) SelectStatement
|
||||
|
||||
// Creates a inner join tableName expression using onCondition.
|
||||
InnerJoinOn(table ReadableTable, onCondition BoolExpression) ReadableTable
|
||||
|
||||
InnerJoinUsing(table ReadableTable, col1 Column, col2 Column) ReadableTable
|
||||
//InnerJoinUsing(table ReadableTable, col1 Column, col2 Column) ReadableTable
|
||||
|
||||
// Creates a left join tableName expression using onCondition.
|
||||
LeftJoinOn(table ReadableTable, onCondition BoolExpression) ReadableTable
|
||||
|
|
@ -35,7 +34,7 @@ type ReadableTable interface {
|
|||
// Creates a right join tableName expression using onCondition.
|
||||
RightJoinOn(table ReadableTable, onCondition BoolExpression) ReadableTable
|
||||
|
||||
FullJoin(table ReadableTable, col1 Column, col2 Column) ReadableTable
|
||||
FullJoin(table ReadableTable, onCondition BoolExpression) ReadableTable
|
||||
|
||||
CrossJoin(table ReadableTable) ReadableTable
|
||||
}
|
||||
|
|
@ -43,21 +42,21 @@ type ReadableTable interface {
|
|||
// The sql tableName write interface.
|
||||
type WritableTable interface {
|
||||
// Returns the list of columns that are in the tableName.
|
||||
Columns() []NonAliasColumn
|
||||
Columns() []Column
|
||||
|
||||
// Generates the sql string for the current tableName expression. Note: the
|
||||
// generated string may not be a valid/executable sql statement.
|
||||
// The database is the name of the database the tableName is on
|
||||
SerializeSql(out *bytes.Buffer) error
|
||||
|
||||
Insert(columns ...NonAliasColumn) InsertStatement
|
||||
Insert(columns ...Column) InsertStatement
|
||||
Update() UpdateStatement
|
||||
Delete() DeleteStatement
|
||||
}
|
||||
|
||||
// Defines a physical tableName in the database that is both readable and writable.
|
||||
// This function will panic if name is not valid
|
||||
func NewTable(schemaName, name string, columns ...NonAliasColumn) *Table {
|
||||
func NewTable(schemaName, name string, columns ...Column) *Table {
|
||||
if !validIdentifierName(name) {
|
||||
panic("Invalid tableName name")
|
||||
}
|
||||
|
|
@ -66,7 +65,7 @@ func NewTable(schemaName, name string, columns ...NonAliasColumn) *Table {
|
|||
schemaName: schemaName,
|
||||
name: name,
|
||||
columns: columns,
|
||||
columnLookup: make(map[string]NonAliasColumn),
|
||||
columnLookup: make(map[string]Column),
|
||||
}
|
||||
for _, c := range columns {
|
||||
err := c.setTableName(name)
|
||||
|
|
@ -87,21 +86,21 @@ type Table struct {
|
|||
schemaName string
|
||||
name string
|
||||
alias string
|
||||
columns []NonAliasColumn
|
||||
columnLookup map[string]NonAliasColumn
|
||||
columns []Column
|
||||
columnLookup map[string]Column
|
||||
// If not empty, the name of the index to force
|
||||
forcedIndex string
|
||||
}
|
||||
|
||||
// Returns the specified column, or errors if it doesn't exist in the tableName
|
||||
func (t *Table) getColumn(name string) (NonAliasColumn, error) {
|
||||
func (t *Table) getColumn(name string) (Column, error) {
|
||||
if c, ok := t.columnLookup[name]; ok {
|
||||
return c, nil
|
||||
}
|
||||
return nil, errors.Newf("No such column '%s' in tableName '%s'", name, t.name)
|
||||
}
|
||||
|
||||
func (t *Table) Column(name string) NonAliasColumn {
|
||||
func (t *Table) Column(name string) Column {
|
||||
return &baseColumn{
|
||||
name: name,
|
||||
nullable: NotNullable,
|
||||
|
|
@ -109,9 +108,9 @@ func (t *Table) Column(name string) NonAliasColumn {
|
|||
}
|
||||
}
|
||||
|
||||
// Returns all columns for a tableName as a slice of projections
|
||||
func (t *Table) Projections() []Projection {
|
||||
result := make([]Projection, 0)
|
||||
// Returns all expresssion for a tableName as a slice of projections
|
||||
func (t *Table) Projections() []Expression {
|
||||
result := make([]Expression, 0)
|
||||
|
||||
for _, col := range t.columns {
|
||||
col.Asc()
|
||||
|
|
@ -142,7 +141,7 @@ func (t *Table) SchemaName() string {
|
|||
}
|
||||
|
||||
// Returns a list of the tableName's columns
|
||||
func (t *Table) Columns() []NonAliasColumn {
|
||||
func (t *Table) Columns() []Column {
|
||||
return t.columns
|
||||
}
|
||||
|
||||
|
|
@ -182,7 +181,7 @@ func (t *Table) SerializeSql(out *bytes.Buffer) error {
|
|||
}
|
||||
|
||||
// Generates a select query on the current tableName.
|
||||
func (t *Table) Select(projections ...Projection) SelectStatement {
|
||||
func (t *Table) Select(projections ...Expression) SelectStatement {
|
||||
return newSelectStatement(t, projections)
|
||||
}
|
||||
|
||||
|
|
@ -194,13 +193,13 @@ func (t *Table) InnerJoinOn(
|
|||
return InnerJoinOn(t, table, onCondition)
|
||||
}
|
||||
|
||||
func (t *Table) InnerJoinUsing(
|
||||
table ReadableTable,
|
||||
col1 Column,
|
||||
col2 Column) ReadableTable {
|
||||
|
||||
return InnerJoinOn(t, table, col1.Eq(col2))
|
||||
}
|
||||
//func (t *Table) InnerJoinUsing(
|
||||
// table ReadableTable,
|
||||
// col1 Column,
|
||||
// col2 Column) ReadableTable {
|
||||
//
|
||||
// return InnerJoinOn(t, table, col1.Eq(col2))
|
||||
//}
|
||||
|
||||
// Creates a left join tableName expression using onCondition.
|
||||
func (t *Table) LeftJoinOn(
|
||||
|
|
@ -218,15 +217,15 @@ func (t *Table) RightJoinOn(
|
|||
return RightJoinOn(t, table, onCondition)
|
||||
}
|
||||
|
||||
func (t *Table) FullJoin(table ReadableTable, col1, col2 Column) ReadableTable {
|
||||
return FullJoin(t, table, col1.Eq(col2))
|
||||
func (t *Table) FullJoin(table ReadableTable, onCondition BoolExpression) ReadableTable {
|
||||
return FullJoin(t, table, onCondition)
|
||||
}
|
||||
|
||||
func (t *Table) CrossJoin(table ReadableTable) ReadableTable {
|
||||
return CrossJoin(t, table)
|
||||
}
|
||||
|
||||
func (t *Table) Insert(columns ...NonAliasColumn) InsertStatement {
|
||||
func (t *Table) Insert(columns ...Column) InsertStatement {
|
||||
return newInsertStatement(t, columns...)
|
||||
}
|
||||
|
||||
|
|
@ -309,15 +308,15 @@ func CrossJoin(
|
|||
return newJoinTable(lhs, rhs, CROSS_JOIN, nil)
|
||||
}
|
||||
|
||||
func (t *joinTable) Columns() []NonAliasColumn {
|
||||
columns := make([]NonAliasColumn, 0)
|
||||
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) NonAliasColumn {
|
||||
func (t *joinTable) Column(name string) Column {
|
||||
panic("Not implemented")
|
||||
}
|
||||
|
||||
|
|
@ -364,7 +363,7 @@ func (t *joinTable) SerializeSql(out *bytes.Buffer) (err error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (t *joinTable) Select(projections ...Projection) SelectStatement {
|
||||
func (t *joinTable) Select(projections ...Expression) SelectStatement {
|
||||
return newSelectStatement(t, projections)
|
||||
}
|
||||
|
||||
|
|
@ -375,14 +374,6 @@ func (t *joinTable) InnerJoinOn(
|
|||
return InnerJoinOn(t, table, onCondition)
|
||||
}
|
||||
|
||||
func (t *joinTable) InnerJoinUsing(
|
||||
table ReadableTable,
|
||||
col1 Column,
|
||||
col2 Column) ReadableTable {
|
||||
|
||||
return InnerJoinOn(t, table, col1.Eq(col2))
|
||||
}
|
||||
|
||||
func (t *joinTable) LeftJoinOn(
|
||||
table ReadableTable,
|
||||
onCondition BoolExpression) ReadableTable {
|
||||
|
|
@ -390,8 +381,8 @@ func (t *joinTable) LeftJoinOn(
|
|||
return LeftJoinOn(t, table, onCondition)
|
||||
}
|
||||
|
||||
func (t *joinTable) FullJoin(table ReadableTable, col1 Column, col2 Column) ReadableTable {
|
||||
return FullJoin(t, table, col1.Eq(col2))
|
||||
func (t *joinTable) FullJoin(table ReadableTable, onCondition BoolExpression) ReadableTable {
|
||||
return FullJoin(t, table, onCondition)
|
||||
}
|
||||
|
||||
func (t *joinTable) CrossJoin(table ReadableTable) ReadableTable {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
// +build disabled
|
||||
|
||||
package sqlbuilder
|
||||
|
||||
var table1Col1 = IntColumn("col1", Nullable)
|
||||
|
|
|
|||
|
|
@ -1,9 +1,5 @@
|
|||
package sqlbuilder
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
)
|
||||
|
||||
// A clause that can be used in order by
|
||||
type OrderByClause interface {
|
||||
Clause
|
||||
|
|
@ -11,43 +7,43 @@ type OrderByClause interface {
|
|||
}
|
||||
|
||||
// A clause that is selectable.
|
||||
type Projection interface {
|
||||
Clause
|
||||
isProjectionInterface
|
||||
//type Projection interface {
|
||||
// Clause
|
||||
// isProjectionInterface
|
||||
//
|
||||
// SerializeSqlForColumnList(out *bytes.Buffer) error
|
||||
//}
|
||||
|
||||
SerializeSqlForColumnList(out *bytes.Buffer) error
|
||||
}
|
||||
//type ColumnList []Column
|
||||
//
|
||||
//func (cl ColumnList) SerializeSql(out *bytes.Buffer, options ...serializeOption) error {
|
||||
// for i, column := range cl {
|
||||
// column.SerializeSql(out)
|
||||
//
|
||||
// if i != len(cl)-1 {
|
||||
// out.WriteString(", ")
|
||||
// }
|
||||
// }
|
||||
// return nil
|
||||
//}
|
||||
//
|
||||
//func (cl ColumnList) isProjectionType() {
|
||||
//}
|
||||
//
|
||||
//func (cl ColumnList) As(name string) Clause {
|
||||
// panic("Unallowed operation ")
|
||||
//}
|
||||
|
||||
type ColumnList []NonAliasColumn
|
||||
|
||||
func (cl ColumnList) SerializeSql(out *bytes.Buffer) error {
|
||||
for i, column := range cl {
|
||||
column.SerializeSql(out)
|
||||
|
||||
if i != len(cl)-1 {
|
||||
out.WriteString(", ")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cl ColumnList) isProjectionType() {
|
||||
}
|
||||
|
||||
func (cl ColumnList) As(name string) Projection {
|
||||
panic("Unallowed operation ")
|
||||
}
|
||||
|
||||
func (cl ColumnList) SerializeSqlForColumnList(out *bytes.Buffer) error {
|
||||
for i, column := range cl {
|
||||
column.SerializeSqlForColumnList(out)
|
||||
|
||||
if i != len(cl)-1 {
|
||||
out.WriteString(", ")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
//func (cl ColumnList) SerializeSqlForColumnList(out *bytes.Buffer) error {
|
||||
// for i, column := range cl {
|
||||
// column.SerializeSqlForColumnList(out)
|
||||
//
|
||||
// if i != len(cl)-1 {
|
||||
// out.WriteString(", ")
|
||||
// }
|
||||
// }
|
||||
// return nil
|
||||
//}
|
||||
|
||||
//
|
||||
// Boiler plates ...
|
||||
|
|
@ -63,12 +59,13 @@ type isOrderByClause struct {
|
|||
func (o *isOrderByClause) isOrderByClauseType() {
|
||||
}
|
||||
|
||||
type isProjectionInterface interface {
|
||||
isProjectionType()
|
||||
}
|
||||
|
||||
type isProjection struct {
|
||||
}
|
||||
|
||||
func (p *isProjection) isProjectionType() {
|
||||
}
|
||||
//
|
||||
//type isProjectionInterface interface {
|
||||
// isProjectionType()
|
||||
//}
|
||||
//
|
||||
//type isProjection struct {
|
||||
//}
|
||||
//
|
||||
//func (p *isProjection) isProjectionType() {
|
||||
//}
|
||||
|
|
|
|||
1
sqlbuilder/utils.go
Normal file
1
sqlbuilder/utils.go
Normal file
|
|
@ -0,0 +1 @@
|
|||
package sqlbuilder
|
||||
Loading…
Add table
Add a link
Reference in a new issue