• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

stephenafamo / bob / 21511526140

30 Jan 2026 08:53AM UTC coverage: 42.626% (-0.1%) from 42.739%
21511526140

Pull #622

github

manhrev
feat: all, some, any starters for psql
Pull Request #622: Add EXISTS, ALL, SOME, ANY expressions

0 of 62 new or added lines in 4 files covered. (0.0%)

22 existing lines in 2 files now uncovered.

9989 of 23434 relevant lines covered (42.63%)

598.05 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

43.43
/expr/builder.go
1
package expr
2

3
import (
4
        "github.com/stephenafamo/bob"
5
)
6

7
type builder[B any] interface {
8
        New(bob.Expression) B
9
}
10

11
// Build an expression
12
func X[T bob.Expression, B builder[T]](exp bob.Expression, others ...bob.Expression) T {
666✔
13
        var b B
666✔
14

666✔
15
        // Easy chain. For example:
666✔
16
        // X("a", "=", "b")
666✔
17
        if len(others) > 0 {
666✔
18
                exp = Join{Exprs: append([]bob.Expression{exp}, others...)}
×
19
        }
×
20

21
        // Wrap in parenthesis if not a raw string or string in quotes
22
        switch t := exp.(type) {
666✔
23
        case Clause, Raw, rawString, quoted:
268✔
24
                // expected to be printed as it is
268✔
25
                break
268✔
26
        case args:
242✔
27
                // Often initialized in a context that includes
242✔
28
                // its own parenthesis such as VALUES(...)
242✔
29
                break
242✔
30
        case group:
8✔
31
                // Already has its own parentheses
8✔
32
                break
8✔
33
        case T:
6✔
34
                return t
6✔
35
        default:
142✔
36
                exp = group{exp}
142✔
37
        }
38

39
        return b.New(exp)
660✔
40
}
41

42
// prefix the expression with a NOT
43
func Not[T bob.Expression, B builder[T]](exp bob.Expression) T {
×
44
        var b B
×
45
        return b.New(Join{Exprs: []bob.Expression{not, X[T, B](exp)}})
×
46
}
×
47

48
// Exists expression
NEW
49
func Exists[T bob.Expression, B builder[T]](exp bob.Expression) T {
×
NEW
50
        var b B
×
NEW
51
        return b.New(Join{Exprs: []bob.Expression{exists, group{exp}}})
×
NEW
52
}
×
53

54
// prefix the expression with a - (minus)
NEW
55
func Minus[T bob.Expression, B builder[T]](exp bob.Expression) T {
×
NEW
56
        var b B
×
NEW
57
        return b.New(Join{Exprs: []bob.Expression{minus, X[T, B](exp)}})
×
NEW
58
}
×
59

60
// ANY expression
NEW
61
func Any[T bob.Expression, B builder[T]](exp bob.Expression) T {
×
NEW
62
        var b B
×
NEW
63
        return b.New(Join{Exprs: []bob.Expression{anyOp, group{exp}}})
×
NEW
64
}
×
65

66
// SOME expression
NEW
67
func Some[T bob.Expression, B builder[T]](exp bob.Expression) T {
×
NEW
68
        var b B
×
NEW
69
        return b.New(Join{Exprs: []bob.Expression{some, group{exp}}})
×
NEW
70
}
×
71

72
// ALL expression
NEW
UNCOV
73
func All[T bob.Expression, B builder[T]](exp bob.Expression) T {
×
NEW
UNCOV
74
        var b B
×
NEW
UNCOV
75
        return b.New(Join{Exprs: []bob.Expression{all, group{exp}}})
×
NEW
UNCOV
76
}
×
77

78
// To be embedded in query mods
79
// T is the chain type, this allows dialects to have custom chain methods
80
// F is function type, so that the dialect can change where it
81
// accepted. E.g. it can be modified to work as a mod
82
// B has a New() method that is used to create a new instance of T
83
type Builder[T bob.Expression, B builder[T]] struct{}
84

85
// prefix the expression with a NOT
86
func (e Builder[T, B]) Not(exp bob.Expression) T {
×
87
        return Not[T, B](exp)
×
UNCOV
88
}
×
89

90
// Or
91
func (e Builder[T, B]) Or(args ...bob.Expression) T {
×
92
        return X[T, B](Join{Exprs: args, Sep: " OR "})
×
UNCOV
93
}
×
94

95
// And
UNCOV
96
func (e Builder[T, B]) And(args ...bob.Expression) T {
×
UNCOV
97
        return X[T, B](Join{Exprs: args, Sep: " AND "})
×
UNCOV
98
}
×
99

100
// single quoted raw string
101
func (e Builder[T, B]) S(s string) T {
62✔
102
        return X[T, B](rawString(s))
62✔
103
}
62✔
104

105
// Comma separated list of arguments
106
func (e Builder[T, B]) Arg(vals ...any) T {
230✔
107
        return X[T, B](Arg(vals...))
230✔
108
}
230✔
109

110
// Comma separated list of arguments surrounded by parentheses
111
func (e Builder[T, B]) ArgGroup(vals ...any) T {
12✔
112
        return X[T, B](ArgGroup(vals...))
12✔
113
}
12✔
114

UNCOV
115
func (e Builder[T, B]) Placeholder(n uint) T {
×
UNCOV
116
        return e.Arg(make([]any, n)...)
×
UNCOV
117
}
×
118

119
func (e Builder[T, B]) Raw(query string, args ...any) T {
16✔
120
        return X[T, B](Clause{
16✔
121
                query: query,
16✔
122
                args:  args,
16✔
123
        })
16✔
124
}
16✔
125

126
// Add parentheses around an expressions and separate them by commas
127
func (e Builder[T, B]) Group(exps ...bob.Expression) T {
8✔
128
        return X[T, B](group(exps))
8✔
129
}
8✔
130

131
// quoted and joined... something like "users"."id"
132
func (e Builder[T, B]) Quote(aa ...string) T {
190✔
133
        return X[T, B](Quote(aa...))
190✔
134
}
190✔
135

136
// quoted and joined... something like "users"."id"
137
func (e Builder[T, B]) Cast(exp bob.Expression, typname string) T {
×
138
        return X[T, B](Cast(exp, typname))
×
139
}
×
140

141
// EXISTS expression
NEW
142
func (e Builder[T, B]) Exists(exp bob.Expression) T {
×
NEW
143
        return Exists[T, B](exp)
×
NEW
144
}
×
145

146
// prefix the expression with a - (minus)
NEW
147
func (e Builder[T, B]) Minus(exp bob.Expression) T {
×
NEW
148
        return Minus[T, B](exp)
×
NEW
149
}
×
150

151
// ANY expression
NEW
152
func (e Builder[T, B]) Any(exp bob.Expression) T {
×
NEW
153
        return Any[T, B](exp)
×
NEW
UNCOV
154
}
×
155

156
// SOME expression
NEW
UNCOV
157
func (e Builder[T, B]) Some(exp bob.Expression) T {
×
NEW
UNCOV
158
        return Some[T, B](exp)
×
NEW
UNCOV
159
}
×
160

161
// ALL expression
NEW
UNCOV
162
func (e Builder[T, B]) All(exp bob.Expression) T {
×
NEW
UNCOV
163
        return All[T, B](exp)
×
NEW
UNCOV
164
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc