2025-07-26 18:34:56 +05:30
|
|
|
// 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
|
2025-08-10 20:26:09 +05:30
|
|
|
Join(m Table, t1Field, t2Field Field, cond ...Conditioner) SelectClause
|
|
|
|
LeftJoin(m Table, t1Field, t2Field Field, cond ...Conditioner) SelectClause
|
|
|
|
RightJoin(m Table, t1Field, t2Field Field, cond ...Conditioner) SelectClause
|
|
|
|
FullJoin(m Table, t1Field, t2Field Field, cond ...Conditioner) SelectClause
|
2025-07-26 18:34:56 +05:30
|
|
|
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
|
|
|
|
var op string
|
2025-08-03 21:41:20 +05:30
|
|
|
if cv.Val != nil {
|
|
|
|
*args = append(*args, cv.Val)
|
|
|
|
if strings.HasSuffix(cv.op, "$") {
|
|
|
|
op = cv.op + strconv.Itoa(argIdx+1)
|
|
|
|
} else {
|
|
|
|
op = strings.Replace(cv.op, "$", "$"+strconv.Itoa(argIdx+1), 1)
|
|
|
|
}
|
2025-07-26 18:34:56 +05:30
|
|
|
} else {
|
2025-08-03 21:41:20 +05:30
|
|
|
op = cv.op
|
2025-07-26 18:34:56 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
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()
|
|
|
|
}
|