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

go-ap / filters / #1

29 Mar 2026 03:14PM UTC coverage: 71.78%. First build
#1

push

sourcehut

mariusor
Add tests for multiple filters

41 of 97 new or added lines in 10 files covered. (42.27%)

1460 of 2034 relevant lines covered (71.78%)

18.28 hits per line

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

84.28
/sql.go
1
package filters
2

3
import (
4
        "fmt"
5
        "reflect"
6
        "runtime"
7
        "strings"
8

9
        vocab "github.com/go-ap/activitypub"
10
        "github.com/leporo/sqlf"
11
)
12

13
func SQLLimit(st *Stmt, f ...Check) {
3✔
14
        if st == nil || len(f) == 0 {
4✔
15
                return
1✔
16
        }
1✔
17
        lim := MaxItems
2✔
18
        for _, check := range f {
5✔
19
                switch c := check.(type) {
3✔
20
                case *counter:
1✔
21
                        lim = c.max
1✔
22
                        break
1✔
23
                }
24
        }
25
        st.Limit(lim)
2✔
26
}
27

28
type Stmt = sqlf.Stmt
29

30
func SQLWhere(s *Stmt, ff ...Check) error {
53✔
31
        getWhereClauses(s, ff...)
53✔
32
        return nil
53✔
33
}
53✔
34

35
func getWhereClauses(s *Stmt, f ...Check) {
53✔
36
        //addNotClauses(s, f...)
53✔
37
        addTypeWheres(s, f...)
53✔
38
        addIRIWheres(s, f...)
53✔
39
        addNLVWheres(s, f...)
53✔
40
        addInReplyToWheres(s, f...)
53✔
41
        addAttributedToWheres(s, f...)
53✔
42
        addURLWheres(s, f...)
53✔
43
        addContextWheres(s, f...)
53✔
44
}
53✔
45

NEW
46
func addNotClauses(s *Stmt, f ...Check) {
×
NEW
47
        if s == nil || len(f) == 0 {
×
NEW
48
                return
×
NEW
49
        }
×
50

NEW
51
        nots := make([]any, 0)
×
NEW
52
        var os *Stmt
×
NEW
53
        hasNots := false
×
NEW
54
        /*
×
NEW
55
                for _, check := range f {
×
NEW
56
                        switch c := check.(type) {
×
NEW
57
                        case notCrit:
×
NEW
58
                                nots = append()
×
NEW
59
                        }
×
NEW
60
                }
×
NEW
61
        */
×
NEW
62
        if len(nots) > 0 {
×
NEW
63
                if len(nots) == 1 {
×
NEW
64
                        s.Where("iri = ?", nots[0])
×
NEW
65
                } else {
×
NEW
66
                        s.Where("iri").In(nots...)
×
NEW
67
                }
×
68
        }
NEW
69
        if hasNots {
×
NEW
70
                tsql := strings.TrimPrefix(s.String(), " WHERE ")
×
NEW
71
                os.Where("("+tsql+" OR iri IS NULL)", s.Args()...)
×
NEW
72
        }
×
73
}
74

75
func addIRIWheres(s *Stmt, f ...Check) {
53✔
76
        if s == nil || len(f) == 0 {
54✔
77
                return
1✔
78
        }
1✔
79

80
        inVal := make([]any, 0)
52✔
81
        likeVal := make([]any, 0)
52✔
82

52✔
83
        var os *Stmt
52✔
84
        andNil := false
52✔
85
        for _, check := range f {
117✔
86
                switch i := check.(type) {
65✔
87
                case idEquals:
6✔
88
                        inVal = append(inVal, vocab.IRI(i))
6✔
89
                case iriEquals:
6✔
90
                        inVal = append(inVal, vocab.IRI(i))
6✔
91
                case iriLike:
4✔
92
                        likeVal = append(likeVal, "%"+string(i)+"%")
4✔
93
                case idLike:
×
94
                        likeVal = append(likeVal, "%"+string(i)+"%")
×
95
                case iriNil:
4✔
96
                        andNil = true
4✔
97
                        os = s
4✔
98
                        s = sqlf.New("")
4✔
99
                case idNil:
2✔
100
                        andNil = true
2✔
101
                        os = s
2✔
102
                        s = sqlf.New("")
2✔
103
                }
104
        }
105

106
        if len(inVal) > 0 {
60✔
107
                if len(inVal) == 1 {
12✔
108
                        s.Where("iri = ?", inVal[0])
4✔
109
                } else {
8✔
110
                        s.Where("iri").In(inVal...)
4✔
111
                }
4✔
112
        }
113
        if len(likeVal) > 0 {
55✔
114
                if len(likeVal) == 1 {
5✔
115
                        s.Where("iri LIKE ?", likeVal[0])
2✔
116
                } else {
3✔
117
                        lors := sqlf.New("")
1✔
118
                        for _, like := range likeVal {
3✔
119
                                lors.Where("iri LIKE ?", like)
2✔
120
                        }
2✔
121
                        orsq := strings.TrimPrefix(lors.String(), " WHERE ")
1✔
122
                        s.Where(strings.ReplaceAll(orsq, " AND ", " OR "), lors.Args()...)
1✔
123
                }
124
        }
125
        if andNil {
58✔
126
                tsql := strings.TrimPrefix(s.String(), " WHERE ")
6✔
127
                os.Where("("+tsql+" OR iri IS NULL)", s.Args()...)
6✔
128
        }
6✔
129
}
130

131
func addTypeWheres(s *Stmt, f ...Check) {
53✔
132
        if s == nil || len(f) == 0 {
54✔
133
                return
1✔
134
        }
1✔
135

136
        inVal := make([]any, 0)
52✔
137

52✔
138
        var os *Stmt
52✔
139
        andNil := false
52✔
140
        for _, check := range f {
117✔
141
                c, ok := check.(withTypes)
65✔
142
                if !ok {
126✔
143
                        continue
61✔
144
                }
145
                for _, typ := range c {
13✔
146
                        if typ == vocab.NilType {
11✔
147
                                andNil = true
2✔
148
                                os = s
2✔
149
                                s = sqlf.New("")
2✔
150
                                continue
2✔
151
                        }
152
                        inVal = append(inVal, typ)
7✔
153
                }
154
        }
155

156
        if len(inVal) > 0 {
56✔
157
                if len(inVal) == 1 {
6✔
158
                        s.Where("type = ?", inVal[0])
2✔
159
                } else {
4✔
160
                        s.Where("type").In(inVal...)
2✔
161
                }
2✔
162
        }
163
        if andNil {
54✔
164
                tsql := strings.TrimPrefix(s.String(), " WHERE ")
2✔
165
                os.Where("("+tsql+" OR type IS NULL)", s.Args()...)
2✔
166
        }
2✔
167
}
168

169
func addContextWheres(s *Stmt, f ...Check) {
53✔
170
        for _, check := range f {
118✔
171
                switch c := check.(type) {
65✔
172
                case contextNil:
2✔
173
                        jsonIsNull(s, "context")
2✔
174
                case contextEquals:
2✔
175
                        jsonEquals(s, "context", vocab.IRI(c))
2✔
176
                case contextLike:
2✔
177
                        jsonLike(s, "context", vocab.IRI(c))
2✔
178
                }
179
        }
180
}
181

182
func addURLWheres(s *Stmt, f ...Check) {
53✔
183
        for _, check := range f {
118✔
184
                switch c := check.(type) {
65✔
185
                case urlNil:
2✔
186
                        s.Where("url IS NULL")
2✔
187
                case urlEquals:
2✔
188
                        s.Where("url = ?", vocab.IRI(c))
2✔
189
                case urlLike:
2✔
190
                        s.Where("url LIKE ?", "%"+vocab.IRI(c)+"%")
2✔
191
                }
192
        }
193
}
194

195
func sameFns(f1, f2 any) bool {
182✔
196
        p1 := reflect.ValueOf(f1).Pointer()
182✔
197
        p2 := reflect.ValueOf(f2).Pointer()
182✔
198
        if p1 == p2 {
349✔
199
                return true
167✔
200
        }
167✔
201
        if p1 == 0 || p2 == 0 {
15✔
202
                return false
×
203
        }
×
204
        s1, l1 := runtime.FuncForPC(p1).FileLine(p1)
15✔
205
        s2, l2 := runtime.FuncForPC(p2).FileLine(p2)
15✔
206
        return s1 == s2 && l1 == l2
15✔
207
}
208

209
func addNLVWheres(s *Stmt, f ...Check) {
53✔
210
        for _, check := range f {
118✔
211
                switch c := check.(type) {
65✔
212
                case naturalLanguageValCheck:
15✔
213
                        var field string
15✔
214
                        switch c.typ {
15✔
215
                        case byName:
4✔
216
                                field = keyName
4✔
217
                        case byPreferredUsername:
3✔
218
                                field = "preferred_username"
3✔
219
                        case bySummary:
4✔
220
                                field = keySummary
4✔
221
                        case byContent:
4✔
222
                                field = keyContent
4✔
223
                        }
224
                        switch {
15✔
225
                        case sameFns(c.checkFn, naturalLanguageEmpty):
5✔
226
                                s.Where(field + " IS NULL")
5✔
227
                        case sameFns(c.checkFn, naturalLanguageValuesLike):
5✔
228
                                s.Where(field+" LIKE ?", "%"+c.checkValue+"%")
5✔
229
                        case sameFns(c.checkFn, naturalLanguageValuesEquals):
5✔
230
                                s.Where(field+" = ?", c.checkValue)
5✔
231
                        }
232
                }
233
        }
234
}
235

236
func addInReplyToWheres(s *Stmt, f ...Check) {
53✔
237
        for _, check := range f {
118✔
238
                switch c := check.(type) {
65✔
239
                case inReplyToNil:
2✔
240
                        jsonIsNull(s, "inReplyTo")
2✔
241
                case inReplyToEquals:
2✔
242
                        jsonEquals(s, "inReplyTo", vocab.IRI(c))
2✔
243
                case inReplyToLike:
2✔
244
                        jsonLike(s, "inReplyTo", vocab.IRI(c))
2✔
245
                }
246
        }
247
}
248

249
func addAttributedToWheres(s *Stmt, f ...Check) {
53✔
250
        for _, check := range f {
118✔
251
                switch c := check.(type) {
65✔
252
                case attributedToNil:
2✔
253
                        jsonIsNull(s, "attributedTo")
2✔
254
                case attributedToEquals:
2✔
255
                        jsonEquals(s, "attributedTo", vocab.IRI(c))
2✔
256
                case attributedToLike:
2✔
257
                        jsonLike(s, "attributedTo", vocab.IRI(c))
2✔
258
                }
259
        }
260
}
261

262
func jsonLike(s *Stmt, prop string, val fmt.Stringer) {
6✔
263
        isPg := stmtIsPostgres(s)
6✔
264
        if isPg {
9✔
265
                s.Where(fmt.Sprintf(`raw->>'%s' LIKE ?`, prop), "%"+val.String()+"%")
3✔
266
        } else {
6✔
267
                s.Where(fmt.Sprintf(`json_extract(raw, '$.%s') LIKE ?`, prop), "%"+val.String()+"%")
3✔
268
        }
3✔
269
}
270

271
func jsonIsNull(s *Stmt, prop string) {
6✔
272
        isPg := stmtIsPostgres(s)
6✔
273
        if isPg {
9✔
274
                s.Where(fmt.Sprintf(`raw->>'%s' IS NULL`, prop))
3✔
275
        } else {
6✔
276
                s.Where(fmt.Sprintf(`json_extract(raw, '$.%s') IS NULL`, prop))
3✔
277
        }
3✔
278
}
279

280
func jsonIsNotNull(s *Stmt, prop string) {
×
281
        isPg := stmtIsPostgres(s)
×
282
        if isPg {
×
283
                s.Where(fmt.Sprintf(`raw->>'%s' IS NOT NULL`, prop))
×
284
        } else {
×
285
                s.Where(fmt.Sprintf(`json_extract(raw, '$.%s') IS NOT NULL`, prop))
×
286
        }
×
287
}
288

289
func jsonEquals(s *Stmt, prop string, val any) {
6✔
290
        isPg := stmtIsPostgres(s)
6✔
291
        if isPg {
9✔
292
                s.Where(fmt.Sprintf(`raw->>'%s' = ?`, prop), val)
3✔
293
        } else {
6✔
294
                s.Where(fmt.Sprintf(`json_extract(raw, '$.%s') = ?`, prop), val)
3✔
295
        }
3✔
296
}
297

298
func stmtIsPostgres(s *Stmt) bool {
18✔
299
        sc := s.Clone()
18✔
300
        sc.Where("t = ?", 1)
18✔
301
        isPg := strings.Contains(sc.String(), "$1")
18✔
302
        return isPg
18✔
303
}
18✔
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