dal/pkg/builder/Builder.go

242 lines
5.2 KiB
Go
Raw Normal View History

package builder
import (
"fmt"
"strings"
)
const (
BUILDER_VERSION = "0.0.1"
2024-08-16 18:10:34 +00:00
BUILDER_CLIENT_METHODS = "Raw|In|Find|Select|Fields|Join|Group|Sort|Limit|Offset|Delete|Insert|Set|Update|OnConflict|DoUpdate|DoNothing"
BUILDER_SERVER_METHODS = "Sql"
)
type Builder struct {
TableName string
TableAlias string
Parts SQLParts
Dialect Dialect
LastQuery Find
Transaction bool
2024-08-16 18:10:34 +00:00
RawSql RawSql
}
type SQLParts struct {
Operation string
From string
FieldsExp string
FromExp string
HavingExp string
FiterExp string
JoinExps []string
GroupExp string
OrderExp string
LimitExp string
OffsetExp string
Values []interface{}
Insert InsertData
Update UpdateData
}
func New(dialect Dialect) *Builder {
return &Builder{
Parts: SQLParts{
Operation: "SELECT",
From: "FROM",
},
Dialect: dialect,
}
}
2024-08-16 18:10:34 +00:00
func (b *Builder) Raw(sql map[string]interface{}) *Builder {
b.Parts.Operation = "RAW"
b.RawSql = sql
return b
}
func (b *Builder) In(table string) *Builder {
b.TableName, b.TableAlias = getTableAlias(table)
b.Parts.FromExp = table
b.Dialect = b.Dialect.New(DialectOpts{
"TableName": b.TableName,
"TableAlias": b.TableAlias,
})
return b
}
func (b *Builder) Find(query Find) *Builder {
b.LastQuery = query
b.Parts.FiterExp, b.Parts.Values = covertFind(
b.Dialect,
query,
)
if len(b.Parts.Operation) == 0 {
b.Parts.Operation = "SELECT"
}
if len(b.Parts.HavingExp) == 0 {
b.Parts.HavingExp = "WHERE"
}
if len(b.Parts.FieldsExp) == 0 {
b.Parts.FieldsExp = "*"
}
if len(b.Parts.FiterExp) == 0 {
b.Parts.HavingExp = ""
}
return b
}
func (b *Builder) Select(fields ...Map) *Builder {
fieldsExp, err := convertFields(fields)
if err != nil {
return b
}
b.Parts.FieldsExp = fieldsExp
return b
}
func (b *Builder) Fields(fields ...Map) *Builder {
return b.Select(fields...)
}
func (b *Builder) Join(joins ...interface{}) *Builder {
exps, vals := convertJoin(b.Dialect, joins...)
b.Parts.JoinExps = append(b.Parts.JoinExps, exps...)
b.Parts.Values = append(b.Parts.Values, vals...)
return b
}
func (b *Builder) Group(keys ...string) *Builder {
b.Parts.HavingExp = "HAVING"
b.Parts.GroupExp = convertGroup(b.Dialect, keys)
return b
}
func (b *Builder) Sort(sort Map) *Builder {
b.Parts.OrderExp, _ = convertSort(b.Dialect, sort)
return b
}
2024-09-02 10:37:34 +00:00
func (b *Builder) Limit(limit int64) *Builder {
b.Parts.LimitExp = fmt.Sprintf("LIMIT %d", limit)
return b
}
2024-09-02 10:37:34 +00:00
func (b *Builder) Offset(offset int64) *Builder {
b.Parts.OffsetExp = fmt.Sprintf("OFFSET %d", offset)
return b
}
func (b *Builder) Delete() *Builder {
b.Parts.Operation = "DELETE"
return b
}
func (b *Builder) Insert(inserts ...Map) *Builder {
insertData, _ := convertInsert(b.Dialect, inserts)
b.Parts = SQLParts{
Operation: "INSERT INTO",
Insert: insertData,
}
return b
}
func (b *Builder) Set(updates Map) *Builder {
b.Dialect = b.Dialect.New(DialectOpts{
"TableAlias": "",
})
updateData := convertUpdate(b.Dialect, updates)
b.Find(b.LastQuery)
b.Parts.Operation = "UPDATE"
b.Parts.Update = updateData
return b
}
func (b *Builder) Update(updates Map) *Builder {
return b.Set(updates)
}
func (b *Builder) OnConflict(fields ...string) *Builder {
if b.Parts.Operation == "UPDATE" {
b.Parts.Update.Upsert = convertConflict(b.Dialect, fields...)
b.Parts.Update.UpsertExp = "DO NOTHING"
} else {
panic("OnConflict is only available for UPDATE operation")
}
return b
}
func (b *Builder) DoUpdate(fields ...string) *Builder {
if b.Parts.Operation == "UPDATE" {
b.Parts.Update.UpsertExp = convertUpsert(fields)
} else {
panic("DoUpdate is only available for UPDATE operation")
}
return b
}
func (b *Builder) DoNothing() *Builder {
if b.Parts.Operation == "UPDATE" {
b.Parts.Update.UpsertExp = "DO NOTHING"
} else {
panic("DoNothing is only available for UPDATE operation")
}
return b
}
func (b *Builder) Tx() *Builder {
b.Transaction = true
return b
}
func (b *Builder) Sql() (string, []interface{}) {
operation := b.Parts.Operation
switch {
2024-08-16 18:10:34 +00:00
case operation == "RAW":
return b.RawSql["s"].(string), b.RawSql["v"].([]interface{})
case operation == "SELECT" || operation == "SELECT DISTINCT":
return unspace(strings.Join([]string{
b.Parts.Operation,
b.Parts.FieldsExp,
b.Parts.From,
b.Parts.FromExp,
strings.Join(
b.Parts.JoinExps,
" ",
),
b.Parts.GroupExp,
b.Parts.HavingExp,
b.Parts.FiterExp,
b.Parts.OrderExp,
b.Parts.LimitExp,
b.Parts.OffsetExp,
}, " ")), b.Parts.Values
case operation == "DELETE":
return unspace(strings.Join([]string{
b.Parts.Operation,
b.Parts.From,
b.Parts.FromExp,
b.Parts.HavingExp,
b.Parts.FiterExp,
b.Parts.OrderExp,
b.Parts.LimitExp,
b.Parts.OffsetExp,
}, " ")), b.Parts.Values
case operation == "INSERT INTO":
return b.Parts.Insert.Statement, b.Parts.Insert.Values
case operation == "UPDATE":
values := append(b.Parts.Update.Values, b.Parts.Values...)
return unspace(strings.Join([]string{
b.Parts.Update.Statement,
b.Parts.HavingExp,
b.Parts.FiterExp,
b.Parts.OrderExp,
b.Parts.LimitExp,
b.Parts.OffsetExp,
b.Parts.Update.Upsert,
b.Parts.Update.UpsertExp,
}, " ")), values
default:
return "", nil
}
}