Global AND and OR functions for better indentation of a complex condition in the Go code and in the generated SQL.
This commit is contained in:
parent
8ffbe38993
commit
9f91fd705a
17 changed files with 338 additions and 44 deletions
|
|
@ -98,9 +98,9 @@ func (c *ClauseWhere) Serialize(statementType StatementType, out *SQLBuilder, op
|
|||
}
|
||||
out.WriteString("WHERE")
|
||||
|
||||
out.IncreaseIdent()
|
||||
out.IncreaseIdent(6)
|
||||
c.Condition.serialize(statementType, out, NoWrap.WithFallTrough(options)...)
|
||||
out.DecreaseIdent()
|
||||
out.DecreaseIdent(6)
|
||||
}
|
||||
|
||||
// ClauseGroupBy struct
|
||||
|
|
|
|||
|
|
@ -123,6 +123,65 @@ func (c *binaryOperatorExpression) serialize(statement StatementType, out *SQLBu
|
|||
}
|
||||
}
|
||||
|
||||
type expressionListOperator struct {
|
||||
ExpressionInterfaceImpl
|
||||
|
||||
operator string
|
||||
expressions []Expression
|
||||
}
|
||||
|
||||
func newExpressionListOperator(operator string, expressions ...Expression) *expressionListOperator {
|
||||
ret := &expressionListOperator{
|
||||
operator: operator,
|
||||
expressions: expressions,
|
||||
}
|
||||
|
||||
ret.ExpressionInterfaceImpl.Parent = ret
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func newBoolExpressionListOperator(operator string, expressions ...BoolExpression) BoolExpression {
|
||||
return BoolExp(newExpressionListOperator(operator, BoolExpressionListToExpressionList(expressions)...))
|
||||
}
|
||||
|
||||
func (elo *expressionListOperator) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
if len(elo.expressions) == 0 {
|
||||
panic("jet: syntax error, expression list empty")
|
||||
}
|
||||
|
||||
shouldWrap := len(elo.expressions) > 1
|
||||
if shouldWrap {
|
||||
out.WriteByte('(')
|
||||
out.IncreaseIdent(tabSize)
|
||||
out.NewLine()
|
||||
}
|
||||
|
||||
for i, expression := range elo.expressions {
|
||||
if i == 1 {
|
||||
out.IncreaseIdent(tabSize)
|
||||
}
|
||||
if i > 0 {
|
||||
out.NewLine()
|
||||
out.WriteString(elo.operator)
|
||||
}
|
||||
|
||||
out.IncreaseIdent(len(elo.operator) + 1)
|
||||
expression.serialize(statement, out, FallTrough(options)...)
|
||||
out.DecreaseIdent(len(elo.operator) + 1)
|
||||
}
|
||||
|
||||
if len(elo.expressions) > 1 {
|
||||
out.DecreaseIdent(tabSize)
|
||||
}
|
||||
|
||||
if shouldWrap {
|
||||
out.DecreaseIdent(tabSize)
|
||||
out.NewLine()
|
||||
out.WriteByte(')')
|
||||
}
|
||||
}
|
||||
|
||||
// A prefix operator Expression
|
||||
type prefixExpression struct {
|
||||
ExpressionInterfaceImpl
|
||||
|
|
@ -209,8 +268,8 @@ type complexExpression struct {
|
|||
expressions Expression
|
||||
}
|
||||
|
||||
func complexExpr(expressions Expression) Expression {
|
||||
complexExpression := &complexExpression{expressions: expressions}
|
||||
func complexExpr(expression Expression) Expression {
|
||||
complexExpression := &complexExpression{expressions: expression}
|
||||
complexExpression.ExpressionInterfaceImpl.Parent = complexExpression
|
||||
|
||||
return complexExpression
|
||||
|
|
|
|||
|
|
@ -1,5 +1,17 @@
|
|||
package jet
|
||||
|
||||
// AND function adds AND operator between expressions. This function can be used, instead of method AND,
|
||||
// to have a better inlining of a complex condition in the Go code and in the generated SQL.
|
||||
func AND(expressions ...BoolExpression) BoolExpression {
|
||||
return newBoolExpressionListOperator("AND", expressions...)
|
||||
}
|
||||
|
||||
// OR function adds OR operator between expressions. This function can be used, instead of method OR,
|
||||
// to have a better inlining of a complex condition in the Go code and in the generated SQL.
|
||||
func OR(expressions ...BoolExpression) BoolExpression {
|
||||
return newBoolExpressionListOperator("OR", expressions...)
|
||||
}
|
||||
|
||||
// ROW is construct one table row from list of expressions.
|
||||
func ROW(expressions ...Expression) Expression {
|
||||
return NewFunc("ROW", expressions, nil)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,28 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
func TestAND(t *testing.T) {
|
||||
assertClauseSerializeErr(t, AND(), "jet: syntax error, expression list empty")
|
||||
assertClauseSerialize(t, AND(table1ColInt.IS_NULL()), `table1.col_int IS NULL`) // IS NULL doesn't add parenthesis
|
||||
assertClauseSerialize(t, AND(table1ColInt.LT(Int(11))), `(table1.col_int < $1)`, int64(11))
|
||||
assertClauseSerialize(t, AND(table1ColInt.GT(Int(11)), table1ColFloat.EQ(Float(0))),
|
||||
`(
|
||||
(table1.col_int > $1)
|
||||
AND (table1.col_float = $2)
|
||||
)`, int64(11), 0.0)
|
||||
}
|
||||
|
||||
func TestOR(t *testing.T) {
|
||||
assertClauseSerializeErr(t, OR(), "jet: syntax error, expression list empty")
|
||||
assertClauseSerialize(t, OR(table1ColInt.IS_NULL()), `table1.col_int IS NULL`) // IS NULL doesn't add parenthesis
|
||||
assertClauseSerialize(t, OR(table1ColInt.LT(Int(11))), `(table1.col_int < $1)`, int64(11))
|
||||
assertClauseSerialize(t, OR(table1ColInt.GT(Int(11)), table1ColFloat.EQ(Float(0))),
|
||||
`(
|
||||
(table1.col_int > $1)
|
||||
OR (table1.col_float = $2)
|
||||
)`, int64(11), 0.0)
|
||||
}
|
||||
|
||||
func TestFuncAVG(t *testing.T) {
|
||||
assertClauseSerialize(t, AVG(table1ColFloat), "AVG(table1.col_float)")
|
||||
assertClauseSerialize(t, AVG(table1ColInt), "AVG(table1.col_int)")
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ type SQLBuilder struct {
|
|||
Debug bool
|
||||
}
|
||||
|
||||
const tabSize = 4
|
||||
const defaultIdent = 5
|
||||
|
||||
// IncreaseIdent adds ident or defaultIdent number of spaces to each new line
|
||||
|
|
|
|||
|
|
@ -113,6 +113,17 @@ func ExpressionListToSerializerList(expressions []Expression) []Serializer {
|
|||
return ret
|
||||
}
|
||||
|
||||
// BoolExpressionListToExpressionList converts list of bool expressions to list of expressions
|
||||
func BoolExpressionListToExpressionList(expressions []BoolExpression) []Expression {
|
||||
var ret []Expression
|
||||
|
||||
for _, expression := range expressions {
|
||||
ret = append(ret, expression)
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// ColumnListToProjectionList func
|
||||
func ColumnListToProjectionList(columns []ColumnExpression) []Projection {
|
||||
var ret []Projection
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue