fix #211: Support clone (deep copy) in all builders

This commit is contained in:
Huan Du
2025-09-17 16:19:09 +08:00
parent 88a656d237
commit 18f7db8816
18 changed files with 407 additions and 10 deletions
+26 -1
View File
@@ -3,6 +3,12 @@
package sqlbuilder
import (
"reflect"
"github.com/huandu/go-clone"
)
const (
cteMarkerInit injectionMarker = iota
cteMarkerAfterWith
@@ -25,6 +31,25 @@ func newCTEBuilder() *CTEBuilder {
}
}
// Clone returns a deep copy of CTEBuilder.
// It's useful when you want to create a base builder and clone it to build similar queries.
func (cteb *CTEBuilder) Clone() *CTEBuilder {
return clone.Clone(cteb).(*CTEBuilder)
}
func init() {
t := reflect.TypeOf(CTEBuilder{})
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
@@ -47,7 +72,7 @@ func (cteb *CTEBuilder) With(queries ...*CTEQueryBuilder) *CTEBuilder {
queryBuilderVars = append(queryBuilderVars, cteb.args.Add(query))
}
cteb.queries = queries
cteb.queries = append([]*CTEQueryBuilder(nil), queries...)
cteb.queryBuilderVars = queryBuilderVars
cteb.marker = cteMarkerAfterWith
return cteb