Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 10 additions & 17 deletions cte.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,13 @@ func init() {
clone.SetCustomFunc(t, func(allocator *clone.Allocator, old, new reflect.Value) {
cloned := allocator.CloneSlowly(old)
new.Set(cloned)

cteb := cloned.Addr().Interface().(*CTEBuilder)
for i, b := range cteb.queries {
cteb.args.Replace(cteb.queryBuilderVars[i], b)
}
})
}

// CTEBuilder is a CTE (Common Table Expression) builder.
type CTEBuilder struct {
recursive bool
queries []*CTEQueryBuilder
queryBuilderVars []string
recursive bool
queries []*CTEQueryBuilder

args *Args

Expand All @@ -66,14 +60,8 @@ var _ Builder = new(CTEBuilder)

// With sets the CTE name and columns.
func (cteb *CTEBuilder) With(queries ...*CTEQueryBuilder) *CTEBuilder {
queryBuilderVars := make([]string, 0, len(queries))

for _, query := range queries {
queryBuilderVars = append(queryBuilderVars, cteb.args.Add(query))
}

cteb.queries = append([]*CTEQueryBuilder(nil), queries...)
cteb.queryBuilderVars = queryBuilderVars
cteb.marker = cteMarkerAfterWith
return cteb
}
Expand Down Expand Up @@ -118,12 +106,17 @@ func (cteb *CTEBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{}
buf := newStringBuilder()
cteb.injection.WriteTo(buf, cteMarkerInit)

if len(cteb.queryBuilderVars) > 0 {
if len(cteb.queries) > 0 {
buf.WriteLeadingString("WITH ")
if cteb.recursive {
buf.WriteString("RECURSIVE ")
}
buf.WriteStrings(cteb.queryBuilderVars, ", ")
queryBuilderVars := make([]string, 0, len(cteb.queries))

for _, query := range cteb.queries {
queryBuilderVars = append(queryBuilderVars, cteb.args.Add(query))
}
buf.WriteStrings(queryBuilderVars, ", ")
}

cteb.injection.WriteTo(buf, cteMarkerAfterWith)
Expand All @@ -150,7 +143,7 @@ func (cteb *CTEBuilder) SQL(sql string) *CTEBuilder {

// TableNames returns all table names in a CTE.
func (cteb *CTEBuilder) TableNames() []string {
if len(cteb.queryBuilderVars) == 0 {
if len(cteb.queries) == 0 {
return nil
}

Expand Down
15 changes: 5 additions & 10 deletions ctequery.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,14 @@ func init() {
clone.SetCustomFunc(t, func(allocator *clone.Allocator, old, new reflect.Value) {
cloned := allocator.CloneSlowly(old)
new.Set(cloned)

ctetb := cloned.Addr().Interface().(*CTEQueryBuilder)
ctetb.args.Replace(ctetb.builderVar, ctetb.builder)
})
}

// CTEQueryBuilder is a builder to build one table in CTE (Common Table Expression).
type CTEQueryBuilder struct {
name string
cols []string
builder Builder
builderVar string
name string
cols []string
builder Builder

// if true, this query's table name will be automatically added to the table list
// in FROM clause of SELECT statement.
Expand Down Expand Up @@ -87,7 +83,6 @@ func (ctetb *CTEQueryBuilder) Table(name string, cols ...string) *CTEQueryBuilde
// As sets the builder to select data.
func (ctetb *CTEQueryBuilder) As(builder Builder) *CTEQueryBuilder {
ctetb.builder = builder
ctetb.builderVar = ctetb.args.Add(builder)
ctetb.marker = cteQueryMarkerAfterAs
return ctetb
}
Expand Down Expand Up @@ -131,9 +126,9 @@ func (ctetb *CTEQueryBuilder) BuildWithFlavor(flavor Flavor, initialArg ...inter
ctetb.injection.WriteTo(buf, cteQueryMarkerAfterTable)
}

if ctetb.builderVar != "" {
if ctetb.builder != nil {
buf.WriteLeadingString("AS (")
buf.WriteString(ctetb.builderVar)
buf.WriteString(ctetb.args.Add(ctetb.builder))
buf.WriteRune(')')

ctetb.injection.WriteTo(buf, cteQueryMarkerAfterAs)
Expand Down
15 changes: 3 additions & 12 deletions delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ func newDeleteBuilder() *DeleteBuilder {
proxy := &whereClauseProxy{}
return &DeleteBuilder{
whereClauseProxy: proxy,
whereClauseExpr: args.Add(proxy),

Cond: Cond{
Args: args,
Expand All @@ -50,10 +49,6 @@ func init() {
clone.SetCustomFunc(t, func(allocator *clone.Allocator, old, new reflect.Value) {
cloned := allocator.CloneSlowly(old)
new.Set(cloned)

db := cloned.Addr().Interface().(*DeleteBuilder)
db.args.Replace(db.whereClauseExpr, db.whereClauseProxy)
db.args.Replace(db.cteBuilderVar, db.cteBuilder)
})
}

Expand All @@ -63,10 +58,7 @@ type DeleteBuilder struct {
Cond

whereClauseProxy *whereClauseProxy
whereClauseExpr string

cteBuilderVar string
cteBuilder *CTEBuilder
cteBuilder *CTEBuilder

tables []string
orderByCols []string
Expand All @@ -90,7 +82,6 @@ func DeleteFrom(table ...string) *DeleteBuilder {
// With sets WITH clause (the Common Table Expression) before DELETE.
func (db *DeleteBuilder) With(builder *CTEBuilder) *DeleteBuilder {
db.marker = deleteMarkerAfterWith
db.cteBuilderVar = db.Var(builder)
db.cteBuilder = builder
return db
}
Expand Down Expand Up @@ -210,7 +201,7 @@ func (db *DeleteBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{
db.injection.WriteTo(buf, deleteMarkerInit)

if db.cteBuilder != nil {
buf.WriteLeadingString(db.cteBuilderVar)
buf.WriteLeadingString(db.Var(db.cteBuilder))
db.injection.WriteTo(buf, deleteMarkerAfterWith)
}

Expand All @@ -229,7 +220,7 @@ func (db *DeleteBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{
db.whereClauseProxy.WhereClause = nil
}()

buf.WriteLeadingString(db.whereClauseExpr)
buf.WriteLeadingString(db.args.Add(db.whereClauseProxy))
db.injection.WriteTo(buf, deleteMarkerAfterWhere)
}

Expand Down
16 changes: 4 additions & 12 deletions select.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ func newSelectBuilder() *SelectBuilder {
proxy := &whereClauseProxy{}
return &SelectBuilder{
whereClauseProxy: proxy,
whereClauseExpr: args.Add(proxy),

Cond: Cond{
Args: args,
Expand All @@ -69,10 +68,6 @@ func init() {
clone.SetCustomFunc(t, func(allocator *clone.Allocator, old, new reflect.Value) {
cloned := allocator.CloneSlowly(old)
new.Set(cloned)

sb := cloned.Addr().Interface().(*SelectBuilder)
sb.args.Replace(sb.whereClauseExpr, sb.whereClauseProxy)
sb.args.Replace(sb.cteBuilderVar, sb.cteBuilder)
})
}

Expand All @@ -82,10 +77,8 @@ type SelectBuilder struct {
Cond

whereClauseProxy *whereClauseProxy
whereClauseExpr string

cteBuilderVar string
cteBuilder *CTEBuilder
cteBuilder *CTEBuilder

distinct bool
tables []string
Expand Down Expand Up @@ -140,7 +133,6 @@ func (sb *SelectBuilder) TableNames() []string {
// With sets WITH clause (the Common Table Expression) before SELECT.
func (sb *SelectBuilder) With(builder *CTEBuilder) *SelectBuilder {
sb.marker = selectMarkerAfterWith
sb.cteBuilderVar = sb.Var(builder)
sb.cteBuilder = builder
return sb
}
Expand Down Expand Up @@ -344,8 +336,8 @@ func (sb *SelectBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{

oraclePage := flavor == Oracle && (len(sb.limitVar) > 0 || len(sb.offsetVar) > 0)

if sb.cteBuilderVar != "" {
buf.WriteLeadingString(sb.cteBuilderVar)
if sb.cteBuilder != nil {
buf.WriteLeadingString(sb.Var(sb.cteBuilder))
sb.injection.WriteTo(buf, selectMarkerAfterWith)
}

Expand Down Expand Up @@ -434,7 +426,7 @@ func (sb *SelectBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{
sb.whereClauseProxy.WhereClause = nil
}()

buf.WriteLeadingString(sb.whereClauseExpr)
buf.WriteLeadingString(sb.args.Add(sb.whereClauseProxy))
sb.injection.WriteTo(buf, selectMarkerAfterWhere)
}

Expand Down
24 changes: 6 additions & 18 deletions union.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,6 @@ func init() {
clone.SetCustomFunc(t, func(allocator *clone.Allocator, old, new reflect.Value) {
cloned := allocator.CloneSlowly(old)
new.Set(cloned)

ub := cloned.Addr().Interface().(*UnionBuilder)
for i, b := range ub.builders {
ub.args.Replace(ub.builderVars[i], b)
}
})
}

Expand All @@ -61,8 +56,7 @@ type UnionBuilder struct {
limitVar string
offsetVar string

builders []Builder
builderVars []string
builders []Builder

args *Args

Expand Down Expand Up @@ -93,15 +87,9 @@ func (ub *UnionBuilder) UnionAll(builders ...Builder) *UnionBuilder {
}

func (ub *UnionBuilder) union(opt string, builders ...Builder) *UnionBuilder {
builderVars := make([]string, 0, len(builders))

for _, b := range builders {
builderVars = append(builderVars, ub.Var(b))
}

ub.opt = opt
ub.builders = append([]Builder(nil), builders...)
ub.builderVars = builderVars
ub.marker = unionMarkerAfterUnion
return ub
}
Expand Down Expand Up @@ -172,7 +160,7 @@ func (ub *UnionBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{}
nestedSelect := (flavor == Oracle && (len(ub.limitVar) > 0 || len(ub.offsetVar) > 0)) ||
(flavor == Informix && len(ub.limitVar) > 0)

if len(ub.builderVars) > 0 {
if len(ub.builders) > 0 {
needParen := flavor != SQLite

if nestedSelect {
Expand All @@ -181,20 +169,20 @@ func (ub *UnionBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{}

if needParen {
buf.WriteLeadingString("(")
buf.WriteString(ub.builderVars[0])
buf.WriteString(ub.Var(ub.builders[0]))
buf.WriteRune(')')
} else {
buf.WriteLeadingString(ub.builderVars[0])
buf.WriteLeadingString(ub.Var(ub.builders[0]))
}

for _, b := range ub.builderVars[1:] {
for _, b := range ub.builders[1:] {
buf.WriteString(ub.opt)

if needParen {
buf.WriteRune('(')
}

buf.WriteString(b)
buf.WriteString(ub.Var(b))

if needParen {
buf.WriteRune(')')
Expand Down
15 changes: 3 additions & 12 deletions update.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ func newUpdateBuilder() *UpdateBuilder {
proxy := &whereClauseProxy{}
return &UpdateBuilder{
whereClauseProxy: proxy,
whereClauseExpr: args.Add(proxy),

Cond: Cond{
Args: args,
Expand All @@ -52,10 +51,6 @@ func init() {
clone.SetCustomFunc(t, func(allocator *clone.Allocator, old, new reflect.Value) {
cloned := allocator.CloneSlowly(old)
new.Set(cloned)

ub := cloned.Addr().Interface().(*UpdateBuilder)
ub.args.Replace(ub.whereClauseExpr, ub.whereClauseProxy)
ub.args.Replace(ub.cteBuilderVar, ub.cteBuilder)
})
}

Expand All @@ -65,10 +60,7 @@ type UpdateBuilder struct {
Cond

whereClauseProxy *whereClauseProxy
whereClauseExpr string

cteBuilderVar string
cteBuilder *CTEBuilder
cteBuilder *CTEBuilder

tables []string
assignments []string
Expand All @@ -93,7 +85,6 @@ func Update(table ...string) *UpdateBuilder {
// With sets WITH clause (the Common Table Expression) before UPDATE.
func (ub *UpdateBuilder) With(builder *CTEBuilder) *UpdateBuilder {
ub.marker = updateMarkerAfterWith
ub.cteBuilderVar = ub.Var(builder)
ub.cteBuilder = builder
return ub
}
Expand Down Expand Up @@ -271,7 +262,7 @@ func (ub *UpdateBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{
ub.injection.WriteTo(buf, updateMarkerInit)

if ub.cteBuilder != nil {
buf.WriteLeadingString(ub.cteBuilderVar)
buf.WriteLeadingString(ub.Var(ub.cteBuilder))
ub.injection.WriteTo(buf, updateMarkerAfterWith)
}

Expand Down Expand Up @@ -319,7 +310,7 @@ func (ub *UpdateBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{
ub.whereClauseProxy.WhereClause = nil
}()

buf.WriteLeadingString(ub.whereClauseExpr)
buf.WriteLeadingString(ub.args.Add(ub.whereClauseProxy))
ub.injection.WriteTo(buf, updateMarkerAfterWhere)
}

Expand Down
8 changes: 4 additions & 4 deletions update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,10 @@ func TestUpdateAssignments(t *testing.T) {
cases := map[string]func(ub *UpdateBuilder) string{
"f = f + 1|[]": func(ub *UpdateBuilder) string { return ub.Incr("f") },
"f = f - 1|[]": func(ub *UpdateBuilder) string { return ub.Decr("f") },
"f = f + $1|[123]": func(ub *UpdateBuilder) string { return ub.Add("f", 123) },
"f = f - $1|[123]": func(ub *UpdateBuilder) string { return ub.Sub("f", 123) },
"f = f * $1|[123]": func(ub *UpdateBuilder) string { return ub.Mul("f", 123) },
"f = f / $1|[123]": func(ub *UpdateBuilder) string { return ub.Div("f", 123) },
"f = f + $0|[123]": func(ub *UpdateBuilder) string { return ub.Add("f", 123) },
"f = f - $0|[123]": func(ub *UpdateBuilder) string { return ub.Sub("f", 123) },
"f = f * $0|[123]": func(ub *UpdateBuilder) string { return ub.Mul("f", 123) },
"f = f / $0|[123]": func(ub *UpdateBuilder) string { return ub.Div("f", 123) },
}

for expected, f := range cases {
Expand Down