mirror of
https://github.com/hanzoai/sqlbuilder.git
synced 2026-10-01 00:37:42 +00:00
167 lines
4.6 KiB
Go
167 lines
4.6 KiB
Go
// Copyright 2024 Huan Du. All rights reserved.
|
|
// Licensed under the MIT license that can be found in the LICENSE file.
|
|
|
|
package sqlbuilder
|
|
|
|
import (
|
|
"reflect"
|
|
|
|
"github.com/huandu/go-clone"
|
|
)
|
|
|
|
const (
|
|
cteQueryMarkerInit injectionMarker = iota
|
|
cteQueryMarkerAfterTable
|
|
cteQueryMarkerAfterAs
|
|
)
|
|
|
|
// CTETable creates a new CTE query builder with default flavor, marking it as a table.
|
|
//
|
|
// The resulting CTE query can be used in a `SelectBuilder“, where its table name will be
|
|
// automatically included in the FROM clause.
|
|
func CTETable(name string, cols ...string) *CTEQueryBuilder {
|
|
return DefaultFlavor.NewCTEQueryBuilder().AddToTableList().Table(name, cols...)
|
|
}
|
|
|
|
// CTEQuery creates a new CTE query builder with default flavor.
|
|
func CTEQuery(name string, cols ...string) *CTEQueryBuilder {
|
|
return DefaultFlavor.NewCTEQueryBuilder().Table(name, cols...)
|
|
}
|
|
|
|
func newCTEQueryBuilder() *CTEQueryBuilder {
|
|
return &CTEQueryBuilder{
|
|
args: &Args{},
|
|
injection: newInjection(),
|
|
}
|
|
}
|
|
|
|
// Clone returns a deep copy of CTEQueryBuilder.
|
|
// It's useful when you want to create a base builder and clone it to build similar queries.
|
|
func (ctetb *CTEQueryBuilder) Clone() *CTEQueryBuilder {
|
|
return clone.Clone(ctetb).(*CTEQueryBuilder)
|
|
}
|
|
|
|
func init() {
|
|
t := reflect.TypeOf(CTEQueryBuilder{})
|
|
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
|
|
|
|
// if true, this query's table name will be automatically added to the table list
|
|
// in FROM clause of SELECT statement.
|
|
autoAddToTableList bool
|
|
|
|
args *Args
|
|
|
|
injection *injection
|
|
marker injectionMarker
|
|
}
|
|
|
|
var _ Builder = new(CTEQueryBuilder)
|
|
|
|
// CTETableBuilder is an alias of CTEQueryBuilder for backward compatibility.
|
|
//
|
|
// Deprecated: use CTEQueryBuilder instead.
|
|
type CTETableBuilder = CTEQueryBuilder
|
|
|
|
// Table sets the table name and columns in a CTE table.
|
|
func (ctetb *CTEQueryBuilder) Table(name string, cols ...string) *CTEQueryBuilder {
|
|
ctetb.name = name
|
|
ctetb.cols = cols
|
|
ctetb.marker = cteQueryMarkerAfterTable
|
|
return ctetb
|
|
}
|
|
|
|
// 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
|
|
}
|
|
|
|
// AddToTableList sets flag to add table name to table list in FROM clause of SELECT statement.
|
|
func (ctetb *CTEQueryBuilder) AddToTableList() *CTEQueryBuilder {
|
|
ctetb.autoAddToTableList = true
|
|
return ctetb
|
|
}
|
|
|
|
// ShouldAddToTableList returns flag to add table name to table list in FROM clause of SELECT statement.
|
|
func (ctetb *CTEQueryBuilder) ShouldAddToTableList() bool {
|
|
return ctetb.autoAddToTableList
|
|
}
|
|
|
|
// String returns the compiled CTE string.
|
|
func (ctetb *CTEQueryBuilder) String() string {
|
|
sql, _ := ctetb.Build()
|
|
return sql
|
|
}
|
|
|
|
// Build returns compiled CTE string and args.
|
|
func (ctetb *CTEQueryBuilder) Build() (sql string, args []interface{}) {
|
|
return ctetb.BuildWithFlavor(ctetb.args.Flavor)
|
|
}
|
|
|
|
// BuildWithFlavor builds a CTE with the specified flavor and initial arguments.
|
|
func (ctetb *CTEQueryBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{}) (sql string, args []interface{}) {
|
|
buf := newStringBuilder()
|
|
ctetb.injection.WriteTo(buf, cteQueryMarkerInit)
|
|
|
|
if ctetb.name != "" {
|
|
buf.WriteLeadingString(ctetb.name)
|
|
|
|
if len(ctetb.cols) > 0 {
|
|
buf.WriteLeadingString("(")
|
|
buf.WriteStrings(ctetb.cols, ", ")
|
|
buf.WriteString(")")
|
|
}
|
|
|
|
ctetb.injection.WriteTo(buf, cteQueryMarkerAfterTable)
|
|
}
|
|
|
|
if ctetb.builderVar != "" {
|
|
buf.WriteLeadingString("AS (")
|
|
buf.WriteString(ctetb.builderVar)
|
|
buf.WriteRune(')')
|
|
|
|
ctetb.injection.WriteTo(buf, cteQueryMarkerAfterAs)
|
|
}
|
|
|
|
return ctetb.args.CompileWithFlavor(buf.String(), flavor, initialArg...)
|
|
}
|
|
|
|
// SetFlavor sets the flavor of compiled sql.
|
|
func (ctetb *CTEQueryBuilder) SetFlavor(flavor Flavor) (old Flavor) {
|
|
old = ctetb.args.Flavor
|
|
ctetb.args.Flavor = flavor
|
|
return
|
|
}
|
|
|
|
// Flavor returns flavor of builder
|
|
func (ctetb *CTEQueryBuilder) Flavor() Flavor {
|
|
return ctetb.args.Flavor
|
|
}
|
|
|
|
// SQL adds an arbitrary sql to current position.
|
|
func (ctetb *CTEQueryBuilder) SQL(sql string) *CTEQueryBuilder {
|
|
ctetb.injection.SQL(ctetb.marker, sql)
|
|
return ctetb
|
|
}
|
|
|
|
// TableName returns the CTE table name.
|
|
func (ctetb *CTEQueryBuilder) TableName() string {
|
|
return ctetb.name
|
|
}
|