-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathquery.go
95 lines (79 loc) · 1.94 KB
/
query.go
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
package nidhi
import (
"fmt"
"strings"
sq "github.com/elgris/sqrl"
)
// Sqlizer is the type expected by a store to query documents.
//
// ToSql returns a SQL representation of the Sqlizer, along with a slice of args
// as passed to e.g. database/sql.Exec. It can also return an error.
type Sqlizer = sq.Sqlizer
// Field represents a field of a document.
type Field interface {
// Selector returns the selector expression for this field.
// Eg: For a field named `title`
// JSON_VALUE('$.title' RETURNING JSONB DEFAULT '{}' ON EMPTY)
Selector() string
}
type Query[F Field] struct {
err error
buf strings.Builder
args []any
}
func (q *Query[F]) Reset() {
q.buf.Reset()
q.args = q.args[:0]
q.err = nil
}
func (q *Query[F]) Where(f F, c Cond) *Conj[F] {
return q.where(f, c)
}
func (q *Query[F]) WhereMetadata(f *MetadataField, c Cond) *Conj[F] {
return q.where(f, c)
}
func (q *Query[F]) where(f Field, c Cond) *Conj[F] {
if err := c.AppendCond(f.Selector(), &q.buf, &q.args); err != nil {
q.err = err
}
return (*Conj[F])(q)
}
func (q *Query[F]) Paren(iq *Conj[F]) *Conj[F] {
query, args, err := iq.ToSql()
if err != nil {
q.err = err
}
q.buf.Grow(len(query) + 2)
q.buf.WriteString("(")
q.buf.WriteString(query)
q.buf.WriteString(")")
q.args = append(q.args, args...)
return (*Conj[F])(q)
}
func (q *Query[F]) Not() *Query[F] {
q.buf.WriteString("NOT ")
return q
}
type Conj[F Field] Query[F]
func (q *Conj[F]) And() *Query[F] {
q.buf.WriteString(" AND ")
return (*Query[F])(q)
}
func (q *Conj[F]) Or() *Query[F] {
q.buf.WriteString(" OR ")
return (*Query[F])(q)
}
func (q *Conj[F]) ReplaceArgs(args []any) (*Conj[F], error) {
if len(args) != len(q.args) {
return nil, fmt.Errorf("nidhi: different number of args are passed")
}
res := &Conj[F]{
err: q.err,
args: args,
}
res.buf.WriteString(q.buf.String())
return res, nil
}
func (q *Conj[F]) ToSql() (string, []any, error) {
return q.buf.String(), q.args, q.err
}