241 lines
4.2 KiB
Go
241 lines
4.2 KiB
Go
|
// Patial Tech.
|
||
|
// Author, Ankit Patial
|
||
|
|
||
|
package pgm
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
|
||
|
"github.com/jackc/pgx/v5"
|
||
|
)
|
||
|
|
||
|
type (
|
||
|
Clause interface {
|
||
|
Select(fields ...Field) SelectClause
|
||
|
// Insert() InsertSet
|
||
|
// Update() UpdateSet
|
||
|
// Delete() WhereOrExec
|
||
|
}
|
||
|
|
||
|
SelectClause interface {
|
||
|
// Join and Inner Join are same
|
||
|
Join(m Table, t1Field, t2Field Field) SelectClause
|
||
|
LeftJoin(m Table, t1Field, t2Field Field) SelectClause
|
||
|
RightJoin(m Table, t1Field, t2Field Field) SelectClause
|
||
|
FullJoin(m Table, t1Field, t2Field Field) SelectClause
|
||
|
CrossJoin(m Table) SelectClause
|
||
|
WhereClause
|
||
|
OrderByClause
|
||
|
GroupByClause
|
||
|
LimitClause
|
||
|
OffsetClause
|
||
|
Query
|
||
|
raw(prefixArgs []any) (string, []any)
|
||
|
}
|
||
|
|
||
|
WhereClause interface {
|
||
|
Where(cond ...Conditioner) AfterWhere
|
||
|
}
|
||
|
|
||
|
AfterWhere interface {
|
||
|
WhereClause
|
||
|
GroupByClause
|
||
|
OrderByClause
|
||
|
LimitClause
|
||
|
OffsetClause
|
||
|
Query
|
||
|
}
|
||
|
|
||
|
GroupByClause interface {
|
||
|
GroupBy(fields ...Field) AfterGroupBy
|
||
|
}
|
||
|
|
||
|
AfterGroupBy interface {
|
||
|
HavinClause
|
||
|
OrderByClause
|
||
|
LimitClause
|
||
|
OffsetClause
|
||
|
Query
|
||
|
}
|
||
|
|
||
|
HavinClause interface {
|
||
|
Having(cond ...Conditioner) AfterHaving
|
||
|
}
|
||
|
|
||
|
AfterHaving interface {
|
||
|
OrderByClause
|
||
|
LimitClause
|
||
|
OffsetClause
|
||
|
Query
|
||
|
}
|
||
|
|
||
|
OrderByClause interface {
|
||
|
OrderBy(fields ...Field) AfterOrderBy
|
||
|
}
|
||
|
|
||
|
AfterOrderBy interface {
|
||
|
LimitClause
|
||
|
OffsetClause
|
||
|
Query
|
||
|
}
|
||
|
|
||
|
LimitClause interface {
|
||
|
Limit(v int) AfterLimit
|
||
|
}
|
||
|
|
||
|
AfterLimit interface {
|
||
|
OffsetClause
|
||
|
Query
|
||
|
}
|
||
|
|
||
|
OffsetClause interface {
|
||
|
Offset(v int) AfterOffset
|
||
|
}
|
||
|
|
||
|
AfterOffset interface {
|
||
|
LimitClause
|
||
|
Query
|
||
|
}
|
||
|
|
||
|
Conditioner interface {
|
||
|
Condition(args *[]any, idx int) string
|
||
|
}
|
||
|
|
||
|
Insert interface {
|
||
|
Set(field Field, val any) InsertClause
|
||
|
SetMap(fields map[Field]any) InsertClause
|
||
|
}
|
||
|
|
||
|
InsertClause interface {
|
||
|
Insert
|
||
|
Returning(field Field) First
|
||
|
OnConflict(fields ...Field) Do
|
||
|
Execute
|
||
|
Stringer
|
||
|
}
|
||
|
|
||
|
Do interface {
|
||
|
DoNothing() Execute
|
||
|
DoUpdate(fields ...Field) Execute
|
||
|
}
|
||
|
|
||
|
Update interface {
|
||
|
Set(field Field, val any) UpdateClause
|
||
|
SetMap(fields map[Field]any) UpdateClause
|
||
|
}
|
||
|
|
||
|
UpdateClause interface {
|
||
|
Update
|
||
|
Where(cond ...Conditioner) WhereOrExec
|
||
|
}
|
||
|
|
||
|
WhereOrExec interface {
|
||
|
Where(cond ...Conditioner) WhereOrExec
|
||
|
Execute
|
||
|
}
|
||
|
|
||
|
Query interface {
|
||
|
First
|
||
|
All
|
||
|
Stringer
|
||
|
}
|
||
|
|
||
|
First interface {
|
||
|
First(ctx context.Context, dest ...any) error
|
||
|
FirstTx(ctx context.Context, tx pgx.Tx, dest ...any) error
|
||
|
Stringer
|
||
|
}
|
||
|
|
||
|
All interface {
|
||
|
// Query rows
|
||
|
//
|
||
|
// don't forget to close() rows
|
||
|
All(ctx context.Context, rows RowsCb) error
|
||
|
// Query rows
|
||
|
//
|
||
|
// don't forget to close() rows
|
||
|
AllTx(ctx context.Context, tx pgx.Tx, rows RowsCb) error
|
||
|
}
|
||
|
|
||
|
Execute interface {
|
||
|
Exec(ctx context.Context) error
|
||
|
ExecTx(ctx context.Context, tx pgx.Tx) error
|
||
|
Stringer
|
||
|
}
|
||
|
|
||
|
Stringer interface {
|
||
|
String() string
|
||
|
}
|
||
|
|
||
|
RowScanner interface {
|
||
|
Scan(dest ...any) error
|
||
|
}
|
||
|
|
||
|
RowsCb func(row RowScanner) error
|
||
|
)
|
||
|
|
||
|
func joinFileds(fields []Field) string {
|
||
|
sb := getSB()
|
||
|
defer putSB(sb)
|
||
|
for i, f := range fields {
|
||
|
if i == 0 {
|
||
|
sb.WriteString(f.String())
|
||
|
} else {
|
||
|
sb.WriteString(", ")
|
||
|
sb.WriteString(f.String())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return sb.String()
|
||
|
}
|
||
|
|
||
|
func And(cond ...Conditioner) Conditioner {
|
||
|
return &CondGroup{op: " AND ", cond: cond}
|
||
|
}
|
||
|
|
||
|
func Or(cond ...Conditioner) Conditioner {
|
||
|
return &CondGroup{op: " OR ", cond: cond}
|
||
|
}
|
||
|
|
||
|
func (cv *Cond) Condition(args *[]any, argIdx int) string {
|
||
|
// 1. condition with subquery
|
||
|
if cv.action == CondActionSubQuery {
|
||
|
qStr, newArgs := cv.Val.(SelectClause).raw(*args)
|
||
|
*args = newArgs
|
||
|
return cv.Field + strings.Replace(cv.op, "$", qStr, 1)
|
||
|
}
|
||
|
|
||
|
// 2. normal condition
|
||
|
*args = append(*args, cv.Val)
|
||
|
var op string
|
||
|
if strings.HasSuffix(cv.op, "$") {
|
||
|
op = cv.op + strconv.Itoa(argIdx+1)
|
||
|
} else {
|
||
|
op = strings.Replace(cv.op, "$", "$"+strconv.Itoa(argIdx+1), 1)
|
||
|
}
|
||
|
|
||
|
if cv.action == CondActionNeedToClose {
|
||
|
return cv.Field + op + ")"
|
||
|
}
|
||
|
return cv.Field + op
|
||
|
}
|
||
|
|
||
|
func (c *CondGroup) Condition(args *[]any, argIdx int) string {
|
||
|
sb := getSB()
|
||
|
defer putSB(sb)
|
||
|
|
||
|
sb.WriteString("(")
|
||
|
for i, cond := range c.cond {
|
||
|
if i == 0 {
|
||
|
sb.WriteString(cond.Condition(args, argIdx+i))
|
||
|
} else {
|
||
|
sb.WriteString(c.op)
|
||
|
sb.WriteString(cond.Condition(args, argIdx+i))
|
||
|
}
|
||
|
}
|
||
|
sb.WriteString(")")
|
||
|
return sb.String()
|
||
|
}
|