[postgres] Add support for ON CONFLICT clause
This commit is contained in:
parent
eea776a1ac
commit
14e1863456
42 changed files with 827 additions and 277 deletions
|
|
@ -42,12 +42,12 @@ func (b *castExpression) serialize(statement StatementType, out *SQLBuilder, opt
|
|||
castType := b.cast
|
||||
|
||||
if castOverride := out.Dialect.OperatorSerializeOverride("CAST"); castOverride != nil {
|
||||
castOverride(expression, String(castType))(statement, out, options...)
|
||||
castOverride(expression, String(castType))(statement, out, FallTrough(options)...)
|
||||
return
|
||||
}
|
||||
|
||||
out.WriteString("CAST(")
|
||||
expression.serialize(statement, out, options...)
|
||||
expression.serialize(statement, out, FallTrough(options)...)
|
||||
out.WriteString("AS")
|
||||
out.WriteString(castType + ")")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import (
|
|||
|
||||
// Clause interface
|
||||
type Clause interface {
|
||||
Serialize(statementType StatementType, out *SQLBuilder)
|
||||
Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption)
|
||||
}
|
||||
|
||||
// ClauseWithProjections interface
|
||||
|
|
@ -27,7 +27,7 @@ func (s *ClauseSelect) projections() ProjectionList {
|
|||
}
|
||||
|
||||
// Serialize serializes clause into SQLBuilder
|
||||
func (s *ClauseSelect) Serialize(statementType StatementType, out *SQLBuilder) {
|
||||
func (s *ClauseSelect) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
out.NewLine()
|
||||
out.WriteString("SELECT")
|
||||
|
||||
|
|
@ -48,7 +48,7 @@ type ClauseFrom struct {
|
|||
}
|
||||
|
||||
// Serialize serializes clause into SQLBuilder
|
||||
func (f *ClauseFrom) Serialize(statementType StatementType, out *SQLBuilder) {
|
||||
func (f *ClauseFrom) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
if f.Table == nil {
|
||||
return
|
||||
}
|
||||
|
|
@ -56,7 +56,7 @@ func (f *ClauseFrom) Serialize(statementType StatementType, out *SQLBuilder) {
|
|||
out.WriteString("FROM")
|
||||
|
||||
out.IncreaseIdent()
|
||||
f.Table.serialize(statementType, out)
|
||||
f.Table.serialize(statementType, out, FallTrough(options)...)
|
||||
out.DecreaseIdent()
|
||||
}
|
||||
|
||||
|
|
@ -67,18 +67,20 @@ type ClauseWhere struct {
|
|||
}
|
||||
|
||||
// Serialize serializes clause into SQLBuilder
|
||||
func (c *ClauseWhere) Serialize(statementType StatementType, out *SQLBuilder) {
|
||||
func (c *ClauseWhere) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
if c.Condition == nil {
|
||||
if c.Mandatory {
|
||||
panic("jet: WHERE clause not set")
|
||||
}
|
||||
return
|
||||
}
|
||||
out.NewLine()
|
||||
if !contains(options, SkipNewLine) {
|
||||
out.NewLine()
|
||||
}
|
||||
out.WriteString("WHERE")
|
||||
|
||||
out.IncreaseIdent()
|
||||
c.Condition.serialize(statementType, out, noWrap)
|
||||
c.Condition.serialize(statementType, out, NoWrap.WithFallTrough(options)...)
|
||||
out.DecreaseIdent()
|
||||
}
|
||||
|
||||
|
|
@ -88,7 +90,7 @@ type ClauseGroupBy struct {
|
|||
}
|
||||
|
||||
// Serialize serializes clause into SQLBuilder
|
||||
func (c *ClauseGroupBy) Serialize(statementType StatementType, out *SQLBuilder) {
|
||||
func (c *ClauseGroupBy) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
if len(c.List) == 0 {
|
||||
return
|
||||
}
|
||||
|
|
@ -119,7 +121,7 @@ type ClauseHaving struct {
|
|||
}
|
||||
|
||||
// Serialize serializes clause into SQLBuilder
|
||||
func (c *ClauseHaving) Serialize(statementType StatementType, out *SQLBuilder) {
|
||||
func (c *ClauseHaving) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
if c.Condition == nil {
|
||||
return
|
||||
}
|
||||
|
|
@ -128,7 +130,7 @@ func (c *ClauseHaving) Serialize(statementType StatementType, out *SQLBuilder) {
|
|||
out.WriteString("HAVING")
|
||||
|
||||
out.IncreaseIdent()
|
||||
c.Condition.serialize(statementType, out, noWrap)
|
||||
c.Condition.serialize(statementType, out, NoWrap.WithFallTrough(options)...)
|
||||
out.DecreaseIdent()
|
||||
}
|
||||
|
||||
|
|
@ -139,7 +141,7 @@ type ClauseOrderBy struct {
|
|||
}
|
||||
|
||||
// Serialize serializes clause into SQLBuilder
|
||||
func (o *ClauseOrderBy) Serialize(statementType StatementType, out *SQLBuilder) {
|
||||
func (o *ClauseOrderBy) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
if o.List == nil {
|
||||
return
|
||||
}
|
||||
|
|
@ -168,7 +170,7 @@ type ClauseLimit struct {
|
|||
}
|
||||
|
||||
// Serialize serializes clause into SQLBuilder
|
||||
func (l *ClauseLimit) Serialize(statementType StatementType, out *SQLBuilder) {
|
||||
func (l *ClauseLimit) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
if l.Count >= 0 {
|
||||
out.NewLine()
|
||||
out.WriteString("LIMIT")
|
||||
|
|
@ -182,7 +184,7 @@ type ClauseOffset struct {
|
|||
}
|
||||
|
||||
// Serialize serializes clause into SQLBuilder
|
||||
func (o *ClauseOffset) Serialize(statementType StatementType, out *SQLBuilder) {
|
||||
func (o *ClauseOffset) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
if o.Count >= 0 {
|
||||
out.NewLine()
|
||||
out.WriteString("OFFSET")
|
||||
|
|
@ -196,14 +198,14 @@ type ClauseFor struct {
|
|||
}
|
||||
|
||||
// Serialize serializes clause into SQLBuilder
|
||||
func (f *ClauseFor) Serialize(statementType StatementType, out *SQLBuilder) {
|
||||
func (f *ClauseFor) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
if f.Lock == nil {
|
||||
return
|
||||
}
|
||||
|
||||
out.NewLine()
|
||||
out.WriteString("FOR")
|
||||
f.Lock.serialize(statementType, out)
|
||||
f.Lock.serialize(statementType, out, FallTrough(options)...)
|
||||
}
|
||||
|
||||
// ClauseSetStmtOperator struct
|
||||
|
|
@ -224,7 +226,7 @@ func (s *ClauseSetStmtOperator) projections() ProjectionList {
|
|||
}
|
||||
|
||||
// Serialize serializes clause into SQLBuilder
|
||||
func (s *ClauseSetStmtOperator) Serialize(statementType StatementType, out *SQLBuilder) {
|
||||
func (s *ClauseSetStmtOperator) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
if len(s.Selects) < 2 {
|
||||
panic("jet: UNION Statement must contain at least two SELECT statements")
|
||||
}
|
||||
|
|
@ -244,7 +246,7 @@ func (s *ClauseSetStmtOperator) Serialize(statementType StatementType, out *SQLB
|
|||
panic("jet: select statement of '" + s.Operator + "' is nil")
|
||||
}
|
||||
|
||||
selectStmt.serialize(statementType, out)
|
||||
selectStmt.serialize(statementType, out, FallTrough(options)...)
|
||||
}
|
||||
|
||||
s.OrderBy.Serialize(statementType, out)
|
||||
|
|
@ -258,7 +260,7 @@ type ClauseUpdate struct {
|
|||
}
|
||||
|
||||
// Serialize serializes clause into SQLBuilder
|
||||
func (u *ClauseUpdate) Serialize(statementType StatementType, out *SQLBuilder) {
|
||||
func (u *ClauseUpdate) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
out.NewLine()
|
||||
out.WriteString("UPDATE")
|
||||
|
||||
|
|
@ -266,7 +268,7 @@ func (u *ClauseUpdate) Serialize(statementType StatementType, out *SQLBuilder) {
|
|||
panic("jet: table to update is nil")
|
||||
}
|
||||
|
||||
u.Table.serialize(statementType, out)
|
||||
u.Table.serialize(statementType, out, FallTrough(options)...)
|
||||
}
|
||||
|
||||
// ClauseSet struct
|
||||
|
|
@ -276,7 +278,7 @@ type ClauseSet struct {
|
|||
}
|
||||
|
||||
// Serialize serializes clause into SQLBuilder
|
||||
func (s *ClauseSet) Serialize(statementType StatementType, out *SQLBuilder) {
|
||||
func (s *ClauseSet) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
out.NewLine()
|
||||
out.WriteString("SET")
|
||||
|
||||
|
|
@ -299,7 +301,7 @@ func (s *ClauseSet) Serialize(statementType StatementType, out *SQLBuilder) {
|
|||
|
||||
out.WriteString(" = ")
|
||||
|
||||
s.Values[i].serialize(UpdateStatementType, out)
|
||||
s.Values[i].serialize(UpdateStatementType, out, FallTrough(options)...)
|
||||
}
|
||||
out.DecreaseIdent(4)
|
||||
}
|
||||
|
|
@ -320,7 +322,7 @@ func (i *ClauseInsert) GetColumns() []Column {
|
|||
}
|
||||
|
||||
// Serialize serializes clause into SQLBuilder
|
||||
func (i *ClauseInsert) Serialize(statementType StatementType, out *SQLBuilder) {
|
||||
func (i *ClauseInsert) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
out.NewLine()
|
||||
out.WriteString("INSERT INTO")
|
||||
|
||||
|
|
@ -346,7 +348,7 @@ type ClauseValuesQuery struct {
|
|||
}
|
||||
|
||||
// Serialize serializes clause into SQLBuilder
|
||||
func (v *ClauseValuesQuery) Serialize(statementType StatementType, out *SQLBuilder) {
|
||||
func (v *ClauseValuesQuery) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
if len(v.Rows) == 0 && v.Query == nil {
|
||||
panic("jet: VALUES or QUERY has to be specified for INSERT statement")
|
||||
}
|
||||
|
|
@ -355,8 +357,8 @@ func (v *ClauseValuesQuery) Serialize(statementType StatementType, out *SQLBuild
|
|||
panic("jet: VALUES or QUERY has to be specified for INSERT statement")
|
||||
}
|
||||
|
||||
v.ClauseValues.Serialize(statementType, out)
|
||||
v.ClauseQuery.Serialize(statementType, out)
|
||||
v.ClauseValues.Serialize(statementType, out, FallTrough(options)...)
|
||||
v.ClauseQuery.Serialize(statementType, out, FallTrough(options)...)
|
||||
}
|
||||
|
||||
// ClauseValues struct
|
||||
|
|
@ -365,27 +367,29 @@ type ClauseValues struct {
|
|||
}
|
||||
|
||||
// Serialize serializes clause into SQLBuilder
|
||||
func (v *ClauseValues) Serialize(statementType StatementType, out *SQLBuilder) {
|
||||
func (v *ClauseValues) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
if len(v.Rows) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
out.NewLine()
|
||||
out.WriteString("VALUES")
|
||||
|
||||
for rowIndex, row := range v.Rows {
|
||||
if rowIndex > 0 {
|
||||
out.WriteString(",")
|
||||
out.NewLine()
|
||||
} else {
|
||||
out.IncreaseIdent(7)
|
||||
}
|
||||
|
||||
out.IncreaseIdent()
|
||||
out.NewLine()
|
||||
out.WriteString("(")
|
||||
|
||||
SerializeClauseList(statementType, row, out)
|
||||
|
||||
out.WriteByte(')')
|
||||
out.DecreaseIdent()
|
||||
}
|
||||
out.DecreaseIdent(7)
|
||||
}
|
||||
|
||||
// ClauseQuery struct
|
||||
|
|
@ -394,12 +398,12 @@ type ClauseQuery struct {
|
|||
}
|
||||
|
||||
// Serialize serializes clause into SQLBuilder
|
||||
func (v *ClauseQuery) Serialize(statementType StatementType, out *SQLBuilder) {
|
||||
func (v *ClauseQuery) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
if v.Query == nil {
|
||||
return
|
||||
}
|
||||
|
||||
v.Query.serialize(statementType, out)
|
||||
v.Query.serialize(statementType, out, FallTrough(options)...)
|
||||
}
|
||||
|
||||
// ClauseDelete struct
|
||||
|
|
@ -408,7 +412,7 @@ type ClauseDelete struct {
|
|||
}
|
||||
|
||||
// Serialize serializes clause into SQLBuilder
|
||||
func (d *ClauseDelete) Serialize(statementType StatementType, out *SQLBuilder) {
|
||||
func (d *ClauseDelete) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
out.NewLine()
|
||||
out.WriteString("DELETE FROM")
|
||||
|
||||
|
|
@ -416,7 +420,7 @@ func (d *ClauseDelete) Serialize(statementType StatementType, out *SQLBuilder) {
|
|||
panic("jet: nil table in DELETE clause")
|
||||
}
|
||||
|
||||
d.Table.serialize(statementType, out)
|
||||
d.Table.serialize(statementType, out, FallTrough(options)...)
|
||||
}
|
||||
|
||||
// ClauseStatementBegin struct
|
||||
|
|
@ -426,7 +430,7 @@ type ClauseStatementBegin struct {
|
|||
}
|
||||
|
||||
// Serialize serializes clause into SQLBuilder
|
||||
func (d *ClauseStatementBegin) Serialize(statementType StatementType, out *SQLBuilder) {
|
||||
func (d *ClauseStatementBegin) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
out.NewLine()
|
||||
out.WriteString(d.Name)
|
||||
|
||||
|
|
@ -435,7 +439,7 @@ func (d *ClauseStatementBegin) Serialize(statementType StatementType, out *SQLBu
|
|||
out.WriteString(", ")
|
||||
}
|
||||
|
||||
table.serialize(statementType, out)
|
||||
table.serialize(statementType, out, FallTrough(options)...)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -447,7 +451,7 @@ type ClauseOptional struct {
|
|||
}
|
||||
|
||||
// Serialize serializes clause into SQLBuilder
|
||||
func (d *ClauseOptional) Serialize(statementType StatementType, out *SQLBuilder) {
|
||||
func (d *ClauseOptional) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
if !d.Show {
|
||||
return
|
||||
}
|
||||
|
|
@ -463,7 +467,7 @@ type ClauseIn struct {
|
|||
}
|
||||
|
||||
// Serialize serializes clause into SQLBuilder
|
||||
func (i *ClauseIn) Serialize(statementType StatementType, out *SQLBuilder) {
|
||||
func (i *ClauseIn) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
if i.LockMode == "" {
|
||||
return
|
||||
}
|
||||
|
|
@ -485,7 +489,7 @@ type ClauseWindow struct {
|
|||
}
|
||||
|
||||
// Serialize serializes clause into SQLBuilder
|
||||
func (i *ClauseWindow) Serialize(statementType StatementType, out *SQLBuilder) {
|
||||
func (i *ClauseWindow) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
if len(i.Definitions) == 0 {
|
||||
return
|
||||
}
|
||||
|
|
@ -503,6 +507,44 @@ func (i *ClauseWindow) Serialize(statementType StatementType, out *SQLBuilder) {
|
|||
out.WriteString("()")
|
||||
continue
|
||||
}
|
||||
def.Window.serialize(statementType, out)
|
||||
def.Window.serialize(statementType, out, FallTrough(options)...)
|
||||
}
|
||||
}
|
||||
|
||||
// SetPair clause
|
||||
type SetPair struct {
|
||||
Column ColumnSerializer
|
||||
Value Serializer
|
||||
}
|
||||
|
||||
// SetClause clause
|
||||
type SetClause []SetPair
|
||||
|
||||
// Serialize for SetClause
|
||||
func (s SetClause) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
out.NewLine()
|
||||
out.WriteString("SET")
|
||||
out.IncreaseIdent(4)
|
||||
|
||||
for i, pair := range s {
|
||||
if i > 0 {
|
||||
out.WriteString(",")
|
||||
out.NewLine()
|
||||
}
|
||||
|
||||
pair.Column.serialize(statementType, out, ShortName.WithFallTrough(options)...)
|
||||
out.WriteString("=")
|
||||
pair.Value.serialize(statementType, out, FallTrough(options)...)
|
||||
}
|
||||
out.DecreaseIdent(4)
|
||||
}
|
||||
|
||||
// KeywordClause type
|
||||
type KeywordClause struct {
|
||||
Keyword
|
||||
}
|
||||
|
||||
// Serialize for KeywordClause
|
||||
func (k KeywordClause) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
k.serialize(statementType, out, FallTrough(options)...)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,12 @@ type Column interface {
|
|||
defaultAlias() string
|
||||
}
|
||||
|
||||
// ColumnSerializer is interface for all serializable columns
|
||||
type ColumnSerializer interface {
|
||||
Serializer
|
||||
Column
|
||||
}
|
||||
|
||||
// ColumnExpression interface
|
||||
type ColumnExpression interface {
|
||||
Column
|
||||
|
|
@ -101,7 +107,7 @@ func (c ColumnExpressionImpl) serialize(statement StatementType, out *SQLBuilder
|
|||
out.WriteByte('.')
|
||||
out.WriteIdentifier(c.defaultAlias(), true)
|
||||
} else {
|
||||
if c.tableName != "" {
|
||||
if c.tableName != "" && !contains(options, ShortName) {
|
||||
out.WriteIdentifier(c.tableName)
|
||||
out.WriteByte('.')
|
||||
}
|
||||
|
|
@ -125,6 +131,17 @@ func (cl ColumnList) fromImpl(subQuery SelectTable) Projection {
|
|||
return newProjectionList
|
||||
}
|
||||
|
||||
func (cl ColumnList) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
out.WriteString("(")
|
||||
for i, column := range cl {
|
||||
if i > 0 {
|
||||
out.WriteString(", ")
|
||||
}
|
||||
column.serialize(statement, out, FallTrough(options)...)
|
||||
}
|
||||
out.WriteString(")")
|
||||
}
|
||||
|
||||
func (cl ColumnList) serializeForProjection(statement StatementType, out *SQLBuilder) {
|
||||
projections := ColumnListToProjectionList(cl)
|
||||
|
||||
|
|
|
|||
|
|
@ -72,15 +72,15 @@ func (e *ExpressionInterfaceImpl) DESC() OrderByClause {
|
|||
}
|
||||
|
||||
func (e *ExpressionInterfaceImpl) serializeForGroupBy(statement StatementType, out *SQLBuilder) {
|
||||
e.Parent.serialize(statement, out, noWrap)
|
||||
e.Parent.serialize(statement, out, NoWrap)
|
||||
}
|
||||
|
||||
func (e *ExpressionInterfaceImpl) serializeForProjection(statement StatementType, out *SQLBuilder) {
|
||||
e.Parent.serialize(statement, out, noWrap)
|
||||
e.Parent.serialize(statement, out, NoWrap)
|
||||
}
|
||||
|
||||
func (e *ExpressionInterfaceImpl) serializeForOrderBy(statement StatementType, out *SQLBuilder) {
|
||||
e.Parent.serialize(statement, out, noWrap)
|
||||
e.Parent.serialize(statement, out, NoWrap)
|
||||
}
|
||||
|
||||
// Representation of binary operations (e.g. comparisons, arithmetic)
|
||||
|
|
@ -117,7 +117,7 @@ func (c *binaryOperatorExpression) serialize(statement StatementType, out *SQLBu
|
|||
panic("jet: rhs is nil for '" + c.operator + "' operator")
|
||||
}
|
||||
|
||||
wrap := !contains(options, noWrap)
|
||||
wrap := !contains(options, NoWrap)
|
||||
|
||||
if wrap {
|
||||
out.WriteString("(")
|
||||
|
|
@ -125,11 +125,11 @@ func (c *binaryOperatorExpression) serialize(statement StatementType, out *SQLBu
|
|||
|
||||
if serializeOverride := out.Dialect.OperatorSerializeOverride(c.operator); serializeOverride != nil {
|
||||
serializeOverrideFunc := serializeOverride(c.lhs, c.rhs, c.additionalParam)
|
||||
serializeOverrideFunc(statement, out, options...)
|
||||
serializeOverrideFunc(statement, out, FallTrough(options)...)
|
||||
} else {
|
||||
c.lhs.serialize(statement, out)
|
||||
c.lhs.serialize(statement, out, FallTrough(options)...)
|
||||
out.WriteString(c.operator)
|
||||
c.rhs.serialize(statement, out)
|
||||
c.rhs.serialize(statement, out, FallTrough(options)...)
|
||||
}
|
||||
|
||||
if wrap {
|
||||
|
|
@ -163,7 +163,7 @@ func (p *prefixExpression) serialize(statement StatementType, out *SQLBuilder, o
|
|||
panic("jet: nil prefix expression in prefix operator " + p.operator)
|
||||
}
|
||||
|
||||
p.expression.serialize(statement, out)
|
||||
p.expression.serialize(statement, out, FallTrough(options)...)
|
||||
|
||||
out.WriteString(")")
|
||||
}
|
||||
|
|
@ -192,7 +192,7 @@ func (p *postfixOpExpression) serialize(statement StatementType, out *SQLBuilder
|
|||
panic("jet: nil prefix expression in postfix operator " + p.operator)
|
||||
}
|
||||
|
||||
p.expression.serialize(statement, out)
|
||||
p.expression.serialize(statement, out, FallTrough(options)...)
|
||||
|
||||
out.WriteString(p.operator)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -613,7 +613,7 @@ func newWindowFunc(name string, expressions ...Expression) windowExpression {
|
|||
func (f *funcExpressionImpl) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
if serializeOverride := out.Dialect.FunctionSerializeOverride(f.name); serializeOverride != nil {
|
||||
serializeOverrideFunc := serializeOverride(ExpressionListToSerializerList(f.expressions)...)
|
||||
serializeOverrideFunc(statement, out, options...)
|
||||
serializeOverrideFunc(statement, out, FallTrough(options)...)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,5 +33,5 @@ type IntervalImpl struct {
|
|||
|
||||
func (i IntervalImpl) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
out.WriteString("INTERVAL")
|
||||
i.interval.serialize(statement, out, options...)
|
||||
i.interval.serialize(statement, out, FallTrough(options)...)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,18 +2,12 @@ package jet
|
|||
|
||||
const (
|
||||
// DEFAULT is jet equivalent of SQL DEFAULT
|
||||
DEFAULT keywordClause = "DEFAULT"
|
||||
DEFAULT Keyword = "DEFAULT"
|
||||
)
|
||||
|
||||
var (
|
||||
// NULL is jet equivalent of SQL NULL
|
||||
NULL = newNullLiteral()
|
||||
// STAR is jet equivalent of SQL *
|
||||
STAR = newStarLiteral()
|
||||
)
|
||||
// Keyword type
|
||||
type Keyword string
|
||||
|
||||
type keywordClause string
|
||||
|
||||
func (k keywordClause) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
func (k Keyword) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
out.WriteString(string(k))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -278,6 +278,14 @@ func formatNanoseconds(nanoseconds ...time.Duration) string {
|
|||
}
|
||||
|
||||
//--------------------------------------------------//
|
||||
|
||||
var (
|
||||
// NULL is jet equivalent of SQL NULL
|
||||
NULL = newNullLiteral()
|
||||
// STAR is jet equivalent of SQL *
|
||||
STAR = newStarLiteral()
|
||||
)
|
||||
|
||||
type nullLiteral struct {
|
||||
ExpressionInterfaceImpl
|
||||
}
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ func (c *caseOperatorImpl) serialize(statement StatementType, out *SQLBuilder, o
|
|||
out.WriteString("(CASE")
|
||||
|
||||
if c.expression != nil {
|
||||
c.expression.serialize(statement, out)
|
||||
c.expression.serialize(statement, out, FallTrough(options)...)
|
||||
}
|
||||
|
||||
if len(c.when) == 0 || len(c.then) == 0 {
|
||||
|
|
@ -160,15 +160,15 @@ func (c *caseOperatorImpl) serialize(statement StatementType, out *SQLBuilder, o
|
|||
|
||||
for i, when := range c.when {
|
||||
out.WriteString("WHEN")
|
||||
when.serialize(statement, out, noWrap)
|
||||
when.serialize(statement, out, NoWrap)
|
||||
|
||||
out.WriteString("THEN")
|
||||
c.then[i].serialize(statement, out, noWrap)
|
||||
c.then[i].serialize(statement, out, NoWrap)
|
||||
}
|
||||
|
||||
if c.els != nil {
|
||||
out.WriteString("ELSE")
|
||||
c.els.serialize(statement, out, noWrap)
|
||||
c.els.serialize(statement, out, NoWrap)
|
||||
}
|
||||
|
||||
out.WriteString("END)")
|
||||
|
|
|
|||
|
|
@ -5,9 +5,18 @@ type SerializeOption int
|
|||
|
||||
// Serialize options
|
||||
const (
|
||||
noWrap SerializeOption = iota
|
||||
NoWrap SerializeOption = iota
|
||||
SkipNewLine
|
||||
|
||||
fallTroughOptions // fall trough options
|
||||
ShortName
|
||||
)
|
||||
|
||||
// WithFallTrough extends existing serialize options with additional
|
||||
func (s SerializeOption) WithFallTrough(options []SerializeOption) []SerializeOption {
|
||||
return append(FallTrough(options), s)
|
||||
}
|
||||
|
||||
// StatementType is type of the SQL statement
|
||||
type StatementType string
|
||||
|
||||
|
|
@ -42,6 +51,19 @@ func contains(options []SerializeOption, option SerializeOption) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// FallTrough filters fall-trough options from the list
|
||||
func FallTrough(options []SerializeOption) []SerializeOption {
|
||||
var ret []SerializeOption
|
||||
|
||||
for _, option := range options {
|
||||
if option > fallTroughOptions {
|
||||
ret = append(ret, option)
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// ListSerializer serializes list of serializers with separator
|
||||
type ListSerializer struct {
|
||||
Serializers []Serializer
|
||||
|
|
@ -53,6 +75,21 @@ func (s ListSerializer) serialize(statement StatementType, out *SQLBuilder, opti
|
|||
if i > 0 {
|
||||
out.WriteString(s.Separator)
|
||||
}
|
||||
ser.serialize(statement, out)
|
||||
ser.serialize(statement, out, FallTrough(options)...)
|
||||
}
|
||||
}
|
||||
|
||||
// NewSerializerClauseImpl is constructor for Seralizer with list of clauses
|
||||
func NewSerializerClauseImpl(clauses ...Clause) Serializer {
|
||||
return &serializerImpl{Clauses: clauses}
|
||||
}
|
||||
|
||||
type serializerImpl struct {
|
||||
Clauses []Clause
|
||||
}
|
||||
|
||||
func (s serializerImpl) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
for _, clause := range s.Clauses {
|
||||
clause.Serialize(statement, out, FallTrough(options)...)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ func (s *SQLBuilder) WriteString(str string) {
|
|||
|
||||
// WriteIdentifier adds identifier to output SQL
|
||||
func (s *SQLBuilder) WriteIdentifier(name string, alwaysQuote ...bool) {
|
||||
if s.Dialect.IsReservedWord(name) || shouldQuoteIdentifier(name) || len(alwaysQuote) > 0 {
|
||||
if s.shouldQuote(name, alwaysQuote...) {
|
||||
identQuoteChar := string(s.Dialect.IdentifierQuoteChar())
|
||||
s.WriteString(identQuoteChar + name + identQuoteChar)
|
||||
} else {
|
||||
|
|
@ -106,6 +106,10 @@ func (s *SQLBuilder) WriteIdentifier(name string, alwaysQuote ...bool) {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *SQLBuilder) shouldQuote(name string, alwaysQuote ...bool) bool {
|
||||
return s.Dialect.IsReservedWord(name) || shouldQuoteIdentifier(name) || len(alwaysQuote) > 0
|
||||
}
|
||||
|
||||
// WriteByte writes byte to output SQL
|
||||
func (s *SQLBuilder) WriteByte(b byte) {
|
||||
s.write([]byte{b})
|
||||
|
|
|
|||
|
|
@ -41,3 +41,9 @@ func TestArgToString(t *testing.T) {
|
|||
argToString(map[string]bool{})
|
||||
}()
|
||||
}
|
||||
|
||||
func TestFallTrough(t *testing.T) {
|
||||
assert.Equal(t, FallTrough([]SerializeOption{ShortName}), []SerializeOption{ShortName})
|
||||
assert.Equal(t, FallTrough([]SerializeOption{SkipNewLine}), []SerializeOption(nil))
|
||||
assert.Equal(t, FallTrough([]SerializeOption{ShortName, SkipNewLine}), []SerializeOption{ShortName})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ func (s *serializerStatementInterfaceImpl) Sql() (query string, args []interface
|
|||
|
||||
queryData := &SQLBuilder{Dialect: s.dialect}
|
||||
|
||||
s.parent.serialize(s.statementType, queryData, noWrap)
|
||||
s.parent.serialize(s.statementType, queryData, NoWrap)
|
||||
|
||||
query, args = queryData.finalize()
|
||||
return
|
||||
|
|
@ -67,7 +67,7 @@ func (s *serializerStatementInterfaceImpl) Sql() (query string, args []interface
|
|||
func (s *serializerStatementInterfaceImpl) DebugSql() (query string) {
|
||||
sqlBuilder := &SQLBuilder{Dialect: s.dialect, Debug: true}
|
||||
|
||||
s.parent.serialize(s.statementType, sqlBuilder, noWrap)
|
||||
s.parent.serialize(s.statementType, sqlBuilder, NoWrap)
|
||||
|
||||
query, _ = sqlBuilder.finalize()
|
||||
return
|
||||
|
|
@ -157,16 +157,16 @@ func (s *statementImpl) projections() ProjectionList {
|
|||
|
||||
func (s *statementImpl) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
|
||||
if !contains(options, noWrap) {
|
||||
if !contains(options, NoWrap) {
|
||||
out.WriteString("(")
|
||||
out.IncreaseIdent()
|
||||
}
|
||||
|
||||
for _, clause := range s.Clauses {
|
||||
clause.Serialize(statement, out)
|
||||
clause.Serialize(statement, out, FallTrough(options)...)
|
||||
}
|
||||
|
||||
if !contains(options, noWrap) {
|
||||
if !contains(options, NoWrap) {
|
||||
out.DecreaseIdent()
|
||||
out.NewLine()
|
||||
out.WriteString(")")
|
||||
|
|
|
|||
|
|
@ -19,17 +19,15 @@ type Table interface {
|
|||
}
|
||||
|
||||
// NewTable creates new table with schema Name, table Name and list of columns
|
||||
func NewTable(schemaName, name string, column ColumnExpression, columns ...ColumnExpression) SerializerTable {
|
||||
|
||||
columnList := append([]ColumnExpression{column}, columns...)
|
||||
func NewTable(schemaName, name string, columns ...ColumnExpression) SerializerTable {
|
||||
|
||||
t := tableImpl{
|
||||
schemaName: schemaName,
|
||||
name: name,
|
||||
columnList: columnList,
|
||||
columnList: columns,
|
||||
}
|
||||
|
||||
for _, c := range columnList {
|
||||
for _, c := range columns {
|
||||
c.setTableName(name)
|
||||
}
|
||||
|
||||
|
|
@ -156,7 +154,7 @@ func (t *joinTableImpl) serialize(statement StatementType, out *SQLBuilder, opti
|
|||
panic("jet: left hand side of join operation is nil table")
|
||||
}
|
||||
|
||||
t.lhs.serialize(statement, out)
|
||||
t.lhs.serialize(statement, out, FallTrough(options)...)
|
||||
|
||||
out.NewLine()
|
||||
|
||||
|
|
|
|||
|
|
@ -63,6 +63,22 @@ func SerializeColumnNames(columns []Column, out *SQLBuilder) {
|
|||
}
|
||||
}
|
||||
|
||||
// SerializeColumnExpressionNames func
|
||||
func SerializeColumnExpressionNames(columns []ColumnExpression, statementType StatementType,
|
||||
out *SQLBuilder, options ...SerializeOption) {
|
||||
for i, col := range columns {
|
||||
if i > 0 {
|
||||
out.WriteString(", ")
|
||||
}
|
||||
|
||||
if col == nil {
|
||||
panic("jet: nil column in columns list")
|
||||
}
|
||||
|
||||
col.serialize(statementType, out, options...)
|
||||
}
|
||||
}
|
||||
|
||||
// ExpressionListToSerializerList converts list of expressions to list of serializers
|
||||
func ExpressionListToSerializerList(expressions []Expression) []Serializer {
|
||||
var ret []Serializer
|
||||
|
|
@ -85,7 +101,8 @@ func ColumnListToProjectionList(columns []ColumnExpression) []Projection {
|
|||
return ret
|
||||
}
|
||||
|
||||
func valueToClause(value interface{}) Serializer {
|
||||
// ToSerializerValue creates Serializer type from the value
|
||||
func ToSerializerValue(value interface{}) Serializer {
|
||||
if clause, ok := value.(Serializer); ok {
|
||||
return clause
|
||||
}
|
||||
|
|
@ -148,7 +165,7 @@ func UnwindRowFromValues(value interface{}, values []interface{}) []Serializer {
|
|||
allValues := append([]interface{}{value}, values...)
|
||||
|
||||
for _, val := range allValues {
|
||||
row = append(row, valueToClause(val))
|
||||
row = append(row, ToSerializerValue(val))
|
||||
}
|
||||
|
||||
return row
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ func (w *commonWindowImpl) serialize(statement StatementType, out *SQLBuilder, o
|
|||
w.expression.serialize(statement, out)
|
||||
if w.window != nil {
|
||||
out.WriteString("OVER")
|
||||
w.window.serialize(statement, out)
|
||||
w.window.serialize(statement, out, FallTrough(options)...)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -49,7 +49,7 @@ func (f *windowExpressionImpl) OVER(window ...Window) Expression {
|
|||
}
|
||||
|
||||
func (f *windowExpressionImpl) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
f.commonWindowImpl.serialize(statement, out)
|
||||
f.commonWindowImpl.serialize(statement, out, FallTrough(options)...)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------
|
||||
|
|
@ -80,7 +80,7 @@ func (f *floatWindowExpressionImpl) OVER(window ...Window) FloatExpression {
|
|||
}
|
||||
|
||||
func (f *floatWindowExpressionImpl) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
f.commonWindowImpl.serialize(statement, out)
|
||||
f.commonWindowImpl.serialize(statement, out, FallTrough(options)...)
|
||||
}
|
||||
|
||||
// ------------------------------------------------
|
||||
|
|
@ -111,7 +111,7 @@ func (f *integerWindowExpressionImpl) OVER(window ...Window) IntegerExpression {
|
|||
}
|
||||
|
||||
func (f *integerWindowExpressionImpl) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
f.commonWindowImpl.serialize(statement, out)
|
||||
f.commonWindowImpl.serialize(statement, out, FallTrough(options)...)
|
||||
}
|
||||
|
||||
// ------------------------------------------------
|
||||
|
|
@ -142,5 +142,5 @@ func (f *boolWindowExpressionImpl) OVER(window ...Window) BoolExpression {
|
|||
}
|
||||
|
||||
func (f *boolWindowExpressionImpl) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
f.commonWindowImpl.serialize(statement, out)
|
||||
f.commonWindowImpl.serialize(statement, out, FallTrough(options)...)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ func newWindowImpl(parent Window) *windowImpl {
|
|||
}
|
||||
|
||||
func (w *windowImpl) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
|
||||
if !contains(options, noWrap) {
|
||||
if !contains(options, NoWrap) {
|
||||
out.WriteByte('(')
|
||||
}
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ func (w *windowImpl) serialize(statement StatementType, out *SQLBuilder, options
|
|||
serializeExpressionList(statement, w.partitionBy, ", ", out)
|
||||
}
|
||||
w.orderBy.SkipNewLine = true
|
||||
w.orderBy.Serialize(statement, out)
|
||||
w.orderBy.Serialize(statement, out, FallTrough(options)...)
|
||||
|
||||
if w.frameUnits != "" {
|
||||
out.WriteString(w.frameUnits)
|
||||
|
|
@ -55,7 +55,7 @@ func (w *windowImpl) serialize(statement StatementType, out *SQLBuilder, options
|
|||
}
|
||||
}
|
||||
|
||||
if !contains(options, noWrap) {
|
||||
if !contains(options, NoWrap) {
|
||||
out.WriteByte(')')
|
||||
}
|
||||
}
|
||||
|
|
@ -139,7 +139,7 @@ func (f *frameExtentImpl) serialize(statement StatementType, out *SQLBuilder, op
|
|||
if f == nil {
|
||||
return
|
||||
}
|
||||
f.offset.serialize(statement, out)
|
||||
f.offset.serialize(statement, out, FallTrough(options)...)
|
||||
|
||||
if f.preceding {
|
||||
out.WriteString("PRECEDING")
|
||||
|
|
@ -152,12 +152,12 @@ func (f *frameExtentImpl) serialize(statement StatementType, out *SQLBuilder, op
|
|||
|
||||
// Window function keywords
|
||||
var (
|
||||
UNBOUNDED = keywordClause("UNBOUNDED")
|
||||
UNBOUNDED = Keyword("UNBOUNDED")
|
||||
CURRENT_ROW = frameExtentKeyword{"CURRENT ROW"}
|
||||
)
|
||||
|
||||
type frameExtentKeyword struct {
|
||||
keywordClause
|
||||
Keyword
|
||||
}
|
||||
|
||||
func (f frameExtentKeyword) isFrameExtent() {}
|
||||
|
|
@ -180,7 +180,7 @@ func (w windowName) serialize(statement StatementType, out *SQLBuilder, options
|
|||
out.WriteByte('(')
|
||||
|
||||
out.WriteString(w.name)
|
||||
w.windowImpl.serialize(statement, out, noWrap)
|
||||
w.windowImpl.serialize(statement, out, NoWrap.WithFallTrough(options)...)
|
||||
|
||||
out.WriteByte(')')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
"github.com/go-jet/jet/internal/utils"
|
||||
"github.com/go-jet/jet/qrm"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
|
@ -110,17 +111,17 @@ func AssertDebugStatementSql(t *testing.T, query jet.Statement, expectedQuery st
|
|||
_, args := query.Sql()
|
||||
|
||||
if len(expectedArgs) > 0 {
|
||||
AssertDeepEqual(t, args, expectedArgs)
|
||||
AssertDeepEqual(t, args, expectedArgs, "arguments are not equal")
|
||||
}
|
||||
|
||||
debuqSql := query.DebugSql()
|
||||
assert.Equal(t, debuqSql, expectedQuery)
|
||||
}
|
||||
|
||||
// AssertClauseSerialize checks if clause serialize produces expected query and args
|
||||
func AssertClauseSerialize(t *testing.T, dialect jet.Dialect, clause jet.Serializer, query string, args ...interface{}) {
|
||||
// AssertSerialize checks if clause serialize produces expected query and args
|
||||
func AssertSerialize(t *testing.T, dialect jet.Dialect, serializer jet.Serializer, query string, args ...interface{}) {
|
||||
out := jet.SQLBuilder{Dialect: dialect}
|
||||
jet.Serialize(clause, jet.SelectStatementType, &out)
|
||||
jet.Serialize(serializer, jet.SelectStatementType, &out)
|
||||
|
||||
//fmt.Println(out.Buff.String())
|
||||
|
||||
|
|
@ -131,8 +132,20 @@ func AssertClauseSerialize(t *testing.T, dialect jet.Dialect, clause jet.Seriali
|
|||
}
|
||||
}
|
||||
|
||||
// AssertDebugClauseSerialize checks if clause serialize produces expected debug query and args
|
||||
func AssertDebugClauseSerialize(t *testing.T, dialect jet.Dialect, clause jet.Serializer, query string, args ...interface{}) {
|
||||
// AssertClauseSerialize checks if clause serialize produces expected query and args
|
||||
func AssertClauseSerialize(t *testing.T, dialect jet.Dialect, clause jet.Clause, query string, args ...interface{}) {
|
||||
out := jet.SQLBuilder{Dialect: dialect}
|
||||
clause.Serialize(jet.SelectStatementType, &out)
|
||||
|
||||
require.Equal(t, out.Buff.String(), query)
|
||||
|
||||
if len(args) > 0 {
|
||||
AssertDeepEqual(t, out.Args, args)
|
||||
}
|
||||
}
|
||||
|
||||
// AssertDebugSerialize checks if clause serialize produces expected debug query and args
|
||||
func AssertDebugSerialize(t *testing.T, dialect jet.Dialect, clause jet.Serializer, query string, args ...interface{}) {
|
||||
out := jet.SQLBuilder{Dialect: dialect, Debug: true}
|
||||
jet.Serialize(clause, jet.SelectStatementType, &out)
|
||||
|
||||
|
|
@ -153,8 +166,8 @@ func AssertPanicErr(t *testing.T, fun func(), errorStr string) {
|
|||
fun()
|
||||
}
|
||||
|
||||
// AssertClauseSerializeErr check if clause serialize panics with errString
|
||||
func AssertClauseSerializeErr(t *testing.T, dialect jet.Dialect, clause jet.Serializer, errString string) {
|
||||
// AssertSerializeErr check if clause serialize panics with errString
|
||||
func AssertSerializeErr(t *testing.T, dialect jet.Dialect, clause jet.Serializer, errString string) {
|
||||
defer func() {
|
||||
r := recover()
|
||||
assert.Equal(t, r, errString)
|
||||
|
|
@ -191,9 +204,8 @@ func AssertFileContent(t *testing.T, filePath string, contentBegin string, expec
|
|||
|
||||
beginIndex := bytes.Index(enumFileData, []byte(contentBegin))
|
||||
|
||||
//fmt.Println("-"+string(enumFileData[beginIndex:])+"-")
|
||||
|
||||
AssertDeepEqual(t, string(enumFileData[beginIndex:]), expectedContent)
|
||||
//AssertDeepEqual(t, string(enumFileData[beginIndex:]), expectedContent)
|
||||
require.Equal(t, string(enumFileData[beginIndex:]), expectedContent)
|
||||
}
|
||||
|
||||
// AssertFileNamesEqual check if all filesInfos are contained in fileNames
|
||||
|
|
@ -212,6 +224,6 @@ func AssertFileNamesEqual(t *testing.T, fileInfos []os.FileInfo, fileNames ...st
|
|||
}
|
||||
|
||||
// AssertDeepEqual checks if actual and expected objects are deeply equal.
|
||||
func AssertDeepEqual(t *testing.T, actual, expected interface{}) {
|
||||
assert.True(t, cmp.Equal(actual, expected))
|
||||
func AssertDeepEqual(t *testing.T, actual, expected interface{}, msg ...string) {
|
||||
assert.True(t, cmp.Equal(actual, expected), msg)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue