-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconditions.go
More file actions
105 lines (95 loc) · 2.99 KB
/
conditions.go
File metadata and controls
105 lines (95 loc) · 2.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package norm
import (
"strings"
"time"
)
type Condition struct {
Expr string
Args []any
}
func Eq(col string, v any) Condition { return Condition{Expr: col + " = ?", Args: []any{v}} }
func Ne(col string, v any) Condition { return Condition{Expr: col + " <> ?", Args: []any{v}} }
func Gt(col string, v any) Condition { return Condition{Expr: col + " > ?", Args: []any{v}} }
func Ge(col string, v any) Condition { return Condition{Expr: col + " >= ?", Args: []any{v}} }
func Lt(col string, v any) Condition { return Condition{Expr: col + " < ?", Args: []any{v}} }
func Le(col string, v any) Condition { return Condition{Expr: col + " <= ?", Args: []any{v}} }
func In(col string, vals []any) Condition {
if len(vals) == 0 {
return Condition{Expr: "1=0"}
}
args := make([]any, len(vals))
copy(args, vals)
// Build "col IN (?, ?, ?)" without allocating a []string for placeholders
var sb strings.Builder
sb.Grow(len(col) + 5 + len(vals)*3) // col + " IN (" + "?, " per val
sb.WriteString(col)
sb.WriteString(" IN (")
for i := range vals {
if i > 0 {
sb.WriteString(", ")
}
sb.WriteByte('?')
}
sb.WriteByte(')')
return Condition{Expr: sb.String(), Args: args}
}
func RawCond(expr string, args ...any) Condition { return Condition{Expr: expr, Args: args} }
// Between builds a generic BETWEEN condition inclusive of both ends
func Between(col string, start any, end any) Condition {
return Condition{Expr: col + " BETWEEN ? AND ?", Args: []any{start, end}}
}
// DateRange returns a timestamp range condition inclusive of boundaries
func DateRange(col string, from, to time.Time) Condition {
return Condition{Expr: col + " BETWEEN ? AND ?", Args: []any{from, to}}
}
// OnDate matches rows where timestamp column falls on the given calendar day (UTC-based start/end)
func OnDate(col string, day time.Time) Condition {
d := day.UTC()
start := time.Date(d.Year(), d.Month(), d.Day(), 0, 0, 0, 0, time.UTC)
end := start.Add(24 * time.Hour)
return Condition{Expr: col + " >= ? AND " + col + " < ?", Args: []any{start, end}}
}
func And(conds ...Condition) Condition {
if len(conds) == 0 {
return Condition{Expr: "1=1"}
}
// Pre-count total args to avoid repeated grow
totalArgs := 0
for _, c := range conds {
totalArgs += len(c.Args)
}
args := make([]any, 0, totalArgs)
var sb strings.Builder
for i, c := range conds {
if i > 0 {
sb.WriteString(" AND ")
}
sb.WriteByte('(')
sb.WriteString(c.Expr)
sb.WriteByte(')')
args = append(args, c.Args...)
}
return Condition{Expr: sb.String(), Args: args}
}
func Or(conds ...Condition) Condition {
if len(conds) == 0 {
return Condition{Expr: "1=0"}
}
// Pre-count total args to avoid repeated grow
totalArgs := 0
for _, c := range conds {
totalArgs += len(c.Args)
}
args := make([]any, 0, totalArgs)
var sb strings.Builder
for i, c := range conds {
if i > 0 {
sb.WriteString(" OR ")
}
sb.WriteByte('(')
sb.WriteString(c.Expr)
sb.WriteByte(')')
args = append(args, c.Args...)
}
return Condition{Expr: sb.String(), Args: args}
}