Model refactor cleanup.

This commit is contained in:
zer0sub 2019-05-07 19:06:21 +02:00
parent c9561ecc37
commit f016a93d78
33 changed files with 536 additions and 618 deletions

View file

@ -1,20 +1,20 @@
package sqlbuilder package sqlbuilder
type Alias struct { type Alias struct {
expression Expression expression expression
alias string alias string
} }
func NewAlias(expression Expression, alias string) *Alias { func NewAlias(expression expression, alias string) *Alias {
return &Alias{ return &Alias{
expression: expression, expression: expression,
alias: alias, alias: alias,
} }
} }
func (a *Alias) SerializeForProjection(out *queryData) error { func (a *Alias) serializeForProjection(out *queryData) error {
err := a.expression.Serialize(out) err := a.expression.serialize(out)
if err != nil { if err != nil {
return err return err

View file

@ -1,51 +1,51 @@
package sqlbuilder package sqlbuilder
type BoolExpression interface { type boolExpression interface {
Expression expression
Eq(expression BoolExpression) BoolExpression Eq(expression boolExpression) boolExpression
NotEq(expression BoolExpression) BoolExpression NotEq(expression boolExpression) boolExpression
GtEq(rhs Expression) BoolExpression GtEq(rhs expression) boolExpression
LtEq(rhs Expression) BoolExpression LtEq(rhs expression) boolExpression
AND(expression BoolExpression) BoolExpression AND(expression boolExpression) boolExpression
OR(expression BoolExpression) BoolExpression OR(expression boolExpression) boolExpression
IS_TRUE() BoolExpression IS_TRUE() boolExpression
IS_FALSE() BoolExpression IS_FALSE() boolExpression
} }
type boolInterfaceImpl struct { type boolInterfaceImpl struct {
parent BoolExpression parent boolExpression
} }
func (b *boolInterfaceImpl) Eq(expression BoolExpression) BoolExpression { func (b *boolInterfaceImpl) Eq(expression boolExpression) boolExpression {
return Eq(b.parent, expression) return Eq(b.parent, expression)
} }
func (b *boolInterfaceImpl) NotEq(expression BoolExpression) BoolExpression { func (b *boolInterfaceImpl) NotEq(expression boolExpression) boolExpression {
return NotEq(b.parent, expression) return NotEq(b.parent, expression)
} }
func (b *boolInterfaceImpl) GtEq(rhs Expression) BoolExpression { func (b *boolInterfaceImpl) GtEq(rhs expression) boolExpression {
return GtEq(b.parent, rhs) return GtEq(b.parent, rhs)
} }
func (b *boolInterfaceImpl) LtEq(rhs Expression) BoolExpression { func (b *boolInterfaceImpl) LtEq(rhs expression) boolExpression {
return LtEq(b.parent, rhs) return LtEq(b.parent, rhs)
} }
func (b *boolInterfaceImpl) AND(expression BoolExpression) BoolExpression { func (b *boolInterfaceImpl) AND(expression boolExpression) boolExpression {
return And(b.parent, expression) return And(b.parent, expression)
} }
func (b *boolInterfaceImpl) OR(expression BoolExpression) BoolExpression { func (b *boolInterfaceImpl) OR(expression boolExpression) boolExpression {
return Or(b.parent, expression) return Or(b.parent, expression)
} }
func (b *boolInterfaceImpl) IS_TRUE() BoolExpression { func (b *boolInterfaceImpl) IS_TRUE() boolExpression {
return IsTrue(b.parent) return IsTrue(b.parent)
} }
func (b *boolInterfaceImpl) IS_FALSE() BoolExpression { func (b *boolInterfaceImpl) IS_FALSE() boolExpression {
return nil return nil
} }
@ -55,7 +55,7 @@ type boolLiteralExpression struct {
literalExpression literalExpression
} }
func newBoolLiteralExpression(value bool) BoolExpression { func newBoolLiteralExpression(value bool) boolExpression {
boolLiteralExpression := boolLiteralExpression{} boolLiteralExpression := boolLiteralExpression{}
boolLiteralExpression.literalExpression = *Literal(value) boolLiteralExpression.literalExpression = *Literal(value)
@ -72,7 +72,7 @@ type binaryBoolExpression struct {
binaryExpression binaryExpression
} }
func newBinaryBoolExpression(lhs, rhs Expression, operator string) BoolExpression { func newBinaryBoolExpression(lhs, rhs expression, operator string) boolExpression {
boolExpression := binaryBoolExpression{} boolExpression := binaryBoolExpression{}
boolExpression.binaryExpression = newBinaryExpression(lhs, rhs, operator) boolExpression.binaryExpression = newBinaryExpression(lhs, rhs, operator)
@ -90,7 +90,7 @@ type prefixBoolExpression struct {
prefixExpression prefixExpression
} }
func newPrefixBoolExpression(expression Expression, operator string) BoolExpression { func newPrefixBoolExpression(expression expression, operator string) boolExpression {
boolExpression := prefixBoolExpression{} boolExpression := prefixBoolExpression{}
boolExpression.prefixExpression = newPrefixExpression(expression, operator) boolExpression.prefixExpression = newPrefixExpression(expression, operator)
@ -100,100 +100,100 @@ func newPrefixBoolExpression(expression Expression, operator string) BoolExpress
return &boolExpression return &boolExpression
} }
func EXISTS(subQuery SelectStatement) BoolExpression { func EXISTS(subQuery selectStatement) boolExpression {
return newPrefixBoolExpression(subQuery, "EXISTS") return newPrefixBoolExpression(subQuery, "EXISTS")
} }
// Returns a representation of "a=b" // Returns a representation of "a=b"
func Eq(lhs, rhs Expression) BoolExpression { func Eq(lhs, rhs expression) boolExpression {
return newBinaryBoolExpression(lhs, rhs, "=") return newBinaryBoolExpression(lhs, rhs, "=")
} }
// Returns a representation of "a=b", where b is a literal // Returns a representation of "a=b", where b is a literal
func EqL(lhs Expression, val interface{}) BoolExpression { func EqL(lhs expression, val interface{}) boolExpression {
return Eq(lhs, Literal(val)) return Eq(lhs, Literal(val))
} }
// Returns a representation of "a!=b" // Returns a representation of "a!=b"
func NotEq(lhs, rhs Expression) BoolExpression { func NotEq(lhs, rhs expression) boolExpression {
return newBinaryBoolExpression(lhs, rhs, "!=") return newBinaryBoolExpression(lhs, rhs, "!=")
} }
// Returns a representation of "a!=b", where b is a literal // Returns a representation of "a!=b", where b is a literal
func NeqL(lhs Expression, val interface{}) BoolExpression { func NeqL(lhs expression, val interface{}) boolExpression {
return NotEq(lhs, Literal(val)) return NotEq(lhs, Literal(val))
} }
// Returns a representation of "a<b" // Returns a representation of "a<b"
func Lt(lhs Expression, rhs Expression) BoolExpression { func Lt(lhs expression, rhs expression) boolExpression {
return newBinaryBoolExpression(lhs, rhs, "<") return newBinaryBoolExpression(lhs, rhs, "<")
} }
// Returns a representation of "a<b", where b is a literal // Returns a representation of "a<b", where b is a literal
func LtL(lhs Expression, val interface{}) BoolExpression { func LtL(lhs expression, val interface{}) boolExpression {
return Lt(lhs, Literal(val)) return Lt(lhs, Literal(val))
} }
// Returns a representation of "a<=b" // Returns a representation of "a<=b"
func LtEq(lhs, rhs Expression) BoolExpression { func LtEq(lhs, rhs expression) boolExpression {
return newBinaryBoolExpression(lhs, rhs, "<=") return newBinaryBoolExpression(lhs, rhs, "<=")
} }
// Returns a representation of "a<=b", where b is a literal // Returns a representation of "a<=b", where b is a literal
func LteL(lhs Expression, val interface{}) BoolExpression { func LteL(lhs expression, val interface{}) boolExpression {
return LtEq(lhs, Literal(val)) return LtEq(lhs, Literal(val))
} }
// Returns a representation of "a>b" // Returns a representation of "a>b"
func Gt(lhs, rhs Expression) BoolExpression { func Gt(lhs, rhs expression) boolExpression {
return newBinaryBoolExpression(lhs, rhs, ">") return newBinaryBoolExpression(lhs, rhs, ">")
} }
// Returns a representation of "a>b", where b is a literal // Returns a representation of "a>b", where b is a literal
func GtL(lhs Expression, val interface{}) BoolExpression { func GtL(lhs expression, val interface{}) boolExpression {
return Gt(lhs, Literal(val)) return Gt(lhs, Literal(val))
} }
// Returns a representation of "a>=b" // Returns a representation of "a>=b"
func GtEq(lhs, rhs Expression) BoolExpression { func GtEq(lhs, rhs expression) boolExpression {
return newBinaryBoolExpression(lhs, rhs, ">=") return newBinaryBoolExpression(lhs, rhs, ">=")
} }
// Returns a representation of "a>=b", where b is a literal // Returns a representation of "a>=b", where b is a literal
func GteL(lhs Expression, val interface{}) BoolExpression { func GteL(lhs expression, val interface{}) boolExpression {
return GtEq(lhs, Literal(val)) return GtEq(lhs, Literal(val))
} }
// Returns a representation of "not expr" // Returns a representation of "not expr"
func Not(expr BoolExpression) BoolExpression { func Not(expr boolExpression) boolExpression {
return newPrefixBoolExpression(expr, "NOT") return newPrefixBoolExpression(expr, "NOT")
} }
func IsTrue(expr BoolExpression) BoolExpression { func IsTrue(expr boolExpression) boolExpression {
return newPrefixBoolExpression(expr, "IS TRUE") return newPrefixBoolExpression(expr, "IS TRUE")
} }
func And(lhs, rhs Expression) BoolExpression { func And(lhs, rhs expression) boolExpression {
return newBinaryBoolExpression(lhs, rhs, "AND") return newBinaryBoolExpression(lhs, rhs, "AND")
} }
// Returns a representation of "c[0] OR ... OR c[n-1]" for c in clauses // Returns a representation of "c[0] OR ... OR c[n-1]" for c in clauses
func Or(lhs, rhs Expression) BoolExpression { func Or(lhs, rhs expression) boolExpression {
return newBinaryBoolExpression(lhs, rhs, "OR") return newBinaryBoolExpression(lhs, rhs, "OR")
} }
func Like(lhs, rhs Expression) BoolExpression { func Like(lhs, rhs expression) boolExpression {
return newBinaryBoolExpression(lhs, rhs, "LIKE") return newBinaryBoolExpression(lhs, rhs, "LIKE")
} }
func LikeL(lhs Expression, val string) BoolExpression { func LikeL(lhs expression, val string) boolExpression {
return Like(lhs, Literal(val)) return Like(lhs, Literal(val))
} }
func Regexp(lhs, rhs Expression) BoolExpression { func Regexp(lhs, rhs expression) boolExpression {
return newBinaryBoolExpression(lhs, rhs, "REGEXP") return newBinaryBoolExpression(lhs, rhs, "REGEXP")
} }
func RegexpL(lhs Expression, val string) BoolExpression { func RegexpL(lhs expression, val string) boolExpression {
return Regexp(lhs, Literal(val)) return Regexp(lhs, Literal(val))
} }

View file

@ -9,7 +9,7 @@ func TestBinaryExpression(t *testing.T) {
boolExpression := Eq(Literal(2), Literal(3)) boolExpression := Eq(Literal(2), Literal(3))
out := queryData{} out := queryData{}
err := boolExpression.Serialize(&out) err := boolExpression.serialize(&out)
assert.NilError(t, err) assert.NilError(t, err)
@ -20,7 +20,7 @@ func TestBinaryExpression(t *testing.T) {
alias := boolExpression.AS("alias_eq_expression") alias := boolExpression.AS("alias_eq_expression")
out := queryData{} out := queryData{}
err := alias.SerializeForProjection(&out) err := alias.serializeForProjection(&out)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, out.buff.String(), `$1 = $2 AS "alias_eq_expression"`) assert.Equal(t, out.buff.String(), `$1 = $2 AS "alias_eq_expression"`)
@ -30,7 +30,7 @@ func TestBinaryExpression(t *testing.T) {
exp := boolExpression.AND(Eq(Literal(4), Literal(5))) exp := boolExpression.AND(Eq(Literal(4), Literal(5)))
out := queryData{} out := queryData{}
err := exp.Serialize(&out) err := exp.serialize(&out)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, out.buff.String(), `($1 = $2 AND $3 = $4)`) assert.Equal(t, out.buff.String(), `($1 = $2 AND $3 = $4)`)
@ -40,7 +40,7 @@ func TestBinaryExpression(t *testing.T) {
exp := boolExpression.OR(Eq(Literal(4), Literal(5))) exp := boolExpression.OR(Eq(Literal(4), Literal(5)))
out := queryData{} out := queryData{}
err := exp.Serialize(&out) err := exp.serialize(&out)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, out.buff.String(), `($1 = $2 OR $3 = $4)`) assert.Equal(t, out.buff.String(), `($1 = $2 OR $3 = $4)`)
@ -51,7 +51,7 @@ func TestUnaryExpression(t *testing.T) {
notExpression := Not(Eq(Literal(2), Literal(1))) notExpression := Not(Eq(Literal(2), Literal(1)))
out := queryData{} out := queryData{}
err := notExpression.Serialize(&out) err := notExpression.serialize(&out)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, out.buff.String(), "NOT $1 = $2") assert.Equal(t, out.buff.String(), "NOT $1 = $2")
@ -60,7 +60,7 @@ func TestUnaryExpression(t *testing.T) {
alias := notExpression.AS("alias_not_expression") alias := notExpression.AS("alias_not_expression")
out := queryData{} out := queryData{}
err := alias.SerializeForProjection(&out) err := alias.serializeForProjection(&out)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, out.buff.String(), `NOT $1 = $2 AS "alias_not_expression"`) assert.Equal(t, out.buff.String(), `NOT $1 = $2 AS "alias_not_expression"`)
@ -70,7 +70,7 @@ func TestUnaryExpression(t *testing.T) {
exp := notExpression.AND(Eq(Literal(4), Literal(5))) exp := notExpression.AND(Eq(Literal(4), Literal(5)))
out := queryData{} out := queryData{}
err := exp.Serialize(&out) err := exp.serialize(&out)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, out.buff.String(), `(NOT $1 = $2 AND $3 = $4)`) assert.Equal(t, out.buff.String(), `(NOT $1 = $2 AND $3 = $4)`)
@ -81,7 +81,7 @@ func TestUnaryIsTrueExpression(t *testing.T) {
notExpression := IsTrue(Eq(Literal(2), Literal(1))) notExpression := IsTrue(Eq(Literal(2), Literal(1)))
out := queryData{} out := queryData{}
err := notExpression.Serialize(&out) err := notExpression.serialize(&out)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, out.buff.String(), "IS TRUE $1 = $2") assert.Equal(t, out.buff.String(), "IS TRUE $1 = $2")
@ -90,7 +90,7 @@ func TestUnaryIsTrueExpression(t *testing.T) {
exp := notExpression.AND(Eq(Literal(4), Literal(5))) exp := notExpression.AND(Eq(Literal(4), Literal(5)))
out := queryData{} out := queryData{}
err := exp.Serialize(&out) err := exp.serialize(&out)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, out.buff.String(), `(IS TRUE $1 = $2 AND $3 = $4)`) assert.Equal(t, out.buff.String(), `(IS TRUE $1 = $2 AND $3 = $4)`)
@ -101,7 +101,7 @@ func TestBoolLiteral(t *testing.T) {
literal := newBoolLiteralExpression(true) literal := newBoolLiteralExpression(true)
out := queryData{} out := queryData{}
err := literal.Serialize(&out) err := literal.serialize(&out)
assert.NilError(t, err) assert.NilError(t, err)
@ -116,7 +116,7 @@ func TestExists(t *testing.T) {
) )
out := queryData{} out := queryData{}
err := query.Serialize(&out) err := query.serialize(&out)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, out.buff.String(), "EXISTS (SELECT $1 FROM db.table2 WHERE table1.col1 = table2.col3)") assert.Equal(t, out.buff.String(), "EXISTS (SELECT $1 FROM db.table2 WHERE table1.col1 = table2.col3)")
@ -126,7 +126,7 @@ func TestIn(t *testing.T) {
query := Literal(1.11).IN(table1.SELECT(table1Col1)) query := Literal(1.11).IN(table1.SELECT(table1Col1))
out := queryData{} out := queryData{}
err := query.Serialize(&out) err := query.serialize(&out)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, out.buff.String(), `$1 IN (SELECT table1.col1 AS "table1.col1" FROM db.table1)`) assert.Equal(t, out.buff.String(), `$1 IN (SELECT table1.col1 AS "table1.col1" FROM db.table1)`)
@ -134,7 +134,7 @@ func TestIn(t *testing.T) {
query2 := ROW(Literal(12), table1Col1).IN(table2.SELECT(table2Col3, table3Col1)) query2 := ROW(Literal(12), table1Col1).IN(table2.SELECT(table2Col3, table3Col1))
out = queryData{} out = queryData{}
err = query2.Serialize(&out) err = query2.serialize(&out)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, out.buff.String(), `(ROW($1, table1.col1) IN (SELECT table2.col3 AS "table2.col3", table3.col1 AS "table3.col1" FROM db.table2))`) assert.Equal(t, out.buff.String(), `(ROW($1, table1.col1) IN (SELECT table2.col3 AS "table2.col3", table3.col1 AS "table3.col1" FROM db.table2))`)

View file

@ -6,14 +6,8 @@ import (
"strconv" "strconv"
) )
type serializeOption int type clause interface {
serialize(out *queryData) error
const (
FOR_PROJECTION = iota
)
type Clause interface {
Serialize(out *queryData, options ...serializeOption) error
} }
type queryData struct { type queryData struct {
@ -40,34 +34,34 @@ const (
having_clause having_clause
) )
func (q *queryData) WriteProjection(projections []Projection) error { func (q *queryData) WriteProjection(projections []projection) error {
q.clauseType = projection_clause q.clauseType = projection_clause
return serializeProjectionList(projections, q) return serializeProjectionList(projections, q)
} }
func (q *queryData) WriteWhere(where Expression) error { func (q *queryData) WriteWhere(where expression) error {
q.clauseType = where_clause q.clauseType = where_clause
q.WriteString(" WHERE ") q.WriteString(" WHERE ")
return where.Serialize(q) return where.serialize(q)
} }
func (q *queryData) WriteGroupBy(groupBy []Clause) error { func (q *queryData) WriteGroupBy(groupBy []groupByClause) error {
q.clauseType = group_by_clause q.clauseType = group_by_clause
q.WriteString(" GROUP BY ") q.WriteString(" GROUP BY ")
return serializeClauseList(groupBy, q) return serializeGroupByClauseList(groupBy, q)
} }
func (q *queryData) WriteOrderBy(orderBy []OrderByClause) error { func (q *queryData) WriteOrderBy(orderBy []orderByClause) error {
q.clauseType = order_by_clause q.clauseType = order_by_clause
q.WriteString(" ORDER BY ") q.WriteString(" ORDER BY ")
return serializeOrderByClauseList(orderBy, q) return serializeOrderByClauseList(orderBy, q)
} }
func (q *queryData) WriteHaving(having Expression) error { func (q *queryData) WriteHaving(having expression) error {
q.clauseType = having_clause q.clauseType = having_clause
q.WriteString(" HAVING ") q.WriteString(" HAVING ")
return having.Serialize(q) return having.serialize(q)
} }
@ -141,12 +135,3 @@ func argToString(value interface{}) (string, error) {
return "", errors.New("Unsupported literal type. ") return "", errors.New("Unsupported literal type. ")
} }
} }
func contains(s []serializeOption, e serializeOption) bool {
for _, a := range s {
if a == e {
return true
}
}
return false
}

View file

@ -6,13 +6,13 @@ import (
"strings" "strings"
) )
type Column interface { type column interface {
Expression expression
Name() string Name() string
TableName() string TableName() string
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)
@ -49,7 +49,7 @@ type baseColumn struct {
tableName string tableName string
} }
func newBaseColumn(name string, nullable NullableColumn, tableName string, parent Column) baseColumn { func newBaseColumn(name string, nullable NullableColumn, tableName string, parent column) baseColumn {
bc := baseColumn{ bc := baseColumn{
name: name, name: name,
nullable: nullable, nullable: nullable,
@ -73,11 +73,11 @@ func (c *baseColumn) setTableName(table string) {
c.tableName = table c.tableName = table
} }
func (c *baseColumn) DefaultAlias() Projection { func (c *baseColumn) DefaultAlias() projection {
return c.AS(c.tableName + "." + c.name) return c.AS(c.tableName + "." + c.name)
} }
func (c baseColumn) Serialize(out *queryData, options ...serializeOption) error { func (c baseColumn) serialize(out *queryData) error {
setOrderBy := out.statementType == set_statement && out.clauseType == order_by_clause setOrderBy := out.statementType == set_statement && out.clauseType == order_by_clause

View file

@ -9,26 +9,26 @@ func TestNewBoolColumn(t *testing.T) {
boolColumn := NewBoolColumn("col", Nullable) boolColumn := NewBoolColumn("col", Nullable)
out := queryData{} out := queryData{}
err := boolColumn.Serialize(&out) err := boolColumn.serialize(&out)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, out.buff.String(), "col") assert.Equal(t, out.buff.String(), "col")
out.Reset() out.Reset()
err = boolColumn.Serialize(&out, FOR_PROJECTION) err = boolColumn.serialize(&out)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, out.buff.String(), "col") assert.Equal(t, out.buff.String(), "col")
out.Reset() out.Reset()
boolColumn.setTableName("table1") boolColumn.setTableName("table1")
err = boolColumn.DefaultAlias().SerializeForProjection(&out) err = boolColumn.DefaultAlias().serializeForProjection(&out)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, out.buff.String(), `table1.col AS "table1.col"`) assert.Equal(t, out.buff.String(), `table1.col AS "table1.col"`)
out.Reset() out.Reset()
boolColumn.setTableName("table1") boolColumn.setTableName("table1")
aliasedBoolColumn := boolColumn.AS("alias1") aliasedBoolColumn := boolColumn.AS("alias1")
err = aliasedBoolColumn.SerializeForProjection(&out) err = aliasedBoolColumn.serializeForProjection(&out)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, out.buff.String(), `table1.col AS "alias1"`) assert.Equal(t, out.buff.String(), `table1.col AS "alias1"`)
} }
@ -37,26 +37,26 @@ func TestNewIntColumn(t *testing.T) {
integerColumn := NewIntegerColumn("col", Nullable) integerColumn := NewIntegerColumn("col", Nullable)
out := queryData{} out := queryData{}
err := integerColumn.Serialize(&out) err := integerColumn.serialize(&out)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, out.buff.String(), "col") assert.Equal(t, out.buff.String(), "col")
out.Reset() out.Reset()
err = integerColumn.Serialize(&out, FOR_PROJECTION) err = integerColumn.serialize(&out)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, out.buff.String(), "col") assert.Equal(t, out.buff.String(), "col")
out.Reset() out.Reset()
integerColumn.setTableName("table1") integerColumn.setTableName("table1")
err = integerColumn.DefaultAlias().SerializeForProjection(&out) err = integerColumn.DefaultAlias().serializeForProjection(&out)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, out.buff.String(), `table1.col AS "table1.col"`) assert.Equal(t, out.buff.String(), `table1.col AS "table1.col"`)
out.Reset() out.Reset()
integerColumn.setTableName("table1") integerColumn.setTableName("table1")
aliasedBoolColumn := integerColumn.AS("alias1") aliasedBoolColumn := integerColumn.AS("alias1")
err = aliasedBoolColumn.SerializeForProjection(&out) err = aliasedBoolColumn.serializeForProjection(&out)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, out.buff.String(), `table1.col AS "alias1"`) assert.Equal(t, out.buff.String(), `table1.col AS "alias1"`)
} }
@ -65,26 +65,26 @@ func TestNewNumericColumnColumn(t *testing.T) {
numericColumn := NewNumericColumn("col", Nullable) numericColumn := NewNumericColumn("col", Nullable)
out := queryData{} out := queryData{}
err := numericColumn.Serialize(&out) err := numericColumn.serialize(&out)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, out.buff.String(), "col") assert.Equal(t, out.buff.String(), "col")
out.Reset() out.Reset()
err = numericColumn.Serialize(&out) err = numericColumn.serialize(&out)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, out.buff.String(), "col") assert.Equal(t, out.buff.String(), "col")
out.Reset() out.Reset()
numericColumn.setTableName("table1") numericColumn.setTableName("table1")
err = numericColumn.DefaultAlias().SerializeForProjection(&out) err = numericColumn.DefaultAlias().serializeForProjection(&out)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, out.buff.String(), `table1.col AS "table1.col"`) assert.Equal(t, out.buff.String(), `table1.col AS "table1.col"`)
out.Reset() out.Reset()
numericColumn.setTableName("table1") numericColumn.setTableName("table1")
aliasedBoolColumn := numericColumn.AS("alias1") aliasedBoolColumn := numericColumn.AS("alias1")
err = aliasedBoolColumn.SerializeForProjection(&out) err = aliasedBoolColumn.serializeForProjection(&out)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, out.buff.String(), `table1.col AS "alias1"`) assert.Equal(t, out.buff.String(), `table1.col AS "alias1"`)
} }

View file

@ -6,24 +6,24 @@ import (
"github.com/sub0zero/go-sqlbuilder/types" "github.com/sub0zero/go-sqlbuilder/types"
) )
type DeleteStatement interface { type deleteStatement interface {
Statement statement
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
} }
func (d *deleteStatementImpl) WHERE(expression BoolExpression) DeleteStatement { func (d *deleteStatementImpl) WHERE(expression boolExpression) deleteStatement {
d.where = expression d.where = expression
return d return d
} }
@ -38,7 +38,7 @@ func (d *deleteStatementImpl) Sql() (query string, args []interface{}, err error
return "", nil, errors.New("nil tableName.") return "", nil, errors.New("nil tableName.")
} }
if err = d.table.SerializeSql(queryData); err != nil { if err = d.table.serializeSql(queryData); err != nil {
return return
} }

View file

@ -5,63 +5,68 @@ import (
) )
// An expression // An expression
type Expression interface { type expression interface {
Clause clause
Projection projection
groupByClause
IN(subQuery SelectStatement) BoolExpression IN(subQuery selectStatement) boolExpression
NOT_IN(subQuery SelectStatement) BoolExpression NOT_IN(subQuery selectStatement) boolExpression
AS(alias string) Projection AS(alias string) projection
IS_DISTINCT_FROM(expression Expression) BoolExpression IS_DISTINCT_FROM(expression expression) boolExpression
IS_NULL() BoolExpression IS_NULL() boolExpression
ASC() OrderByClause ASC() orderByClause
DESC() OrderByClause DESC() orderByClause
} }
type expressionInterfaceImpl struct { type expressionInterfaceImpl struct {
parent Expression parent expression
} }
func (e *expressionInterfaceImpl) IN(subQuery SelectStatement) BoolExpression { func (e *expressionInterfaceImpl) IN(subQuery selectStatement) boolExpression {
return newBinaryBoolExpression(e.parent, subQuery, "IN") return newBinaryBoolExpression(e.parent, subQuery, "IN")
} }
func (e *expressionInterfaceImpl) NOT_IN(subQuery SelectStatement) BoolExpression { func (e *expressionInterfaceImpl) NOT_IN(subQuery selectStatement) boolExpression {
return newBinaryBoolExpression(e.parent, subQuery, "NOT_IN") return newBinaryBoolExpression(e.parent, subQuery, "NOT_IN")
} }
func (e *expressionInterfaceImpl) AS(alias string) Projection { func (e *expressionInterfaceImpl) AS(alias string) projection {
return NewAlias(e.parent, alias) return NewAlias(e.parent, alias)
} }
func (e *expressionInterfaceImpl) IS_DISTINCT_FROM(expression Expression) BoolExpression { func (e *expressionInterfaceImpl) IS_DISTINCT_FROM(expression expression) boolExpression {
return newBinaryBoolExpression(e.parent, expression, "IS DISTINCT FROM") return newBinaryBoolExpression(e.parent, expression, "IS DISTINCT FROM")
} }
func (e *expressionInterfaceImpl) IS_NULL() BoolExpression { func (e *expressionInterfaceImpl) IS_NULL() boolExpression {
return nil return nil
} }
func (e *expressionInterfaceImpl) ASC() OrderByClause { func (e *expressionInterfaceImpl) ASC() orderByClause {
return &orderByClause{expression: e.parent, ascent: true} return &orderByClauseImpl{expression: e.parent, ascent: true}
} }
func (e *expressionInterfaceImpl) DESC() OrderByClause { func (e *expressionInterfaceImpl) DESC() orderByClause {
return &orderByClause{expression: e.parent, ascent: false} return &orderByClauseImpl{expression: e.parent, ascent: false}
} }
func (e *expressionInterfaceImpl) SerializeForProjection(out *queryData) error { func (e *expressionInterfaceImpl) serializeForGroupBy(out *queryData) error {
return e.parent.Serialize(out, FOR_PROJECTION) return e.parent.serialize(out)
}
func (e *expressionInterfaceImpl) serializeForProjection(out *queryData) error {
return e.parent.serialize(out)
} }
// Representation of binary operations (e.g. comparisons, arithmetic) // Representation of binary operations (e.g. comparisons, arithmetic)
type binaryExpression struct { type binaryExpression struct {
lhs, rhs Expression lhs, rhs expression
operator string operator string
} }
func newBinaryExpression(lhs, rhs Expression, operator string, parent ...Expression) binaryExpression { func newBinaryExpression(lhs, rhs expression, operator string, parent ...expression) binaryExpression {
binaryExpression := binaryExpression{ binaryExpression := binaryExpression{
lhs: lhs, lhs: lhs,
rhs: rhs, rhs: rhs,
@ -71,11 +76,11 @@ func newBinaryExpression(lhs, rhs Expression, operator string, parent ...Express
return binaryExpression return binaryExpression
} }
func isSimpleOperand(expression Expression) bool { func isSimpleOperand(expression expression) bool {
if _, ok := expression.(*literalExpression); ok { if _, ok := expression.(*literalExpression); ok {
return true return true
} }
if _, ok := expression.(Column); ok { if _, ok := expression.(column); ok {
return true return true
} }
if _, ok := expression.(*numericFunc); ok { if _, ok := expression.(*numericFunc); ok {
@ -85,7 +90,7 @@ func isSimpleOperand(expression Expression) bool {
return false return false
} }
func (c *binaryExpression) Serialize(out *queryData, options ...serializeOption) error { func (c *binaryExpression) serialize(out *queryData) error {
if c.lhs == nil { if c.lhs == nil {
return errors.Newf("nil lhs.") return errors.Newf("nil lhs.")
} }
@ -99,13 +104,13 @@ func (c *binaryExpression) Serialize(out *queryData, options ...serializeOption)
out.WriteString("(") out.WriteString("(")
} }
if err := c.lhs.Serialize(out); err != nil { if err := c.lhs.serialize(out); err != nil {
return err return err
} }
out.WriteString(" " + c.operator + " ") out.WriteString(" " + c.operator + " ")
if err := c.rhs.Serialize(out); err != nil { if err := c.rhs.serialize(out); err != nil {
return err return err
} }
@ -118,11 +123,11 @@ func (c *binaryExpression) Serialize(out *queryData, options ...serializeOption)
// A not expression which negates a expression value // A not expression which negates a expression value
type prefixExpression struct { type prefixExpression struct {
expression Expression expression expression
operator string operator string
} }
func newPrefixExpression(expression Expression, operator string) prefixExpression { func newPrefixExpression(expression expression, operator string) prefixExpression {
prefixExpression := prefixExpression{ prefixExpression := prefixExpression{
expression: expression, expression: expression,
operator: operator, operator: operator,
@ -131,13 +136,13 @@ func newPrefixExpression(expression Expression, operator string) prefixExpressio
return prefixExpression return prefixExpression
} }
func (p *prefixExpression) Serialize(out *queryData, options ...serializeOption) error { func (p *prefixExpression) serialize(out *queryData) error {
out.WriteString(p.operator + " ") out.WriteString(p.operator + " ")
if p.expression == nil { if p.expression == nil {
return errors.Newf("nil prefix expression.") return errors.Newf("nil prefix expression.")
} }
if err := p.expression.Serialize(out); err != nil { if err := p.expression.serialize(out); err != nil {
return err return err
} }

View file

@ -14,7 +14,7 @@ type intervalExpression struct {
const intervalSep = ":" const intervalSep = ":"
func (c *intervalExpression) Serialize(out *queryData, options ...serializeOption) error { func (c *intervalExpression) serialize(out *queryData) error {
out.WriteString("INTERVAL '") out.WriteString("INTERVAL '")
duration := c.duration duration := c.duration
@ -42,7 +42,7 @@ func (c *intervalExpression) Serialize(out *queryData, options ...serializeOptio
} }
//// Interval returns a representation of duration //// Interval returns a representation of duration
//func Interval(duration time.Duration) Expression { //func Interval(duration time.Duration) expression {
// intervalExp := &intervalExpression{ // intervalExp := &intervalExpression{
// duration: duration, // duration: duration,
// } // }

View file

@ -19,7 +19,7 @@ func (s *ExprSuite) TestConjunctExprEmptyList(c *gc.C) {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
err := expr.Serialize(buf) err := expr.serialize(buf)
c.Assert(err, gc.NotNil) c.Assert(err, gc.NotNil)
} }
@ -28,7 +28,7 @@ func (s *ExprSuite) TestConjunctExprNilInList(c *gc.C) {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
err := expr.Serialize(buf) err := expr.serialize(buf)
c.Assert(err, gc.NotNil) c.Assert(err, gc.NotNil)
} }
@ -37,7 +37,7 @@ func (s *ExprSuite) TestConjunctExprSingleElement(c *gc.C) {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
err := expr.Serialize(buf) err := expr.serialize(buf)
c.Assert(err, gc.IsNil) c.Assert(err, gc.IsNil)
sql := buf.String() sql := buf.String()
@ -49,7 +49,7 @@ func (s *ExprSuite) TestLikeExpr(c *gc.C) {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
err := expr.Serialize(buf) err := expr.serialize(buf)
c.Assert(err, gc.IsNil) c.Assert(err, gc.IsNil)
sql := buf.String() sql := buf.String()
@ -65,7 +65,7 @@ func (s *ExprSuite) TestRegexExpr(c *gc.C) {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
err := expr.Serialize(buf) err := expr.serialize(buf)
c.Assert(err, gc.IsNil) c.Assert(err, gc.IsNil)
sql := buf.String() sql := buf.String()
@ -81,7 +81,7 @@ func (s *ExprSuite) TestAndExpr(c *gc.C) {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
err := expr.Serialize(buf) err := expr.serialize(buf)
c.Assert(err, gc.IsNil) c.Assert(err, gc.IsNil)
sql := buf.String() sql := buf.String()
@ -96,7 +96,7 @@ func (s *ExprSuite) TestOrExpr(c *gc.C) {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
err := expr.Serialize(buf) err := expr.serialize(buf)
c.Assert(err, gc.IsNil) c.Assert(err, gc.IsNil)
sql := buf.String() sql := buf.String()
@ -159,7 +159,7 @@ func (s *ExprSuite) TestBinaryExprNilLHS(c *gc.C) {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
err := expr.Serialize(buf) err := expr.serialize(buf)
c.Assert(err, gc.NotNil) c.Assert(err, gc.NotNil)
} }
@ -168,7 +168,7 @@ func (s *ExprSuite) TestNegateExpr(c *gc.C) {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
err := expr.Serialize(buf) err := expr.serialize(buf)
c.Assert(err, gc.IsNil) c.Assert(err, gc.IsNil)
sql := buf.String() sql := buf.String()
@ -180,7 +180,7 @@ func (s *ExprSuite) TestBinaryExprNilRHS(c *gc.C) {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
err := expr.Serialize(buf) err := expr.serialize(buf)
c.Assert(err, gc.NotNil) c.Assert(err, gc.NotNil)
} }
@ -189,7 +189,7 @@ func (s *ExprSuite) TestEqExpr(c *gc.C) {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
err := expr.Serialize(buf) err := expr.serialize(buf)
c.Assert(err, gc.IsNil) c.Assert(err, gc.IsNil)
sql := buf.String() sql := buf.String()
@ -201,7 +201,7 @@ func (s *ExprSuite) TestEqExprNilLHS(c *gc.C) {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
err := expr.Serialize(buf) err := expr.serialize(buf)
c.Assert(err, gc.IsNil) c.Assert(err, gc.IsNil)
sql := buf.String() sql := buf.String()
@ -213,7 +213,7 @@ func (s *ExprSuite) TestNeqExpr(c *gc.C) {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
err := expr.Serialize(buf) err := expr.serialize(buf)
c.Assert(err, gc.IsNil) c.Assert(err, gc.IsNil)
sql := buf.String() sql := buf.String()
@ -225,7 +225,7 @@ func (s *ExprSuite) TestNeqExprNilLHS(c *gc.C) {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
err := expr.Serialize(buf) err := expr.serialize(buf)
c.Assert(err, gc.IsNil) c.Assert(err, gc.IsNil)
sql := buf.String() sql := buf.String()
@ -237,7 +237,7 @@ func (s *ExprSuite) TestLtExpr(c *gc.C) {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
err := expr.Serialize(buf) err := expr.serialize(buf)
c.Assert(err, gc.IsNil) c.Assert(err, gc.IsNil)
sql := buf.String() sql := buf.String()
@ -249,7 +249,7 @@ func (s *ExprSuite) TestLteExpr(c *gc.C) {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
err := expr.Serialize(buf) err := expr.serialize(buf)
c.Assert(err, gc.IsNil) c.Assert(err, gc.IsNil)
sql := buf.String() sql := buf.String()
@ -264,7 +264,7 @@ func (s *ExprSuite) TestGtExpr(c *gc.C) {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
err := expr.Serialize(buf) err := expr.serialize(buf)
c.Assert(err, gc.IsNil) c.Assert(err, gc.IsNil)
sql := buf.String() sql := buf.String()
@ -276,7 +276,7 @@ func (s *ExprSuite) TestGteExpr(c *gc.C) {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
err := expr.Serialize(buf) err := expr.serialize(buf)
c.Assert(err, gc.IsNil) c.Assert(err, gc.IsNil)
sql := buf.String() sql := buf.String()
@ -343,20 +343,20 @@ func (s *ExprSuite) TestSqlFuncExprNonEmptyArgList(c *gc.C) {
} }
func (s *ExprSuite) TestOrderByClauseNilExpr(c *gc.C) { func (s *ExprSuite) TestOrderByClauseNilExpr(c *gc.C) {
clause := Asc(nil) clause := ASC(nil)
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
err := clause.Serialize(buf) err := clause.serialize(buf)
c.Assert(err, gc.NotNil) c.Assert(err, gc.NotNil)
} }
func (s *ExprSuite) TestAsc(c *gc.C) { func (s *ExprSuite) TestAsc(c *gc.C) {
clause := Asc(table1Col1) clause := ASC(table1Col1)
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
err := clause.Serialize(buf) err := clause.serialize(buf)
c.Assert(err, gc.IsNil) c.Assert(err, gc.IsNil)
sql := buf.String() sql := buf.String()
@ -364,11 +364,11 @@ func (s *ExprSuite) TestAsc(c *gc.C) {
} }
func (s *ExprSuite) TestDesc(c *gc.C) { func (s *ExprSuite) TestDesc(c *gc.C) {
clause := Desc(table1Col1) clause := DESC(table1Col1)
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
err := clause.Serialize(buf) err := clause.serialize(buf)
c.Assert(err, gc.IsNil) c.Assert(err, gc.IsNil)
sql := buf.String() sql := buf.String()

View file

@ -1,16 +1,16 @@
package sqlbuilder package sqlbuilder
type ExpressionTable interface { 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 statement expression
columns []Column columns []column
alias string alias string
} }
@ -23,7 +23,7 @@ func (s *expressionTableImpl) TableName() string {
return s.alias return s.alias
} }
func (s *expressionTableImpl) Columns() []Column { func (s *expressionTableImpl) Columns() []column {
return s.columns return s.columns
} }
@ -34,22 +34,22 @@ func (s *expressionTableImpl) RefIntColumnName(name string) *IntegerColumn {
return intColumn return intColumn
} }
func (s *expressionTableImpl) RefIntColumn(column Column) *IntegerColumn { func (s *expressionTableImpl) RefIntColumn(column column) *IntegerColumn {
intColumn := NewIntegerColumn(column.TableName()+"."+column.Name(), NotNullable) intColumn := NewIntegerColumn(column.TableName()+"."+column.Name(), NotNullable)
intColumn.setTableName(s.alias) intColumn.setTableName(s.alias)
return intColumn return intColumn
} }
func (s *expressionTableImpl) RefStringColumn(column Column) *StringColumn { func (s *expressionTableImpl) RefStringColumn(column column) *StringColumn {
strColumn := NewStringColumn(column.Name(), NotNullable) strColumn := NewStringColumn(column.Name(), NotNullable)
strColumn.setTableName(column.TableName()) strColumn.setTableName(column.TableName())
return strColumn return strColumn
} }
func (s *expressionTableImpl) SerializeSql(out *queryData) error { func (s *expressionTableImpl) serializeSql(out *queryData) error {
out.WriteString("( ") out.WriteString("( ")
err := s.statement.Serialize(out) err := s.statement.serialize(out)
if err != nil { if err != nil {
return err return err
@ -62,33 +62,33 @@ func (s *expressionTableImpl) SerializeSql(out *queryData) error {
} }
// Generates a select query on the current tableName. // Generates a select query on the current tableName.
func (s *expressionTableImpl) SELECT(projections ...Projection) SelectStatement { func (s *expressionTableImpl) SELECT(projections ...projection) selectStatement {
return newSelectStatement(s, projections) return newSelectStatement(s, projections)
} }
// Creates a inner join tableName expression using onCondition. // Creates a inner join tableName expression using onCondition.
func (s *expressionTableImpl) INNER_JOIN(table ReadableTable, onCondition BoolExpression) ReadableTable { func (s *expressionTableImpl) INNER_JOIN(table readableTable, onCondition boolExpression) readableTable {
return InnerJoinOn(s, table, onCondition) return InnerJoinOn(s, table, onCondition)
} }
//func (s *expressionTableImpl) InnerJoinUsing(table ReadableTable, col1 Column, col2 Column) ReadableTable { //func (s *expressionTableImpl) InnerJoinUsing(table readableTable, col1 column, col2 column) readableTable {
// return INNER_JOIN(s, table, col1.Eq(col2)) // return INNER_JOIN(s, table, col1.Eq(col2))
//} //}
// Creates a left join tableName expression using onCondition. // Creates a left join tableName expression using onCondition.
func (s *expressionTableImpl) LEFT_JOIN(table ReadableTable, onCondition BoolExpression) ReadableTable { func (s *expressionTableImpl) LEFT_JOIN(table readableTable, onCondition boolExpression) readableTable {
return LeftJoinOn(s, table, onCondition) return LeftJoinOn(s, table, onCondition)
} }
// Creates a right join tableName expression using onCondition. // Creates a right join tableName expression using onCondition.
func (s *expressionTableImpl) RIGHT_JOIN(table ReadableTable, onCondition BoolExpression) ReadableTable { func (s *expressionTableImpl) RIGHT_JOIN(table readableTable, onCondition boolExpression) readableTable {
return RightJoinOn(s, table, onCondition) return RightJoinOn(s, table, onCondition)
} }
func (s *expressionTableImpl) FULL_JOIN(table ReadableTable, onCondition BoolExpression) ReadableTable { func (s *expressionTableImpl) FULL_JOIN(table readableTable, onCondition boolExpression) readableTable {
return FullJoin(s, table, onCondition) return FullJoin(s, table, onCondition)
} }
func (s *expressionTableImpl) CROSS_JOIN(table ReadableTable) ReadableTable { func (s *expressionTableImpl) CROSS_JOIN(table readableTable) readableTable {
return CrossJoin(s, table) return CrossJoin(s, table)
} }

View file

@ -6,14 +6,14 @@ type funcExpressionImpl struct {
expressionInterfaceImpl expressionInterfaceImpl
name string name string
expression []Expression expression []expression
} }
func ROW(expressions ...Expression) Expression { func ROW(expressions ...expression) expression {
return newFunc("ROW", expressions, nil) return newFunc("ROW", expressions, nil)
} }
func newFunc(name string, expressions []Expression, parent Expression) *funcExpressionImpl { func newFunc(name string, expressions []expression, parent expression) *funcExpressionImpl {
funcExp := &funcExpressionImpl{ funcExp := &funcExpressionImpl{
name: name, name: name,
expression: expressions, expression: expressions,
@ -28,7 +28,7 @@ func newFunc(name string, expressions []Expression, parent Expression) *funcExpr
return funcExp return funcExp
} }
func (f *funcExpressionImpl) Serialize(out *queryData, options ...serializeOption) error { func (f *funcExpressionImpl) serialize(out *queryData) error {
out.WriteString(f.name) out.WriteString(f.name)
out.WriteString("(") out.WriteString("(")
err := serializeExpressionList(f.expression, ", ", out) err := serializeExpressionList(f.expression, ", ", out)
@ -45,7 +45,7 @@ type numericFunc struct {
numericInterfaceImpl numericInterfaceImpl
} }
func NewNumericFunc(name string, expressions ...Expression) NumericExpression { func NewNumericFunc(name string, expressions ...expression) numericExpression {
numericFunc := &numericFunc{} numericFunc := &numericFunc{}
numericFunc.funcExpressionImpl = *newFunc(name, expressions, numericFunc) numericFunc.funcExpressionImpl = *newFunc(name, expressions, numericFunc)
@ -55,35 +55,35 @@ func NewNumericFunc(name string, expressions ...Expression) NumericExpression {
} }
//func (f *FuncExpression) SerializeSqlForColumnList(out *bytes.Buffer) error { //func (f *FuncExpression) SerializeSqlForColumnList(out *bytes.Buffer) error {
// return f.Serialize(out) // return f.serialize(out)
//} //}
func MAX(expression NumericExpression) NumericExpression { func MAX(expression numericExpression) numericExpression {
return NewNumericFunc("MAX", expression) return NewNumericFunc("MAX", expression)
} }
func SUM(expression NumericExpression) NumericExpression { func SUM(expression numericExpression) numericExpression {
return NewNumericFunc("SUM", expression) return NewNumericFunc("SUM", expression)
} }
type caseInterface interface { type caseInterface interface {
Expression expression
WHEN(condition Expression) caseInterface WHEN(condition expression) caseInterface
THEN(then Expression) caseInterface THEN(then expression) caseInterface
ELSE(els Expression) caseInterface ELSE(els expression) caseInterface
} }
type caseExpression struct { type caseExpression struct {
expressionInterfaceImpl expressionInterfaceImpl
expression Expression expression expression
when []Expression when []expression
then []Expression then []expression
els Expression els expression
} }
func CASE(expression ...Expression) caseInterface { func CASE(expression ...expression) caseInterface {
caseExp := &caseExpression{} caseExp := &caseExpression{}
if len(expression) == 1 { if len(expression) == 1 {
@ -95,28 +95,28 @@ func CASE(expression ...Expression) caseInterface {
return caseExp return caseExp
} }
func (c *caseExpression) WHEN(when Expression) caseInterface { func (c *caseExpression) WHEN(when expression) caseInterface {
c.when = append(c.when, when) c.when = append(c.when, when)
return c return c
} }
func (c *caseExpression) THEN(then Expression) caseInterface { func (c *caseExpression) THEN(then expression) caseInterface {
c.then = append(c.then, then) c.then = append(c.then, then)
return c return c
} }
func (c *caseExpression) ELSE(els Expression) caseInterface { func (c *caseExpression) ELSE(els expression) caseInterface {
c.els = els c.els = els
return c return c
} }
func (c *caseExpression) Serialize(out *queryData, options ...serializeOption) error { func (c *caseExpression) serialize(out *queryData) error {
out.WriteString("(CASE") out.WriteString("(CASE")
if c.expression != nil { if c.expression != nil {
out.WriteString(" ") out.WriteString(" ")
err := c.expression.Serialize(out) err := c.expression.serialize(out)
if err != nil { if err != nil {
return err return err
@ -133,14 +133,14 @@ func (c *caseExpression) Serialize(out *queryData, options ...serializeOption) e
for i, when := range c.when { for i, when := range c.when {
out.WriteString(" WHEN ") out.WriteString(" WHEN ")
err := when.Serialize(out) err := when.serialize(out)
if err != nil { if err != nil {
return err return err
} }
out.WriteString(" THEN ") out.WriteString(" THEN ")
err = c.then[i].Serialize(out) err = c.then[i].serialize(out)
if err != nil { if err != nil {
return err return err
@ -149,7 +149,7 @@ func (c *caseExpression) Serialize(out *queryData, options ...serializeOption) e
if c.els != nil { if c.els != nil {
out.WriteString(" ELSE ") out.WriteString(" ELSE ")
err := c.els.Serialize(out) err := c.els.serialize(out)
if err != nil { if err != nil {
return err return err

View file

@ -12,7 +12,7 @@ func TestCase1(t *testing.T) {
queryData := &queryData{} queryData := &queryData{}
err := query.Serialize(queryData) err := query.serialize(queryData)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, queryData.buff.String(), `(CASE WHEN table3.col1 = $1 THEN table3.col1 + $2 WHEN table3.col1 = $3 THEN table3.col1 + $4 END)`) assert.Equal(t, queryData.buff.String(), `(CASE WHEN table3.col1 = $1 THEN table3.col1 + $2 WHEN table3.col1 = $3 THEN table3.col1 + $4 END)`)
@ -26,7 +26,7 @@ func TestCase2(t *testing.T) {
queryData := &queryData{} queryData := &queryData{}
err := query.Serialize(queryData) err := query.serialize(queryData)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, queryData.buff.String(), `(CASE table3.col1 WHEN $1 THEN table3.col1 + $2 WHEN $3 THEN table3.col1 + $4 ELSE $5 END)`) assert.Equal(t, queryData.buff.String(), `(CASE table3.col1 WHEN $1 THEN table3.col1 + $2 WHEN $3 THEN table3.col1 + $4 ELSE $5 END)`)
@ -37,7 +37,7 @@ func TestInterval(t *testing.T) {
queryData := &queryData{} queryData := &queryData{}
err := query.Serialize(queryData) err := query.serialize(queryData)
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, queryData.buff.String(), `INTERVAL $1`) assert.Equal(t, queryData.buff.String(), `INTERVAL $1`)

View file

@ -0,0 +1,7 @@
package sqlbuilder
type groupByClause interface {
serializeForGroupBy(out *queryData) error
}
// TODO: GROUPING SETS, CUBE, and ROLLUP

View file

@ -9,20 +9,20 @@ import (
"strings" "strings"
) )
type InsertStatement interface { type insertStatement interface {
Statement statement
// Add a row of values to the insert statement. // Add a row of values to the insert statement.
VALUES(values ...interface{}) InsertStatement VALUES(values ...interface{}) insertStatement
// Map or stracture mapped to column names // Map or stracture mapped to column names
VALUES_MAPPING(data interface{}) InsertStatement VALUES_MAPPING(data interface{}) insertStatement
RETURNING(projections ...Projection) InsertStatement RETURNING(projections ...projection) insertStatement
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,11 +30,11 @@ 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
errors []string errors []string
} }
@ -48,15 +48,15 @@ func (u *insertStatementImpl) Execute(db types.Db) (res sql.Result, err error) {
} }
// expression or default keyword // expression or default keyword
func (s *insertStatementImpl) VALUES(values ...interface{}) InsertStatement { func (s *insertStatementImpl) VALUES(values ...interface{}) insertStatement {
if len(values) == 0 { if len(values) == 0 {
return s return s
} }
literalRow := []Clause{} literalRow := []clause{}
for _, value := range values { for _, value := range values {
if clause, ok := value.(Clause); ok { if clause, ok := value.(clause); ok {
literalRow = append(literalRow, clause) literalRow = append(literalRow, clause)
} else { } else {
literalRow = append(literalRow, Literal(value)) literalRow = append(literalRow, Literal(value))
@ -67,7 +67,7 @@ func (s *insertStatementImpl) VALUES(values ...interface{}) InsertStatement {
return s return s
} }
func (i *insertStatementImpl) VALUES_MAPPING(data interface{}) InsertStatement { func (i *insertStatementImpl) VALUES_MAPPING(data interface{}) insertStatement {
if data == nil { if data == nil {
i.addError("Add method data is nil.") i.addError("Add method data is nil.")
return i return i
@ -84,7 +84,7 @@ func (i *insertStatementImpl) VALUES_MAPPING(data interface{}) InsertStatement {
return i return i
} }
rowValues := []Clause{} rowValues := []clause{}
for _, column := range i.columns { for _, column := range i.columns {
columnName := column.Name() columnName := column.Name()
@ -105,13 +105,13 @@ func (i *insertStatementImpl) VALUES_MAPPING(data interface{}) InsertStatement {
return i return i
} }
func (i *insertStatementImpl) RETURNING(projections ...Projection) InsertStatement { func (i *insertStatementImpl) RETURNING(projections ...projection) insertStatement {
i.returning = defaultProjectionAliasing(projections) i.returning = defaultProjectionAliasing(projections)
return i return i
} }
func (i *insertStatementImpl) QUERY(selectStatement SelectStatement) InsertStatement { func (i *insertStatementImpl) QUERY(selectStatement selectStatement) insertStatement {
i.query = selectStatement i.query = selectStatement
return i return i
@ -134,7 +134,7 @@ func (s *insertStatementImpl) Sql() (sql string, args []interface{}, err error)
return "", nil, errors.Newf("nil tableName.") return "", nil, errors.Newf("nil tableName.")
} }
err = s.table.SerializeSql(queryData) err = s.table.serializeSql(queryData)
if err != nil { if err != nil {
return "", nil, err return "", nil, err
@ -182,7 +182,7 @@ func (s *insertStatementImpl) Sql() (sql string, args []interface{}, err error)
} }
if s.query != nil { if s.query != nil {
err = s.query.Serialize(queryData) err = s.query.serialize(queryData)
if err != nil { if err != nil {
return return

View file

@ -1,42 +1,42 @@
package sqlbuilder package sqlbuilder
type IntegerExpression interface { type integerExpression interface {
NumericExpression numericExpression
//AddInt(value int) IntegerExpression //AddInt(value int) integerExpression
//AddInt64(value int) IntegerExpression //AddInt64(value int) integerExpression
BitAnd(expression IntegerExpression) IntegerExpression BitAnd(expression integerExpression) integerExpression
BitOr(expression IntegerExpression) IntegerExpression BitOr(expression integerExpression) integerExpression
BitXor(expression IntegerExpression) IntegerExpression BitXor(expression integerExpression) integerExpression
BitNot() IntegerExpression BitNot() integerExpression
} }
type integerInterfaceImpl struct { type integerInterfaceImpl struct {
parent IntegerExpression parent integerExpression
} }
//func (i *integerInterfaceImpl) AddInt(expression IntegerExpression) IntegerExpression { //func (i *integerInterfaceImpl) AddInt(expression integerExpression) integerExpression {
// return NewBinaryIntegerExpression(i.parent, expression, " & ") // return NewBinaryIntegerExpression(i.parent, expression, " & ")
//} //}
// //
//func (i *integerInterfaceImpl) AddInt64(expression IntegerExpression) IntegerExpression { //func (i *integerInterfaceImpl) AddInt64(expression integerExpression) integerExpression {
// return NewBinaryIntegerExpression(i.parent, expression, " & ") // return NewBinaryIntegerExpression(i.parent, expression, " & ")
//} //}
func (i *integerInterfaceImpl) BitAnd(expression IntegerExpression) IntegerExpression { func (i *integerInterfaceImpl) BitAnd(expression integerExpression) integerExpression {
return NewBinaryIntegerExpression(i.parent, expression, " & ") return NewBinaryIntegerExpression(i.parent, expression, " & ")
} }
func (i *integerInterfaceImpl) BitOr(expression IntegerExpression) IntegerExpression { func (i *integerInterfaceImpl) BitOr(expression integerExpression) integerExpression {
return NewBinaryIntegerExpression(i.parent, expression, " | ") return NewBinaryIntegerExpression(i.parent, expression, " | ")
} }
func (i *integerInterfaceImpl) BitXor(expression IntegerExpression) IntegerExpression { func (i *integerInterfaceImpl) BitXor(expression integerExpression) integerExpression {
return NewBinaryIntegerExpression(i.parent, expression, " # ") return NewBinaryIntegerExpression(i.parent, expression, " # ")
} }
func (i *integerInterfaceImpl) BitNot() IntegerExpression { func (i *integerInterfaceImpl) BitNot() integerExpression {
return NewPrefixIntegerExpression(i.parent, " ~") return NewPrefixIntegerExpression(i.parent, " ~")
} }
@ -49,7 +49,7 @@ type binaryIntegerExpression struct {
binaryExpression binaryExpression
} }
func NewBinaryIntegerExpression(lhs, rhs IntegerExpression, operator string) IntegerExpression { func NewBinaryIntegerExpression(lhs, rhs integerExpression, operator string) integerExpression {
integerExpression := binaryIntegerExpression{} integerExpression := binaryIntegerExpression{}
integerExpression.expressionInterfaceImpl.parent = &integerExpression integerExpression.expressionInterfaceImpl.parent = &integerExpression
@ -70,7 +70,7 @@ type prefixIntegerExpression struct {
prefixExpression prefixExpression
} }
func NewPrefixIntegerExpression(expression IntegerExpression, operator string) IntegerExpression { func NewPrefixIntegerExpression(expression integerExpression, operator string) integerExpression {
integerExpression := prefixIntegerExpression{} integerExpression := prefixIntegerExpression{}
integerExpression.prefixExpression = newPrefixExpression(expression, operator) integerExpression.prefixExpression = newPrefixExpression(expression, operator)

View file

@ -6,7 +6,7 @@ const (
type keywordClause string type keywordClause string
func (k keywordClause) Serialize(out *queryData, options ...serializeOption) error { func (k keywordClause) serialize(out *queryData) error {
out.WriteString(string(k)) out.WriteString(string(k))
return nil return nil

View file

@ -13,7 +13,7 @@ func Literal(value interface{}) *literalExpression {
return &exp return &exp
} }
func (l literalExpression) Serialize(out *queryData, options ...serializeOption) error { func (l literalExpression) serialize(out *queryData) error {
out.InsertArgument(l.value) out.InsertArgument(l.value)
return nil return nil
@ -24,7 +24,7 @@ type numLiteralExpression struct {
numericInterfaceImpl numericInterfaceImpl
} }
func IntLiteral(value int) NumericExpression { func IntLiteral(value int) numericExpression {
numLiteral := &numLiteralExpression{} numLiteral := &numLiteralExpression{}
numLiteral.literalExpression = *Literal(value) numLiteral.literalExpression = *Literal(value)

View file

@ -20,7 +20,7 @@ const (
) )
type lockStatement interface { type lockStatement interface {
Statement statement
IN(lockMode lockMode) lockStatement IN(lockMode lockMode) lockStatement
NOWAIT() lockStatement NOWAIT() lockStatement
@ -66,7 +66,7 @@ func (l *lockStatementImpl) Sql() (query string, args []interface{}, err error)
out.WriteString(", ") out.WriteString(", ")
} }
err := table.SerializeSql(out) err := table.serializeSql(out)
if err != nil { if err != nil {
return "", nil, err return "", nil, err

View file

@ -1,79 +1,79 @@
package sqlbuilder package sqlbuilder
type NumericExpression interface { type numericExpression interface {
Expression expression
Eq(expression NumericExpression) BoolExpression Eq(expression numericExpression) boolExpression
EqL(literal interface{}) BoolExpression EqL(literal interface{}) boolExpression
NotEq(expression NumericExpression) BoolExpression NotEq(expression numericExpression) boolExpression
NotEqL(literal interface{}) BoolExpression NotEqL(literal interface{}) boolExpression
Gt(rhs NumericExpression) BoolExpression Gt(rhs numericExpression) boolExpression
GtEq(rhs NumericExpression) BoolExpression GtEq(rhs numericExpression) boolExpression
GtEqL(literal interface{}) BoolExpression GtEqL(literal interface{}) boolExpression
LtEq(rhs NumericExpression) BoolExpression LtEq(rhs numericExpression) boolExpression
LtEqL(literal interface{}) BoolExpression LtEqL(literal interface{}) boolExpression
Add(expression NumericExpression) NumericExpression Add(expression numericExpression) numericExpression
Sub(expression NumericExpression) NumericExpression Sub(expression numericExpression) numericExpression
Mul(expression NumericExpression) NumericExpression Mul(expression numericExpression) numericExpression
Div(expression NumericExpression) NumericExpression Div(expression numericExpression) numericExpression
} }
type numericInterfaceImpl struct { type numericInterfaceImpl struct {
parent NumericExpression parent numericExpression
} }
func (n *numericInterfaceImpl) Eq(expression NumericExpression) BoolExpression { func (n *numericInterfaceImpl) Eq(expression numericExpression) boolExpression {
return Eq(n.parent, expression) return Eq(n.parent, expression)
} }
func (n *numericInterfaceImpl) EqL(literal interface{}) BoolExpression { func (n *numericInterfaceImpl) EqL(literal interface{}) boolExpression {
return Eq(n.parent, Literal(literal)) return Eq(n.parent, Literal(literal))
} }
func (n *numericInterfaceImpl) NotEq(expression NumericExpression) BoolExpression { func (n *numericInterfaceImpl) NotEq(expression numericExpression) boolExpression {
return NotEq(n.parent, expression) return NotEq(n.parent, expression)
} }
func (n *numericInterfaceImpl) NotEqL(literal interface{}) BoolExpression { func (n *numericInterfaceImpl) NotEqL(literal interface{}) boolExpression {
return NotEq(n.parent, Literal(literal)) return NotEq(n.parent, Literal(literal))
} }
func (n *numericInterfaceImpl) Gt(expression NumericExpression) BoolExpression { func (n *numericInterfaceImpl) Gt(expression numericExpression) boolExpression {
return Gt(n.parent, expression) return Gt(n.parent, expression)
} }
func (n *numericInterfaceImpl) GtEq(expression NumericExpression) BoolExpression { func (n *numericInterfaceImpl) GtEq(expression numericExpression) boolExpression {
return GtEq(n.parent, expression) return GtEq(n.parent, expression)
} }
func (n *numericInterfaceImpl) GtEqL(literal interface{}) BoolExpression { func (n *numericInterfaceImpl) GtEqL(literal interface{}) boolExpression {
return GtEq(n.parent, Literal(literal)) return GtEq(n.parent, Literal(literal))
} }
func (n *numericInterfaceImpl) LtEq(expression NumericExpression) BoolExpression { func (n *numericInterfaceImpl) LtEq(expression numericExpression) boolExpression {
return LtEq(n.parent, expression) return LtEq(n.parent, expression)
} }
func (n *numericInterfaceImpl) LtEqL(literal interface{}) BoolExpression { func (n *numericInterfaceImpl) LtEqL(literal interface{}) boolExpression {
return LtEq(n.parent, Literal(literal)) return LtEq(n.parent, Literal(literal))
} }
func (n *numericInterfaceImpl) Add(expression NumericExpression) NumericExpression { func (n *numericInterfaceImpl) Add(expression numericExpression) numericExpression {
return newBinaryNumericExpression(n.parent, expression, "+") return newBinaryNumericExpression(n.parent, expression, "+")
} }
func (n *numericInterfaceImpl) Sub(expression NumericExpression) NumericExpression { func (n *numericInterfaceImpl) Sub(expression numericExpression) numericExpression {
return newBinaryNumericExpression(n.parent, expression, "-") return newBinaryNumericExpression(n.parent, expression, "-")
} }
func (n *numericInterfaceImpl) Mul(expression NumericExpression) NumericExpression { func (n *numericInterfaceImpl) Mul(expression numericExpression) numericExpression {
return newBinaryNumericExpression(n.parent, expression, "*") return newBinaryNumericExpression(n.parent, expression, "*")
} }
func (n *numericInterfaceImpl) Div(expression NumericExpression) NumericExpression { func (n *numericInterfaceImpl) Div(expression numericExpression) numericExpression {
return newBinaryNumericExpression(n.parent, expression, "/") return newBinaryNumericExpression(n.parent, expression, "/")
} }
@ -83,7 +83,7 @@ type numericLiteral struct {
literalExpression literalExpression
} }
func NewNumericLiteral(value interface{}) NumericExpression { func NewNumericLiteral(value interface{}) numericExpression {
numericLiteral := numericLiteral{} numericLiteral := numericLiteral{}
numericLiteral.literalExpression = *Literal(value) numericLiteral.literalExpression = *Literal(value)
@ -100,7 +100,7 @@ type binaryNumericExpression struct {
binaryExpression binaryExpression
} }
func newBinaryNumericExpression(lhs, rhs Expression, operator string) NumericExpression { func newBinaryNumericExpression(lhs, rhs expression, operator string) numericExpression {
numericExpression := binaryNumericExpression{} numericExpression := binaryNumericExpression{}
numericExpression.binaryExpression = newBinaryExpression(lhs, rhs, operator) numericExpression.binaryExpression = newBinaryExpression(lhs, rhs, operator)
@ -116,10 +116,10 @@ type numericExpressionWrapper struct {
expressionInterfaceImpl expressionInterfaceImpl
numericInterfaceImpl numericInterfaceImpl
expression Expression expression expression
} }
func newNumericExpressionWrap(expression Expression) NumericExpression { func newNumericExpressionWrap(expression expression) numericExpression {
numericExpressionWrap := numericExpressionWrapper{} numericExpressionWrap := numericExpressionWrapper{}
numericExpressionWrap.expression = expression numericExpressionWrap.expression = expression
@ -130,9 +130,9 @@ func newNumericExpressionWrap(expression Expression) NumericExpression {
return &numericExpressionWrap return &numericExpressionWrap
} }
func (c *numericExpressionWrapper) Serialize(out *queryData, options ...serializeOption) error { func (c *numericExpressionWrapper) serialize(out *queryData) error {
out.WriteString("(") out.WriteString("(")
err := c.expression.Serialize(out, options...) err := c.expression.serialize(out)
out.WriteString(")") out.WriteString(")")
return err return err

View file

@ -2,8 +2,8 @@ package sqlbuilder
import "github.com/dropbox/godropbox/errors" import "github.com/dropbox/godropbox/errors"
type OrderByClause interface { type orderByClause interface {
Clause clause
isOrderByClauseType() isOrderByClauseType()
} }
@ -13,27 +13,18 @@ type isOrderByClause struct {
func (o *isOrderByClause) isOrderByClauseType() { func (o *isOrderByClause) isOrderByClauseType() {
} }
type ColumnNameOrderBy string type orderByClauseImpl struct {
func (o *ColumnNameOrderBy) isOrderByClauseType() {
}
func (o *ColumnNameOrderBy) Serialize(out *queryData, options ...serializeOption) error {
return nil
}
type orderByClause struct {
isOrderByClause isOrderByClause
expression Expression expression expression
ascent bool ascent bool
} }
func (o *orderByClause) Serialize(out *queryData, options ...serializeOption) error { func (o *orderByClauseImpl) serialize(out *queryData) error {
if o.expression == nil { if o.expression == nil {
return errors.Newf("nil orderBy by clause.") return errors.Newf("nil orderBy by clause.")
} }
if err := o.expression.Serialize(out); err != nil { if err := o.expression.serialize(out); err != nil {
return err return err
} }
@ -46,10 +37,10 @@ func (o *orderByClause) Serialize(out *queryData, options ...serializeOption) er
return nil return nil
} }
func Asc(expression Expression) OrderByClause { func ASC(expression expression) orderByClause {
return &orderByClause{expression: expression, ascent: true} return &orderByClauseImpl{expression: expression, ascent: true}
} }
func Desc(expression Expression) OrderByClause { func DESC(expression expression) orderByClause {
return &orderByClause{expression: expression, ascent: false} return &orderByClauseImpl{expression: expression, ascent: false}
} }

View file

@ -1,16 +1,18 @@
package sqlbuilder package sqlbuilder
type Projection interface { type projection interface {
SerializeForProjection(out *queryData) error serializeForProjection(out *queryData) error
} }
//------------------------------------------------------// //------------------------------------------------------//
// Dummy type for select * AllColumns // Dummy type for select * AllColumns
type ColumnList []Column type ColumnList []column
func (cl ColumnList) SerializeForProjection(out *queryData) error { func (cl ColumnList) isProjectionType() {}
func (cl ColumnList) serializeForProjection(out *queryData) error {
for i, column := range cl { for i, column := range cl {
err := column.Serialize(out, FOR_PROJECTION) err := column.serializeForProjection(out)
if err != nil { if err != nil {
return err return err
@ -23,8 +25,8 @@ func (cl ColumnList) SerializeForProjection(out *queryData) error {
return nil return nil
} }
func (cl ColumnList) DefaultAlias() []Projection { func (cl ColumnList) DefaultAlias() []projection {
newColumnList := []Projection{} newColumnList := []projection{}
for _, column := range cl { for _, column := range cl {
newColumn := column.DefaultAlias() newColumn := column.DefaultAlias()

View file

@ -6,52 +6,52 @@ import (
"github.com/sub0zero/go-sqlbuilder/types" "github.com/sub0zero/go-sqlbuilder/types"
) )
type SelectStatement interface { type selectStatement interface {
Statement statement
Expression expression
DISTINCT() SelectStatement DISTINCT() selectStatement
FROM(table ReadableTable) SelectStatement FROM(table readableTable) selectStatement
WHERE(expression BoolExpression) SelectStatement WHERE(expression boolExpression) selectStatement
GROUP_BY(expressions ...Clause) SelectStatement GROUP_BY(groupByClauses ...groupByClause) selectStatement
HAVING(boolExpression BoolExpression) SelectStatement HAVING(boolExpression boolExpression) selectStatement
ORDER_BY(clauses ...OrderByClause) SelectStatement ORDER_BY(orderByClauses ...orderByClause) selectStatement
LIMIT(limit int64) SelectStatement LIMIT(limit int64) selectStatement
OFFSET(offset int64) SelectStatement OFFSET(offset int64) selectStatement
FOR_UPDATE() SelectStatement FOR_UPDATE() selectStatement
AsTable(alias string) ExpressionTable AsTable(alias string) expressionTable
} }
var SELECT = func(projection ...Projection) SelectStatement { var SELECT = func(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 Table interface since
// mysql's subquery performance is horrible. // mysql's subquery performance is horrible.
type selectStatementImpl struct { type selectStatementImpl struct {
expressionInterfaceImpl expressionInterfaceImpl
table ReadableTable table readableTable
distinct bool distinct bool
projections []Projection projections []projection
where BoolExpression where boolExpression
groupBy []Clause //can be ROLLUP, ... so clause for now groupBy []groupByClause
having BoolExpression having boolExpression
orderBy []OrderByClause orderBy []orderByClause
limit, offset int64 limit, offset int64
forUpdate bool forUpdate bool
} }
func defaultProjectionAliasing(projections []Projection) []Projection { 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()...)
@ -63,7 +63,7 @@ func defaultProjectionAliasing(projections []Projection) []Projection {
return aliasedProjections return aliasedProjections
} }
func newSelectStatement(table ReadableTable, projections []Projection) SelectStatement { func newSelectStatement(table readableTable, projections []projection) selectStatement {
newSelect := &selectStatementImpl{ newSelect := &selectStatementImpl{
table: table, table: table,
projections: defaultProjectionAliasing(projections), projections: defaultProjectionAliasing(projections),
@ -78,16 +78,16 @@ func newSelectStatement(table ReadableTable, projections []Projection) SelectSta
return newSelect return newSelect
} }
func (s *selectStatementImpl) FROM(table ReadableTable) SelectStatement { func (s *selectStatementImpl) FROM(table readableTable) selectStatement {
s.table = table s.table = table
return s return s
} }
func (s *selectStatementImpl) Serialize(out *queryData, options ...serializeOption) error { func (s *selectStatementImpl) serialize(out *queryData) error {
out.WriteString("(") out.WriteString("(")
err := s.serializeImpl(out, options...) err := s.serializeImpl(out)
if err != nil { if err != nil {
return err return err
@ -98,7 +98,7 @@ func (s *selectStatementImpl) Serialize(out *queryData, options ...serializeOpti
return nil return nil
} }
func (s *selectStatementImpl) serializeImpl(out *queryData, options ...serializeOption) error { func (s *selectStatementImpl) serializeImpl(out *queryData) error {
out.WriteString("SELECT ") out.WriteString("SELECT ")
out.statementType = select_statement out.statementType = select_statement
@ -123,7 +123,7 @@ func (s *selectStatementImpl) serializeImpl(out *queryData, options ...serialize
return errors.Newf("nil tableName.") return errors.Newf("nil tableName.")
} }
if err := s.table.SerializeSql(out); err != nil { if err := s.table.serializeSql(out); err != nil {
return err return err
} }
@ -189,51 +189,51 @@ func (q *selectStatementImpl) Sql() (query string, args []interface{}, err error
return queryData.buff.String(), queryData.args, nil return queryData.buff.String(), queryData.args, nil
} }
func (s *selectStatementImpl) AsTable(alias string) ExpressionTable { func (s *selectStatementImpl) AsTable(alias string) expressionTable {
return &expressionTableImpl{ return &expressionTableImpl{
statement: s, statement: s,
alias: alias, alias: alias,
} }
} }
func (q *selectStatementImpl) WHERE(expression BoolExpression) SelectStatement { func (q *selectStatementImpl) WHERE(expression boolExpression) selectStatement {
q.where = expression q.where = expression
return q return q
} }
func (s *selectStatementImpl) GROUP_BY(cluases ...Clause) SelectStatement { func (s *selectStatementImpl) GROUP_BY(groupByClauses ...groupByClause) selectStatement {
s.groupBy = cluases s.groupBy = groupByClauses
return s return s
} }
func (q *selectStatementImpl) HAVING(expression BoolExpression) SelectStatement { func (q *selectStatementImpl) HAVING(expression boolExpression) selectStatement {
q.having = expression q.having = expression
return q return q
} }
func (q *selectStatementImpl) ORDER_BY(clauses ...OrderByClause) SelectStatement { func (q *selectStatementImpl) ORDER_BY(clauses ...orderByClause) selectStatement {
q.orderBy = clauses q.orderBy = clauses
return q return q
} }
func (q *selectStatementImpl) OFFSET(offset int64) SelectStatement { func (q *selectStatementImpl) OFFSET(offset int64) selectStatement {
q.offset = offset q.offset = offset
return q return q
} }
func (q *selectStatementImpl) LIMIT(limit int64) SelectStatement { func (q *selectStatementImpl) LIMIT(limit int64) selectStatement {
q.limit = limit q.limit = limit
return q return q
} }
func (q *selectStatementImpl) DISTINCT() SelectStatement { func (q *selectStatementImpl) DISTINCT() selectStatement {
q.distinct = true q.distinct = true
return q return q
} }
func (q *selectStatementImpl) FOR_UPDATE() SelectStatement { func (q *selectStatementImpl) FOR_UPDATE() selectStatement {
q.forUpdate = true q.forUpdate = true
return q return q
} }
@ -246,6 +246,6 @@ func (u *selectStatementImpl) Execute(db types.Db) (res sql.Result, err error) {
return Execute(u, db) return Execute(u, db)
} }
func NumExp(statement SelectStatement) NumericExpression { func NumExp(statement selectStatement) numericExpression {
return newNumericExpressionWrap(statement) return newNumericExpressionWrap(statement)
} }

View file

@ -12,38 +12,38 @@ const (
except = "EXCEPT" except = "EXCEPT"
) )
type SetStatement interface { type setStatement interface {
Statement statement
Expression expression
ORDER_BY(clauses ...OrderByClause) SetStatement ORDER_BY(clauses ...orderByClause) setStatement
LIMIT(limit int64) SetStatement LIMIT(limit int64) setStatement
OFFSET(offset int64) SetStatement OFFSET(offset int64) setStatement
AsTable(alias string) ExpressionTable AsTable(alias string) expressionTable
} }
func UNION(selects ...SelectStatement) SetStatement { func UNION(selects ...selectStatement) setStatement {
return newSetStatementImpl(union, false, selects...) return newSetStatementImpl(union, false, selects...)
} }
func UNION_ALL(selects ...SelectStatement) SetStatement { func UNION_ALL(selects ...selectStatement) setStatement {
return newSetStatementImpl(union, true, selects...) return newSetStatementImpl(union, true, selects...)
} }
func INTERSECT(selects ...SelectStatement) SetStatement { func INTERSECT(selects ...selectStatement) setStatement {
return newSetStatementImpl(intersect, false, selects...) return newSetStatementImpl(intersect, false, selects...)
} }
func INTERSECT_ALL(selects ...SelectStatement) SetStatement { func INTERSECT_ALL(selects ...selectStatement) setStatement {
return newSetStatementImpl(intersect, true, selects...) return newSetStatementImpl(intersect, true, selects...)
} }
func EXCEPT(selects ...SelectStatement) SetStatement { func EXCEPT(selects ...selectStatement) setStatement {
return newSetStatementImpl(except, false, selects...) return newSetStatementImpl(except, false, selects...)
} }
func EXCEPT_ALL(selects ...SelectStatement) SetStatement { func EXCEPT_ALL(selects ...selectStatement) setStatement {
return newSetStatementImpl(except, true, selects...) return newSetStatementImpl(except, true, selects...)
} }
@ -52,14 +52,14 @@ type setStatementImpl struct {
expressionInterfaceImpl expressionInterfaceImpl
operator string operator string
selects []SelectStatement selects []selectStatement
orderBy []OrderByClause orderBy []orderByClause
limit, offset int64 limit, offset int64
// True if results of the union should be deduped. // True if results of the union should be deduped.
all bool all bool
} }
func newSetStatementImpl(operator string, all bool, selects ...SelectStatement) SetStatement { func newSetStatementImpl(operator string, all bool, selects ...selectStatement) setStatement {
setStatement := &setStatementImpl{ setStatement := &setStatementImpl{
operator: operator, operator: operator,
selects: selects, selects: selects,
@ -73,30 +73,30 @@ func newSetStatementImpl(operator string, all bool, selects ...SelectStatement)
return setStatement return setStatement
} }
func (us *setStatementImpl) ORDER_BY(orderBy ...OrderByClause) SetStatement { func (us *setStatementImpl) ORDER_BY(orderBy ...orderByClause) setStatement {
us.orderBy = orderBy us.orderBy = orderBy
return us return us
} }
func (us *setStatementImpl) LIMIT(limit int64) SetStatement { func (us *setStatementImpl) LIMIT(limit int64) setStatement {
us.limit = limit us.limit = limit
return us return us
} }
func (us *setStatementImpl) OFFSET(offset int64) SetStatement { func (us *setStatementImpl) OFFSET(offset int64) setStatement {
us.offset = offset us.offset = offset
return us return us
} }
func (us *setStatementImpl) AsTable(alias string) ExpressionTable { func (us *setStatementImpl) AsTable(alias string) expressionTable {
return &expressionTableImpl{ return &expressionTableImpl{
statement: us, statement: us,
alias: alias, alias: alias,
} }
} }
func (s *setStatementImpl) Serialize(out *queryData, options ...serializeOption) error { func (s *setStatementImpl) serialize(out *queryData) error {
if s.orderBy != nil || s.limit >= 0 || s.offset >= 0 { if s.orderBy != nil || s.limit >= 0 || s.offset >= 0 {
out.WriteString("(") out.WriteString("(")
} }
@ -114,7 +114,7 @@ func (s *setStatementImpl) Serialize(out *queryData, options ...serializeOption)
return nil return nil
} }
func (s *setStatementImpl) serializeImpl(out *queryData, options ...serializeOption) error { func (s *setStatementImpl) serializeImpl(out *queryData) error {
if len(s.selects) < 2 { if len(s.selects) < 2 {
return errors.Newf("UNION statement must have at least two SELECT statements.") return errors.Newf("UNION statement must have at least two SELECT statements.")
@ -131,7 +131,7 @@ func (s *setStatementImpl) serializeImpl(out *queryData, options ...serializeOpt
} }
} }
err := selectStmt.Serialize(out, options...) err := selectStmt.serialize(out)
if err != nil { if err != nil {
return err return err

View file

@ -5,70 +5,10 @@ import (
"github.com/sub0zero/go-sqlbuilder/types" "github.com/sub0zero/go-sqlbuilder/types"
) )
type Statement interface { type statement interface {
// String returns generated SQL as string. // String returns generated SQL as string.
Sql() (query string, args []interface{}, err error) Sql() (query string, args []interface{}, err error)
Query(db types.Db, destination interface{}) error Query(db types.Db, destination interface{}) error
Execute(db types.Db) (sql.Result, error) Execute(db types.Db) (sql.Result, error)
} }
//// SetGtidNextStatement returns a SQL statement that can be used to explicitly set the next GTID.
//type GtidNextStatement interface {
// Statement
//}
//
//// SET GTID_NEXT statement returns a SQL statement that can be used to explicitly set the next GTID.
//func NewGtidNextStatement(sid []byte, gno uint64) GtidNextStatement {
// return &gtidNextStatementImpl{
// sid: sid,
// gno: gno,
// }
//}
//
//type gtidNextStatementImpl struct {
// sid []byte
// gno uint64
//}
//
//func (g *gtidNextStatementImpl) Execute(db *sql.DB, data interface{}) error {
// return nil
//}
//
//func (s *gtidNextStatementImpl) String() (sql string, err error) {
// // This statement sets a session local variable defining what the next transaction ID is. It
// // does not interact with other MySQL sessions. It is neither a DDL nor DML statement, so we
// // don't have to worry about data corruption.
// // Because of the string formatting (hex plus an integer), can't morph into another statement.
// // See: https://dev.mysql.com/doc/refman/5.7/en/replication-options-gtids.html
// const gtidFormatString = "SET GTID_NEXT=\"%x-%x-%x-%x-%x:%d\""
//
// buf := new(bytes.Buffer)
// _, _ = buf.WriteString(fmt.Sprintf(gtidFormatString,
// s.sid[:4], s.sid[4:6], s.sid[6:8], s.sid[8:10], s.sid[10:], s.gno))
// return buf.String(), nil
//}
//
// Util functions =============================================================
//
// Once again, teisenberger is lazy. Here's a quick filter on comments
//var validCommentRegexp *regexp.Regexp = regexp.MustCompile("^[\\w .?]*$")
//
//func isValidComment(comment string) bool {
// return validCommentRegexp.MatchString(comment)
//}
//
//func writeComment(comment string, buf *bytes.Buffer) error {
// if comment != "" {
// _, _ = buf.WriteString("/* ")
// if !isValidComment(comment) {
// return errors.Newf("Invalid comment: %s", comment)
// }
// _, _ = buf.WriteString(comment)
// _, _ = buf.WriteString(" */")
// }
// return nil
//}

View file

@ -157,7 +157,7 @@ func (s *StmtSuite) TestSelectSingleOrderBy(c *gc.C) {
} }
func (s *StmtSuite) TestSelectOrderByAsc(c *gc.C) { func (s *StmtSuite) TestSelectOrderByAsc(c *gc.C) {
q := table1.Select(table1Col1, table1Col2).OrderBy(Asc(table1Col2)) q := table1.Select(table1Col1, table1Col2).OrderBy(ASC(table1Col2))
sql, err := q.String() sql, err := q.String()
c.Assert(err, gc.IsNil) c.Assert(err, gc.IsNil)
@ -169,7 +169,7 @@ func (s *StmtSuite) TestSelectOrderByAsc(c *gc.C) {
} }
func (s *StmtSuite) TestSelectOrderByDesc(c *gc.C) { func (s *StmtSuite) TestSelectOrderByDesc(c *gc.C) {
q := table1.Select(table1Col1, table1Col2).OrderBy(Desc(table1Col2)) q := table1.Select(table1Col1, table1Col2).OrderBy(DESC(table1Col2))
sql, err := q.String() sql, err := q.String()
c.Assert(err, gc.IsNil) c.Assert(err, gc.IsNil)
@ -406,7 +406,7 @@ func (s *StmtSuite) TestUnlockStatement(c *gc.C) {
} }
func (s *StmtSuite) TestUnionSelectStatement(c *gc.C) { func (s *StmtSuite) TestUnionSelectStatement(c *gc.C) {
select_queries := make([]SelectStatement, 0, 3) select_queries := make([]selectStatement, 0, 3)
select_queries = append(select_queries, select_queries = append(select_queries,
table1.Select(table1Col1).Where(GtL(table1Col1, 123)), table1.Select(table1Col1).Where(GtL(table1Col1, 123)),
@ -428,7 +428,7 @@ func (s *StmtSuite) TestUnionSelectStatement(c *gc.C) {
} }
func (s *StmtSuite) TestUnionLimitWithoutOrderBy(c *gc.C) { func (s *StmtSuite) TestUnionLimitWithoutOrderBy(c *gc.C) {
select_queries := make([]SelectStatement, 0, 3) select_queries := make([]selectStatement, 0, 3)
select_queries = append(select_queries, select_queries = append(select_queries,
table1.Select(table1Col1).Where(GtL(table1Col1, 123)).OrderBy(table1Col2), table1.Select(table1Col1).Where(GtL(table1Col1, 123)).OrderBy(table1Col2),
@ -448,7 +448,7 @@ func (s *StmtSuite) TestUnionLimitWithoutOrderBy(c *gc.C) {
} }
func (s *StmtSuite) TestUnionSelectWithMismatchedColumns(c *gc.C) { func (s *StmtSuite) TestUnionSelectWithMismatchedColumns(c *gc.C) {
select_queries := make([]SelectStatement, 0, 3) select_queries := make([]selectStatement, 0, 3)
select_queries = append(select_queries, select_queries = append(select_queries,
@ -463,7 +463,7 @@ func (s *StmtSuite) TestUnionSelectWithMismatchedColumns(c *gc.C) {
q := UNION(select_queries...) q := UNION(select_queries...)
q = q.Where(And(LtL(table1Col1, 1000), GtL(table1Col1, 15))) q = q.Where(And(LtL(table1Col1, 1000), GtL(table1Col1, 15)))
q = q.ORDER_BY(Desc(table1Col4), Asc(table1Col3)) q = q.ORDER_BY(DESC(table1Col4), ASC(table1Col3))
q = q.LIMIT(5) q = q.LIMIT(5)
_, err := q.String() _, err := q.String()
@ -483,7 +483,7 @@ func (s *StmtSuite) TestComplicatedUnionSelectWithWhereStatement(c *gc.C) {
// tests on outer statement: Group By, Order By, LIMIT // tests on outer statement: Group By, Order By, LIMIT
// on inner statement: AndWhere, WHERE (with AND), Order By, LIMIT // on inner statement: AndWhere, WHERE (with AND), Order By, LIMIT
select_queries := make([]SelectStatement, 0, 3) select_queries := make([]selectStatement, 0, 3)
// We're not trying to write a SQL parser, so we won't warn if you do something silly like // We're not trying to write a SQL parser, so we won't warn if you do something silly like
// try to apply a where clause on more columns than you've selected in your union select // try to apply a where clause on more columns than you've selected in your union select
@ -502,7 +502,7 @@ func (s *StmtSuite) TestComplicatedUnionSelectWithWhereStatement(c *gc.C) {
q := UNION(select_queries...) q := UNION(select_queries...)
q = q.Where(And(LtL(table1Col1, 1000), GtL(table1Col1, 15))) q = q.Where(And(LtL(table1Col1, 1000), GtL(table1Col1, 15)))
q = q.ORDER_BY(Desc(table1Col4), Asc(table1Col3)) q = q.ORDER_BY(DESC(table1Col4), ASC(table1Col3))
q = q.LIMIT(5) q = q.LIMIT(5)
q = q.GroupBy(table1Col4) q = q.GroupBy(table1Col4)

View file

@ -1,30 +1,30 @@
package sqlbuilder package sqlbuilder
type StringExpression interface { type stringExpression interface {
Expression expression
Eq(expression StringExpression) BoolExpression Eq(expression stringExpression) boolExpression
EqString(value string) BoolExpression EqString(value string) boolExpression
NotEq(expression StringExpression) BoolExpression NotEq(expression stringExpression) boolExpression
NotEqString(value string) BoolExpression NotEqString(value string) boolExpression
} }
type stringInterfaceImpl struct { type stringInterfaceImpl struct {
parent StringExpression parent stringExpression
} }
func (b *stringInterfaceImpl) Eq(expression StringExpression) BoolExpression { func (b *stringInterfaceImpl) Eq(expression stringExpression) boolExpression {
return Eq(b.parent, expression) return Eq(b.parent, expression)
} }
func (b *stringInterfaceImpl) EqString(value string) BoolExpression { func (b *stringInterfaceImpl) EqString(value string) boolExpression {
return EqL(b.parent, value) return EqL(b.parent, value)
} }
func (b *stringInterfaceImpl) NotEq(expression StringExpression) BoolExpression { func (b *stringInterfaceImpl) NotEq(expression stringExpression) boolExpression {
return NotEq(b.parent, expression) return NotEq(b.parent, expression)
} }
func (b *stringInterfaceImpl) NotEqString(value string) BoolExpression { func (b *stringInterfaceImpl) NotEqString(value string) boolExpression {
return NotEq(b.parent, Literal(value)) return NotEq(b.parent, Literal(value))
} }

View file

@ -10,47 +10,47 @@ type tableInterface interface {
SchemaName() string SchemaName() string
TableName() string TableName() string
Columns() []Column Columns() []column
// Generates the sql string for the current tableName expression. // Generates the sql string for the current tableName expression.
SerializeSql(out *queryData) error serializeSql(out *queryData) error
} }
// The sql tableName read interface. NOTE: NATURAL JOINs, and join "USING" clause // The sql tableName read interface. NOTE: NATURAL JOINs, and join "USING" clause
// are not supported. // are not supported.
type ReadableTable interface { type readableTable interface {
tableInterface 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
// Creates a inner join tableName expression using onCondition. // Creates a inner join tableName expression using onCondition.
INNER_JOIN(table ReadableTable, onCondition BoolExpression) ReadableTable INNER_JOIN(table readableTable, onCondition boolExpression) readableTable
// Creates a left join tableName expression using onCondition. // Creates a left join tableName expression using onCondition.
LEFT_JOIN(table ReadableTable, onCondition BoolExpression) ReadableTable LEFT_JOIN(table readableTable, onCondition boolExpression) readableTable
// Creates a right join tableName expression using onCondition. // Creates a right join tableName expression using onCondition.
RIGHT_JOIN(table ReadableTable, onCondition BoolExpression) ReadableTable RIGHT_JOIN(table readableTable, onCondition boolExpression) readableTable
FULL_JOIN(table ReadableTable, onCondition BoolExpression) ReadableTable FULL_JOIN(table readableTable, onCondition boolExpression) readableTable
CROSS_JOIN(table ReadableTable) ReadableTable CROSS_JOIN(table readableTable) readableTable
} }
// The sql tableName write interface. // The sql tableName write interface.
type WritableTable interface { type writableTable interface {
tableInterface tableInterface
INSERT(columns ...Column) InsertStatement INSERT(columns ...column) insertStatement
UPDATE(columns ...Column) UpdateStatement 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. // Defines a physical tableName in the database that is both readable and writable.
// This function will panic if name is not valid // This function will panic if name is not valid
func NewTable(schemaName, name string, columns ...Column) *Table { func NewTable(schemaName, name string, columns ...column) *Table {
t := &Table{ t := &Table{
schemaName: schemaName, schemaName: schemaName,
@ -68,10 +68,10 @@ type Table struct {
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 *Table) Column(name string) column {
return &baseColumn{ return &baseColumn{
name: name, name: name,
nullable: NotNullable, nullable: NotNullable,
@ -102,13 +102,13 @@ func (t *Table) SchemaTableName() string {
} }
// Returns a list of the tableName's columns // Returns a list of the tableName's columns
func (t *Table) Columns() []Column { func (t *Table) Columns() []column {
return t.columns return t.columns
} }
// Generates the sql string for the current tableName expression. Note: the // Generates the sql string for the current tableName expression. Note: the
// generated string may not be a valid/executable sql statement. // generated string may not be a valid/executable sql statement.
func (t *Table) SerializeSql(out *queryData) error { func (t *Table) serializeSql(out *queryData) error {
if t == nil { if t == nil {
return errors.Newf("nil tableName.") return errors.Newf("nil tableName.")
} }
@ -126,51 +126,51 @@ func (t *Table) SerializeSql(out *queryData) error {
} }
// Generates a select query on the current tableName. // Generates a select query on the current tableName.
func (t *Table) SELECT(projections ...Projection) SelectStatement { func (t *Table) SELECT(projections ...projection) selectStatement {
return newSelectStatement(t, projections) return newSelectStatement(t, projections)
} }
// Creates a inner join tableName expression using onCondition. // Creates a inner join tableName expression using onCondition.
func (t *Table) INNER_JOIN( func (t *Table) INNER_JOIN(
table ReadableTable, table readableTable,
onCondition BoolExpression) ReadableTable { onCondition boolExpression) readableTable {
return InnerJoinOn(t, table, onCondition) return InnerJoinOn(t, table, onCondition)
} }
// Creates a left join tableName expression using onCondition. // Creates a left join tableName expression using onCondition.
func (t *Table) LEFT_JOIN( func (t *Table) LEFT_JOIN(
table ReadableTable, table readableTable,
onCondition BoolExpression) ReadableTable { onCondition boolExpression) readableTable {
return LeftJoinOn(t, table, onCondition) return LeftJoinOn(t, table, onCondition)
} }
// Creates a right join tableName expression using onCondition. // Creates a right join tableName expression using onCondition.
func (t *Table) RIGHT_JOIN( func (t *Table) RIGHT_JOIN(
table ReadableTable, table readableTable,
onCondition BoolExpression) ReadableTable { onCondition boolExpression) readableTable {
return RightJoinOn(t, table, onCondition) return RightJoinOn(t, table, onCondition)
} }
func (t *Table) FULL_JOIN(table ReadableTable, onCondition BoolExpression) ReadableTable { func (t *Table) FULL_JOIN(table readableTable, onCondition boolExpression) readableTable {
return FullJoin(t, table, onCondition) return FullJoin(t, table, onCondition)
} }
func (t *Table) CROSS_JOIN(table ReadableTable) ReadableTable { func (t *Table) CROSS_JOIN(table readableTable) readableTable {
return CrossJoin(t, table) return CrossJoin(t, table)
} }
func (t *Table) INSERT(columns ...Column) InsertStatement { func (t *Table) INSERT(columns ...column) insertStatement {
return newInsertStatement(t, columns...) return newInsertStatement(t, columns...)
} }
func (t *Table) UPDATE(columns ...Column) UpdateStatement { func (t *Table) UPDATE(columns ...column) updateStatement {
return newUpdateStatement(t, columns) return newUpdateStatement(t, columns)
} }
func (t *Table) DELETE() DeleteStatement { func (t *Table) DELETE() deleteStatement {
return newDeleteStatement(t) return newDeleteStatement(t)
} }
@ -190,17 +190,17 @@ const (
// Join expressions are pseudo readable tables. // Join expressions are pseudo readable tables.
type joinTable struct { type joinTable struct {
lhs ReadableTable lhs readableTable
rhs ReadableTable rhs readableTable
join_type joinType join_type joinType
onCondition BoolExpression onCondition boolExpression
} }
func newJoinTable( func newJoinTable(
lhs ReadableTable, lhs readableTable,
rhs ReadableTable, rhs readableTable,
join_type joinType, join_type joinType,
onCondition BoolExpression) ReadableTable { onCondition boolExpression) readableTable {
return &joinTable{ return &joinTable{
lhs: lhs, lhs: lhs,
@ -211,40 +211,40 @@ func newJoinTable(
} }
func InnerJoinOn( func InnerJoinOn(
lhs ReadableTable, lhs readableTable,
rhs ReadableTable, rhs readableTable,
onCondition BoolExpression) ReadableTable { onCondition boolExpression) readableTable {
return newJoinTable(lhs, rhs, INNER_JOIN, onCondition) return newJoinTable(lhs, rhs, INNER_JOIN, onCondition)
} }
func LeftJoinOn( func LeftJoinOn(
lhs ReadableTable, lhs readableTable,
rhs ReadableTable, rhs readableTable,
onCondition BoolExpression) ReadableTable { onCondition boolExpression) readableTable {
return newJoinTable(lhs, rhs, LEFT_JOIN, onCondition) return newJoinTable(lhs, rhs, LEFT_JOIN, onCondition)
} }
func RightJoinOn( func RightJoinOn(
lhs ReadableTable, lhs readableTable,
rhs ReadableTable, rhs readableTable,
onCondition BoolExpression) ReadableTable { onCondition boolExpression) readableTable {
return newJoinTable(lhs, rhs, RIGHT_JOIN, onCondition) return newJoinTable(lhs, rhs, RIGHT_JOIN, onCondition)
} }
func FullJoin( func FullJoin(
lhs ReadableTable, lhs readableTable,
rhs ReadableTable, rhs readableTable,
onCondition BoolExpression) ReadableTable { onCondition boolExpression) readableTable {
return newJoinTable(lhs, rhs, FULL_JOIN, onCondition) return newJoinTable(lhs, rhs, FULL_JOIN, onCondition)
} }
func CrossJoin( func CrossJoin(
lhs ReadableTable, lhs readableTable,
rhs ReadableTable) ReadableTable { rhs readableTable) readableTable {
return newJoinTable(lhs, rhs, CROSS_JOIN, nil) return newJoinTable(lhs, rhs, CROSS_JOIN, nil)
} }
@ -257,22 +257,22 @@ func (t *joinTable) TableName() string {
return "" return ""
} }
func (t *joinTable) Columns() []Column { func (t *joinTable) Columns() []column {
columns := make([]Column, 0) columns := make([]column, 0)
columns = append(columns, t.lhs.Columns()...) columns = append(columns, t.lhs.Columns()...)
columns = append(columns, t.rhs.Columns()...) columns = append(columns, t.rhs.Columns()...)
return columns return columns
} }
func (t *joinTable) Column(name string) Column { func (t *joinTable) Column(name string) column {
return &baseColumn{ return &baseColumn{
name: name, name: name,
nullable: NotNullable, nullable: NotNullable,
} }
} }
func (t *joinTable) SerializeSql(out *queryData) (err error) { func (t *joinTable) serializeSql(out *queryData) (err error) {
if t.lhs == nil { if t.lhs == nil {
return errors.Newf("nil lhs.") return errors.Newf("nil lhs.")
@ -284,7 +284,7 @@ func (t *joinTable) SerializeSql(out *queryData) (err error) {
return errors.Newf("nil onCondition.") return errors.Newf("nil onCondition.")
} }
if err = t.lhs.SerializeSql(out); err != nil { if err = t.lhs.serializeSql(out); err != nil {
return return
} }
@ -301,13 +301,13 @@ func (t *joinTable) SerializeSql(out *queryData) (err error) {
out.WriteString(" CROSS JOIN ") out.WriteString(" CROSS JOIN ")
} }
if err = t.rhs.SerializeSql(out); err != nil { if err = t.rhs.serializeSql(out); err != nil {
return return
} }
if t.onCondition != nil { if t.onCondition != nil {
out.WriteString(" ON ") out.WriteString(" ON ")
if err = t.onCondition.Serialize(out); err != nil { if err = t.onCondition.serialize(out); err != nil {
return return
} }
} }
@ -315,35 +315,35 @@ func (t *joinTable) SerializeSql(out *queryData) (err error) {
return nil return nil
} }
func (t *joinTable) SELECT(projections ...Projection) SelectStatement { func (t *joinTable) SELECT(projections ...projection) selectStatement {
return newSelectStatement(t, projections) return newSelectStatement(t, projections)
} }
func (t *joinTable) INNER_JOIN( func (t *joinTable) INNER_JOIN(
table ReadableTable, table readableTable,
onCondition BoolExpression) ReadableTable { onCondition boolExpression) readableTable {
return InnerJoinOn(t, table, onCondition) return InnerJoinOn(t, table, onCondition)
} }
func (t *joinTable) LEFT_JOIN( func (t *joinTable) LEFT_JOIN(
table ReadableTable, table readableTable,
onCondition BoolExpression) ReadableTable { onCondition boolExpression) readableTable {
return LeftJoinOn(t, table, onCondition) return LeftJoinOn(t, table, onCondition)
} }
func (t *joinTable) FULL_JOIN(table ReadableTable, onCondition BoolExpression) ReadableTable { func (t *joinTable) FULL_JOIN(table readableTable, onCondition boolExpression) readableTable {
return FullJoin(t, table, onCondition) return FullJoin(t, table, onCondition)
} }
func (t *joinTable) CROSS_JOIN(table ReadableTable) ReadableTable { func (t *joinTable) CROSS_JOIN(table readableTable) readableTable {
return CrossJoin(t, table) return CrossJoin(t, table)
} }
func (t *joinTable) RIGHT_JOIN( func (t *joinTable) RIGHT_JOIN(
table ReadableTable, table readableTable,
onCondition BoolExpression) ReadableTable { onCondition boolExpression) readableTable {
return RightJoinOn(t, table, onCondition) return RightJoinOn(t, table, onCondition)
} }

View file

@ -51,7 +51,7 @@ func (s *TableSuite) TestJoinNilLeftTable(c *gc.C) {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
err := join.SerializeSql(buf) err := join.serializeSql(buf)
c.Assert(err, gc.NotNil) c.Assert(err, gc.NotNil)
} }
@ -60,7 +60,7 @@ func (s *TableSuite) TestJoinNilRightTable(c *gc.C) {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
err := join.SerializeSql(buf) err := join.serializeSql(buf)
c.Assert(err, gc.NotNil) c.Assert(err, gc.NotNil)
} }
@ -69,7 +69,7 @@ func (s *TableSuite) TestJoinNilOnCondition(c *gc.C) {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
err := join.SerializeSql(buf) err := join.serializeSql(buf)
c.Assert(err, gc.NotNil) c.Assert(err, gc.NotNil)
} }
@ -93,7 +93,7 @@ func (s *TableSuite) TestLeftJoin(c *gc.C) {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
err := join.SerializeSql(buf) err := join.serializeSql(buf)
c.Assert(err, gc.IsNil) c.Assert(err, gc.IsNil)
sql := buf.String() sql := buf.String()
@ -109,7 +109,7 @@ func (s *TableSuite) TestRightJoin(c *gc.C) {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
err := join.SerializeSql(buf) err := join.serializeSql(buf)
c.Assert(err, gc.IsNil) c.Assert(err, gc.IsNil)
sql := buf.String() sql := buf.String()

View file

@ -1,51 +1,51 @@
package sqlbuilder package sqlbuilder
type TimeExpression interface { type timeExpression interface {
Expression expression
Eq(expression TimeExpression) BoolExpression Eq(expression timeExpression) boolExpression
EqL(literal string) BoolExpression EqL(literal string) boolExpression
NotEq(expression TimeExpression) BoolExpression NotEq(expression timeExpression) boolExpression
NotEqL(literal string) BoolExpression NotEqL(literal string) boolExpression
GtEq(rhs TimeExpression) BoolExpression GtEq(rhs timeExpression) boolExpression
GtEqL(literal string) BoolExpression GtEqL(literal string) boolExpression
LtEq(rhs TimeExpression) BoolExpression LtEq(rhs timeExpression) boolExpression
LtEqL(literal string) BoolExpression LtEqL(literal string) boolExpression
} }
type timeInterfaceImpl struct { type timeInterfaceImpl struct {
parent TimeExpression parent timeExpression
} }
func (t *timeInterfaceImpl) Eq(expression TimeExpression) BoolExpression { func (t *timeInterfaceImpl) Eq(expression timeExpression) boolExpression {
return Eq(t.parent, expression) return Eq(t.parent, expression)
} }
func (t *timeInterfaceImpl) EqL(literal string) BoolExpression { func (t *timeInterfaceImpl) EqL(literal string) boolExpression {
return Eq(t.parent, Literal(literal)) return Eq(t.parent, Literal(literal))
} }
func (t *timeInterfaceImpl) NotEq(expression TimeExpression) BoolExpression { func (t *timeInterfaceImpl) NotEq(expression timeExpression) boolExpression {
return NotEq(t.parent, expression) return NotEq(t.parent, expression)
} }
func (t *timeInterfaceImpl) NotEqL(literal string) BoolExpression { func (t *timeInterfaceImpl) NotEqL(literal string) boolExpression {
return NotEq(t.parent, Literal(literal)) return NotEq(t.parent, Literal(literal))
} }
func (t *timeInterfaceImpl) GtEq(expression TimeExpression) BoolExpression { func (t *timeInterfaceImpl) GtEq(expression timeExpression) boolExpression {
return GtEq(t.parent, expression) return GtEq(t.parent, expression)
} }
func (t *timeInterfaceImpl) GtEqL(literal string) BoolExpression { func (t *timeInterfaceImpl) GtEqL(literal string) boolExpression {
return GtEq(t.parent, Literal(literal)) return GtEq(t.parent, Literal(literal))
} }
func (t *timeInterfaceImpl) LtEq(expression TimeExpression) BoolExpression { func (t *timeInterfaceImpl) LtEq(expression timeExpression) boolExpression {
return LtEq(t.parent, expression) return LtEq(t.parent, expression)
} }
func (t *timeInterfaceImpl) LtEqL(literal string) BoolExpression { func (t *timeInterfaceImpl) LtEqL(literal string) boolExpression {
return LtEq(t.parent, Literal(literal)) return LtEq(t.parent, Literal(literal))
} }
@ -57,7 +57,7 @@ type prefixTimeExpression struct {
prefixExpression prefixExpression
} }
func newPrefixTimeExpression(expression Expression, operator string) TimeExpression { func newPrefixTimeExpression(expression expression, operator string) timeExpression {
timeExpr := prefixTimeExpression{} timeExpr := prefixTimeExpression{}
timeExpr.prefixExpression = newPrefixExpression(expression, operator) timeExpr.prefixExpression = newPrefixExpression(expression, operator)
@ -67,6 +67,6 @@ func newPrefixTimeExpression(expression Expression, operator string) TimeExpress
return &timeExpr return &timeExpr
} }
func INTERVAL(interval string) Expression { func INTERVAL(interval string) expression {
return newPrefixTimeExpression(Literal(interval), "INTERVAL") return newPrefixTimeExpression(Literal(interval), "INTERVAL")
} }

View file

@ -3,44 +3,13 @@ package sqlbuilder
// A clause that can be used in orderBy by // A clause that can be used in orderBy by
// A clause that is selectable. // A clause that is selectable.
//type Projection interface { //type projection interface {
// Clause // clause
// isProjectionInterface // isProjectionInterface
// //
// SerializeSqlForColumnList(out *bytes.Buffer) error // SerializeSqlForColumnList(out *bytes.Buffer) error
//} //}
//type ColumnList []Column
//
//func (cl ColumnList) Serialize(out *bytes.Buffer, options ...serializeOption) error {
// for i, column := range cl {
// column.Serialize(out)
//
// if i != len(cl)-1 {
// out.WriteString(", ")
// }
// }
// return nil
//}
//
//func (cl ColumnList) isProjectionType() {
//}
//
//func (cl ColumnList) AS(name string) Clause {
// 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
//}
// //
// Boiler plates ... // Boiler plates ...
// //

View file

@ -6,15 +6,15 @@ import (
"github.com/sub0zero/go-sqlbuilder/types" "github.com/sub0zero/go-sqlbuilder/types"
) )
type UpdateStatement interface { type updateStatement interface {
Statement statement
SET(values ...interface{}) UpdateStatement SET(values ...interface{}) updateStatement
WHERE(expression BoolExpression) UpdateStatement WHERE(expression boolExpression) updateStatement
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,17 +22,17 @@ 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
} }
func (u *updateStatementImpl) SET(values ...interface{}) UpdateStatement { func (u *updateStatementImpl) SET(values ...interface{}) updateStatement {
for _, value := range values { for _, value := range values {
if clause, ok := value.(Clause); ok { if clause, ok := value.(clause); ok {
u.updateValues = append(u.updateValues, clause) u.updateValues = append(u.updateValues, clause)
} else { } else {
u.updateValues = append(u.updateValues, Literal(value)) u.updateValues = append(u.updateValues, Literal(value))
@ -42,12 +42,12 @@ func (u *updateStatementImpl) SET(values ...interface{}) UpdateStatement {
return u return u
} }
func (u *updateStatementImpl) WHERE(expression BoolExpression) UpdateStatement { func (u *updateStatementImpl) WHERE(expression boolExpression) updateStatement {
u.where = expression u.where = expression
return u return u
} }
func (u *updateStatementImpl) RETURNING(projections ...Projection) UpdateStatement { func (u *updateStatementImpl) RETURNING(projections ...projection) updateStatement {
u.returning = defaultProjectionAliasing(projections) u.returning = defaultProjectionAliasing(projections)
return u return u
} }
@ -62,7 +62,7 @@ func (u *updateStatementImpl) Sql() (sql string, args []interface{}, err error)
return "", nil, errors.New("nil tableName.") return "", nil, errors.New("nil tableName.")
} }
if err = u.table.SerializeSql(out); err != nil { if err = u.table.serializeSql(out); err != nil {
return return
} }
@ -99,7 +99,7 @@ func (u *updateStatementImpl) Sql() (sql string, args []interface{}, err error)
out.WriteString(", ") out.WriteString(", ")
} }
err = value.Serialize(out) err = value.serialize(out)
if err != nil { if err != nil {
return return

View file

@ -7,14 +7,14 @@ import (
"github.com/sub0zero/go-sqlbuilder/types" "github.com/sub0zero/go-sqlbuilder/types"
) )
func serializeOrderByClauseList(orderByClauses []OrderByClause, out *queryData) error { func serializeOrderByClauseList(orderByClauses []orderByClause, out *queryData) error {
for i, value := range orderByClauses { for i, value := range orderByClauses {
if i > 0 { if i > 0 {
out.WriteString(", ") out.WriteString(", ")
} }
err := value.Serialize(out) err := value.serialize(out)
if err != nil { if err != nil {
return err return err
@ -24,7 +24,7 @@ func serializeOrderByClauseList(orderByClauses []OrderByClause, out *queryData)
return nil return nil
} }
func serializeClauseList(clauses []Clause, out *queryData) (err error) { func serializeGroupByClauseList(clauses []groupByClause, out *queryData) (err error) {
for i, c := range clauses { for i, c := range clauses {
if i > 0 { if i > 0 {
@ -35,7 +35,7 @@ func serializeClauseList(clauses []Clause, out *queryData) (err error) {
return errors.New("nil clause.") return errors.New("nil clause.")
} }
if err = c.Serialize(out); err != nil { if err = c.serializeForGroupBy(out); err != nil {
return return
} }
} }
@ -43,14 +43,33 @@ func serializeClauseList(clauses []Clause, out *queryData) (err error) {
return nil return nil
} }
func serializeExpressionList(expressions []Expression, separator string, out *queryData) error { func serializeClauseList(clauses []clause, out *queryData) (err error) {
for i, c := range clauses {
if i > 0 {
out.WriteString(", ")
}
if c == nil {
return errors.New("nil clause.")
}
if err = c.serialize(out); err != nil {
return
}
}
return nil
}
func serializeExpressionList(expressions []expression, separator string, out *queryData) error {
for i, value := range expressions { for i, value := range expressions {
if i > 0 { if i > 0 {
out.WriteString(separator) out.WriteString(separator)
} }
err := value.Serialize(out) err := value.serialize(out)
if err != nil { if err != nil {
return err return err
@ -60,16 +79,16 @@ func serializeExpressionList(expressions []Expression, separator string, out *qu
return nil return nil
} }
func serializeProjectionList(projections []Projection, out *queryData) error { func serializeProjectionList(projections []projection, out *queryData) error {
for i, col := range projections { for i, col := range projections {
if i > 0 { if i > 0 {
out.WriteString(", ") out.WriteString(", ")
} }
if col == nil { if col == nil {
return errors.New("Projection expression is nil.") return errors.New("projection expression is nil.")
} }
if err := col.SerializeForProjection(out); err != nil { if err := col.serializeForProjection(out); err != nil {
return err return err
} }
} }
@ -77,7 +96,7 @@ func serializeProjectionList(projections []Projection, out *queryData) error {
return nil return nil
} }
func serializeColumnList(columns []Column, out *queryData) error { func serializeColumnList(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(',')
@ -93,7 +112,7 @@ func serializeColumnList(columns []Column, out *queryData) error {
return nil return nil
} }
func Query(statement Statement, db types.Db, destination interface{}) error { func Query(statement statement, db types.Db, destination interface{}) error {
query, args, err := statement.Sql() query, args, err := statement.Sql()
if err != nil { if err != nil {
@ -103,7 +122,7 @@ func Query(statement Statement, db types.Db, destination interface{}) error {
return execution.Query(db, query, args, destination) return execution.Query(db, query, args, destination)
} }
func Execute(statement Statement, db types.Db) (res sql.Result, err error) { func Execute(statement statement, db types.Db) (res sql.Result, err error) {
query, args, err := statement.Sql() query, args, err := statement.Sql()
if err != nil { if err != nil {