Skip to content

Commit

Permalink
Add API: BuilderX.Sub(x string, sub func(* BuilderX)) (#53)
Browse files Browse the repository at this point in the history
  • Loading branch information
sim-wangyan committed Nov 3, 2023
1 parent f53b6ac commit 612190e
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 58 deletions.
48 changes: 32 additions & 16 deletions builder_x.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ func (x *BuilderX) ResultKeys(resultKeys ...string) *BuilderX {
}

func (x *BuilderX) Source(po Po) *BuilderX {
if len(x.sxs) == 0 {
x.sxs = append(x.sxs, new(SourceX))
}
x.sxs[0].po = po
return x
}
Expand Down Expand Up @@ -117,28 +120,41 @@ func (x *BuilderX) Agg(fn string, vs ...interface{}) *BuilderX {
return x
}

func (builder *BuilderX) Build() *Built {
if builder == nil {
func (x *BuilderX) Build() *Built {
if x == nil {
panic("sqlxb.Builder is nil")
}
builder.optimizeSourceBuilder()
x.optimizeSourceBuilder()
built := Built{
ResultKeys: builder.resultKeys,
ConditionX: builder.bbs,
Sorts: builder.sorts,
Aggs: builder.aggs,
Havings: builder.havings,
GroupBys: builder.groupBys,
OrSourceSql: builder.orSourceSql,
Sbs: builder.sxs,
Svs: builder.svs,

Po: builder.po,
ResultKeys: x.resultKeys,
ConditionX: x.bbs,
Sorts: x.sorts,
Aggs: x.aggs,
Havings: x.havings,
GroupBys: x.groupBys,
OrSourceSql: x.orSourceSql,
Sbs: x.sxs,
Svs: x.svs,

Po: x.po,
}

if builder.pageBuilder != nil {
built.PageCondition = &builder.pageBuilder.condition
if x.pageBuilder != nil {
built.PageCondition = &x.pageBuilder.condition
}

return &built
}

func (x *BuilderX) Sub(s string, sub func(sub *BuilderX)) *BuilderX {

b := new(BuilderX)
sub(b)
bb := Bb{
op: SUB,
key: s,
value: b,
}
x.bbs = append(x.bbs, bb)
return x
}
3 changes: 2 additions & 1 deletion oper.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
Expand All @@ -19,6 +19,7 @@ package sqlxb
const (
X = ""
AGG = ""
SUB = "SUB"
AND = "AND"
OR = "OR"
AND_SUB = AND
Expand Down
36 changes: 18 additions & 18 deletions source_builder_optimization.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,20 @@ import (
"strings"
)

func (builder *BuilderX) WithoutOptimization() *BuilderX {
builder.isWithoutOptimization = true
return builder
func (x *BuilderX) WithoutOptimization() *BuilderX {
x.isWithoutOptimization = true
return x
}

func (builder *BuilderX) optimizeSourceBuilder() {
if builder.isWithoutOptimization {
func (x *BuilderX) optimizeSourceBuilder() {
if x.isWithoutOptimization {
return
}
if len(builder.resultKeys) == 0 || len(builder.sxs) < 2 {
if len(x.resultKeys) == 0 || len(x.sxs) < 2 {
return
}

builder.removeSourceBuilder(builder.sxs, func(useds *[]*SourceX, ele *SourceX, i int) bool {
x.removeSourceBuilder(x.sxs, func(useds *[]*SourceX, ele *SourceX, i int) bool {

if ele.sub != nil && (ele.join != nil && !strings.Contains(ele.join.join, "LEFT")) {
return false
Expand All @@ -44,7 +44,7 @@ func (builder *BuilderX) optimizeSourceBuilder() {
return false
}
}
for _, v := range *builder.conds() {
for _, v := range *x.conds() {
if ele.po != nil && strings.Contains(v, ele.po.TableName()+".") { //has return or condition
return false
}
Expand All @@ -54,8 +54,8 @@ func (builder *BuilderX) optimizeSourceBuilder() {
}

//target
for j := len(builder.sxs) - 1; j > i; j-- {
var sb = builder.sxs[j]
for j := len(x.sxs) - 1; j > i; j-- {
var sb = x.sxs[j]

if sb.join != nil && sb.join.on != nil && sb.join.on.bbs != nil {
for _, bb := range sb.join.on.bbs {
Expand All @@ -74,22 +74,22 @@ func (builder *BuilderX) optimizeSourceBuilder() {
})
}

func (builder *BuilderX) conds() *[]string {
func (x *BuilderX) conds() *[]string {
condArr := []string{}
for _, v := range builder.resultKeys {
for _, v := range x.resultKeys {
condArr = append(condArr, v)
}

bbps := builder.CondBuilder.bbs
bbps := x.CondBuilder.bbs

if bbps != nil {
for _, v := range bbps {
condArr = append(condArr, v.key)
}
}

if len(builder.sxs) > 0 {
for _, sb := range builder.sxs {
if len(x.sxs) > 0 {
for _, sb := range x.sxs {
if sb.join != nil && sb.join.on != nil && sb.join.on.bbs != nil {
for i, bb := range sb.join.on.bbs {
if i > 0 {
Expand All @@ -102,7 +102,7 @@ func (builder *BuilderX) conds() *[]string {
return &condArr
}

func (builder *BuilderX) removeSourceBuilder(sbs []*SourceX, canRemove canRemove) {
func (x *BuilderX) removeSourceBuilder(sbs []*SourceX, canRemove canRemove) {
useds := []*SourceX{}
j := 0
leng := len(sbs)
Expand All @@ -119,10 +119,10 @@ func (builder *BuilderX) removeSourceBuilder(sbs []*SourceX, canRemove canRemove
j = 0
if length < leng {
for i := length - 1; i > -1; i-- { //reverse
(builder.sxs)[j] = useds[i]
(x.sxs)[j] = useds[i]
j++
}
builder.sxs = (builder.sxs)[:j]
x.sxs = (x.sxs)[:j]
}
}

Expand Down
6 changes: 3 additions & 3 deletions to_result_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
Expand Down Expand Up @@ -57,7 +57,7 @@ func buildResultKey(key string, km map[string]string) string {
return key
}

func (built *Built) toResultKeyScript(bp *strings.Builder, km map[string]string) {
func (built *Built) toResultKeySql(bp *strings.Builder, km map[string]string) {
bp.WriteString(SELECT)
if built.ResultKeys == nil {
bp.WriteString(STAR)
Expand All @@ -80,7 +80,7 @@ func (built *Built) toResultKeyScript(bp *strings.Builder, km map[string]string)
}
}

func (built *Built) toResultKeyScriptOfCount(bpCount *strings.Builder) {
func (built *Built) toResultKeySqlOfCount(bpCount *strings.Builder) {
if built.ResultKeys != nil && len(built.ResultKeys) > 0 {
bpCount.WriteString(COUNT_KEY_SCRIPT_LEFT)
bpCount.WriteString(built.ResultKeys[0])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
"strings"
)

func (built *Built) toSourceScriptBySql(bp *strings.Builder) bool {
func (built *Built) toSourceSqlBySql(bp *strings.Builder) bool {
if (len(built.Sbs) == 1) && (built.OrSourceSql != "") {
var sql = strings.Trim(built.OrSourceSql, SPACE)
if strings.HasPrefix(sql, "FROM") {
Expand All @@ -33,7 +33,7 @@ func (built *Built) toSourceScriptBySql(bp *strings.Builder) bool {
return false
}

func (built *Built) toSourceScriptByBuilder(vs *[]interface{}, sb *SourceX, bp *strings.Builder) {
func (built *Built) toSourceSqlByBuilder(vs *[]interface{}, sb *SourceX, bp *strings.Builder) {
if sb.join != nil { //JOIN
bp.WriteString(SPACE)
bp.WriteString(sb.join.join)
Expand Down Expand Up @@ -62,7 +62,7 @@ func (built *Built) toSourceScriptByBuilder(vs *[]interface{}, sb *SourceX, bp *
bp.WriteString(sb.s)
} else {
bp.WriteString(ON_SCRIPT)
built.toConditionScript(sb.join.on.bbs, bp, vs, nil)
built.toConditionSql(sb.join.on.bbs, bp, vs, nil)
}
}
}
49 changes: 32 additions & 17 deletions to_sql.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,27 +39,27 @@ type Built struct {
Po Po
}

func (built *Built) toSourceScriptOfCount(bpCount *strings.Builder) {
built.toSourceScript(nil, bpCount)
func (built *Built) toSourceSqlOfCount(bpCount *strings.Builder) {
built.toSourceSql(nil, bpCount)
}

func (built *Built) toConditionScriptOfCount(bbs []Bb, bpCount *strings.Builder) {
built.toConditionScript(bbs, bpCount, nil, nil)
func (built *Built) toConditionSqlOfCount(bbs []Bb, bpCount *strings.Builder) {
built.toConditionSql(bbs, bpCount, nil, nil)
}

func (built *Built) toGroupBySqlOfCount(bpCount *strings.Builder) {
built.toGroupBySql(bpCount)
}

func (built *Built) toSourceScript(vs *[]interface{}, bp *strings.Builder) {
func (built *Built) toSourceSql(vs *[]interface{}, bp *strings.Builder) {
if built.Po == nil {

if built.toSourceScriptBySql(bp) {
if built.toSourceSqlBySql(bp) {
return
}

for _, sb := range built.Sbs {
built.toSourceScriptByBuilder(vs, sb, bp)
built.toSourceSqlByBuilder(vs, sb, bp)
}
} else {
bp.WriteString(built.Po.TableName())
Expand Down Expand Up @@ -101,8 +101,23 @@ func (built *Built) toBb(bb Bb, bp *strings.Builder, vs *[]interface{}) {
return
}
bp.WriteString(BEGIN_SUB)
built.toConditionScript(bb.subs, bp, vs, nil)
built.toConditionSql(bb.subs, bp, vs, nil)
bp.WriteString(END_SUB)
case SUB:
var bx = *bb.value.(*BuilderX)
ss, _ := bx.Build().sqlData(vs, nil)
ss = BEGIN_SUB + ss + END_SUB
if bb.key != "" {
if strings.Contains(bb.key, PLACE_HOLDER) {
bp.WriteString(strings.ReplaceAll(bb.key, PLACE_HOLDER, ss))
} else {
bp.WriteString(bb.key)
bp.WriteString(SPACE)
bp.WriteString(ss)
}
} else {
bp.WriteString(ss)
}
default:
bp.WriteString(bb.key)
bp.WriteString(SPACE)
Expand All @@ -114,7 +129,7 @@ func (built *Built) toBb(bb Bb, bp *strings.Builder, vs *[]interface{}) {
}
}

func (built *Built) toConditionScript(bbs []Bb, bp *strings.Builder, vs *[]interface{}, filterLast func() *Bb) {
func (built *Built) toConditionSql(bbs []Bb, bp *strings.Builder, vs *[]interface{}, filterLast func() *Bb) {

length := len(bbs)

Expand Down Expand Up @@ -179,7 +194,7 @@ func (built *Built) toHavingSql(vs *[]interface{}, bp *strings.Builder) {
return
}
bp.WriteString(HAVING)
built.toConditionScript(built.Havings, bp, vs, nil)
built.toConditionSql(built.Havings, bp, vs, nil)
}

func (built *Built) toHavingSqlOfCount(bp *strings.Builder) {
Expand Down Expand Up @@ -241,7 +256,7 @@ func (built *Built) countBuilder() *strings.Builder {
func (built *Built) SqlOfCondition() ([]interface{}, string) {
vs := []interface{}{}
sb := strings.Builder{}
built.toConditionScript(built.ConditionX, &sb, &vs, built.filterLast)
built.toConditionSql(built.ConditionX, &sb, &vs, built.filterLast)
conditionSql := sb.String()
return vs, conditionSql
}
Expand Down Expand Up @@ -284,11 +299,11 @@ func (built *Built) Sql() ([]interface{}, string, string, map[string]string) {

func (built *Built) sqlData(vs *[]interface{}, km map[string]string) (string, map[string]string) {
sb := strings.Builder{}
built.toResultKeyScript(&sb, km)
built.toResultKeySql(&sb, km)
built.sqlFrom(&sb)
built.toSourceScript(vs, &sb)
built.toSourceSql(vs, &sb)
built.sqlWhere(&sb)
built.toConditionScript(built.ConditionX, &sb, vs, built.filterLast)
built.toConditionSql(built.ConditionX, &sb, vs, built.filterLast)
built.toAggSql(vs, &sb)
built.toGroupBySql(&sb)
built.toHavingSql(vs, &sb)
Expand All @@ -303,11 +318,11 @@ func (built *Built) sqlCount() string {
if sbCount == nil {
return ""
}
built.toResultKeyScriptOfCount(sbCount)
built.toResultKeySqlOfCount(sbCount)
built.countSqlFrom(sbCount)
built.toSourceScriptOfCount(sbCount)
built.toSourceSqlOfCount(sbCount)
built.countSqlWhere(sbCount)
built.toConditionScriptOfCount(built.ConditionX, sbCount)
built.toConditionSqlOfCount(built.ConditionX, sbCount)
built.toAggSqlOfCount(sbCount)
built.toGroupBySqlOfCount(sbCount)
built.toHavingSqlOfCount(sbCount)
Expand Down

0 comments on commit 612190e

Please sign in to comment.