Files
pgm/qry.go

245 lines
4.3 KiB
Go
Raw Permalink Normal View History

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()
}