Skip to content

Commit 62f155f

Browse files
author
Matthias Zimmermann
committed
add query language tests for the glob operator
1 parent 72df030 commit 62f155f

File tree

2 files changed

+196
-13
lines changed

2 files changed

+196
-13
lines changed

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,9 +231,16 @@ query = '(type = "user" OR type = "admin") AND (age >= 18 AND age <= 65)'
231231

232232
# Multiple NOT conditions
233233
query = 'type = "user" AND status != "deleted" AND status != "banned"'
234+
235+
# Pattern matching with GLOB (using * as wildcard)
236+
query = 'name GLOB "John*"' # Names starting with "John"
237+
238+
# Pattern matching with suffix
239+
query = 'email GLOB "*@example.com"' # Emails ending with @example.com
234240
```
235241

236-
**Note:** String values in queries must be enclosed in double quotes (`"`). Numeric values do not require quotes.
242+
**Note:** String values in queries must be enclosed in double quotes (`"`). Numeric values do not require quotes. The `GLOB` operator supports pattern matching using `*` as a wildcard character.
243+
Note that the GLOB operator might be replace by a SQL standard LIKE operator in the future.
237244

238245
### Watch Entity Events
239246

tests/test_query_language.py

Lines changed: 188 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,140 @@ def create_test_entities(client: Arkiv) -> tuple[str, list[str]]:
2525

2626
# Build list of CreateOp operations
2727
c: list[CreateOp] = []
28-
add_to_c(c, {"batch": batch, "id": 1, "type": "A", "size": "xs", "idx": 1})
29-
add_to_c(c, {"batch": batch, "id": 2, "type": "A", "size": "s", "idx": 2})
30-
add_to_c(c, {"batch": batch, "id": 3, "type": "A", "size": "m", "idx": 3})
31-
add_to_c(c, {"batch": batch, "id": 4, "type": "A", "size": "l", "idx": 4})
28+
add_to_c(
29+
c,
30+
{
31+
"batch": batch,
32+
"id": 1,
33+
"type": "A",
34+
"size": "xs",
35+
"idx": 1,
36+
"email": "[email protected]",
37+
},
38+
)
39+
add_to_c(
40+
c,
41+
{
42+
"batch": batch,
43+
"id": 2,
44+
"type": "A",
45+
"size": "s",
46+
"idx": 2,
47+
"email": "[email protected]",
48+
},
49+
)
50+
add_to_c(
51+
c,
52+
{
53+
"batch": batch,
54+
"id": 3,
55+
"type": "A",
56+
"size": "m",
57+
"idx": 3,
58+
"email": "[email protected]",
59+
},
60+
)
61+
add_to_c(
62+
c,
63+
{
64+
"batch": batch,
65+
"id": 4,
66+
"type": "A",
67+
"size": "l",
68+
"idx": 4,
69+
"email": "[email protected]",
70+
},
71+
)
3272

33-
add_to_c(c, {"batch": batch, "id": 5, "type": "B", "size": "xs", "idx": 1})
34-
add_to_c(c, {"batch": batch, "id": 6, "type": "B", "size": "s", "idx": 2})
35-
add_to_c(c, {"batch": batch, "id": 7, "type": "B", "size": "m", "idx": 3})
36-
add_to_c(c, {"batch": batch, "id": 8, "type": "B", "size": "l", "idx": 4})
73+
add_to_c(
74+
c,
75+
{
76+
"batch": batch,
77+
"id": 5,
78+
"type": "B",
79+
"size": "xs",
80+
"idx": 1,
81+
"email": "[email protected]",
82+
},
83+
)
84+
add_to_c(
85+
c,
86+
{
87+
"batch": batch,
88+
"id": 6,
89+
"type": "B",
90+
"size": "s",
91+
"idx": 2,
92+
"email": "[email protected]",
93+
},
94+
)
95+
add_to_c(
96+
c,
97+
{
98+
"batch": batch,
99+
"id": 7,
100+
"type": "B",
101+
"size": "m",
102+
"idx": 3,
103+
"email": "[email protected]",
104+
},
105+
)
106+
add_to_c(
107+
c,
108+
{
109+
"batch": batch,
110+
"id": 8,
111+
"type": "B",
112+
"size": "l",
113+
"idx": 4,
114+
"email": "[email protected]",
115+
},
116+
)
37117

38-
add_to_c(c, {"batch": batch, "id": 9, "type": "C", "size": "xs", "idx": 1})
39-
add_to_c(c, {"batch": batch, "id": 10, "type": "C", "size": "s", "idx": 2})
40-
add_to_c(c, {"batch": batch, "id": 11, "type": "C", "size": "m", "idx": 3})
41-
add_to_c(c, {"batch": batch, "id": 12, "type": "C", "size": "l", "idx": 4})
118+
add_to_c(
119+
c,
120+
{
121+
"batch": batch,
122+
"id": 9,
123+
"type": "C",
124+
"size": "xs",
125+
"idx": 1,
126+
"email": "[email protected]",
127+
},
128+
)
129+
add_to_c(
130+
c,
131+
{
132+
"batch": batch,
133+
"id": 10,
134+
"type": "C",
135+
"size": "s",
136+
"idx": 2,
137+
"email": "[email protected]",
138+
},
139+
)
140+
add_to_c(
141+
c,
142+
{
143+
"batch": batch,
144+
"id": 11,
145+
"type": "C",
146+
"size": "m",
147+
"idx": 3,
148+
"email": "[email protected]",
149+
},
150+
)
151+
add_to_c(
152+
c,
153+
{
154+
"batch": batch,
155+
"id": 12,
156+
"type": "C",
157+
"size": "l",
158+
"idx": 4,
159+
"email": "[email protected]",
160+
},
161+
)
42162

43163
# Execute all creates in a single transaction
44164
operations = Operations(creates=c)
@@ -271,3 +391,59 @@ def test_query_language_in_idx_list(self, arkiv_client_http: Arkiv) -> None:
271391
"idx IN (1 3 4)",
272392
[1, 3, 4, 5, 7, 8, 9, 11, 12],
273393
)
394+
395+
# === LIKE/GLOB Tests ===#
396+
# GLOB operator tests (pattern matching with wildcards using email addresses)
397+
def test_query_language_glob_prefix(self, arkiv_client_http: Arkiv) -> None:
398+
"""Test GLOB with prefix pattern: emails starting with 'alice'."""
399+
execute_query_test(
400+
arkiv_client_http,
401+
"GLOB Prefix alice*",
402+
'email GLOB "alice*"',
403+
[1],
404+
)
405+
406+
def test_query_language_glob_suffix(self, arkiv_client_http: Arkiv) -> None:
407+
"""Test GLOB with suffix pattern: emails ending with @example.com."""
408+
execute_query_test(
409+
arkiv_client_http,
410+
"GLOB Suffix *@example.com",
411+
'email GLOB "*@example.com"',
412+
[1, 3, 5, 7, 9, 11],
413+
)
414+
415+
def test_query_language_glob_contains(self, arkiv_client_http: Arkiv) -> None:
416+
"""Test GLOB with contains pattern: emails containing 'test'."""
417+
execute_query_test(
418+
arkiv_client_http,
419+
"GLOB Contains *test*",
420+
'email GLOB "*test*"',
421+
[2, 6, 10],
422+
)
423+
424+
def test_query_language_glob_exact(self, arkiv_client_http: Arkiv) -> None:
425+
"""Test GLOB with exact match: exact email match."""
426+
execute_query_test(
427+
arkiv_client_http,
428+
"GLOB Exact [email protected]",
429+
'email GLOB "[email protected]"',
430+
[2],
431+
)
432+
433+
def test_query_language_glob_with_and(self, arkiv_client_http: Arkiv) -> None:
434+
"""Test GLOB with AND: type = 'A' AND email ends with .org."""
435+
execute_query_test(
436+
arkiv_client_http,
437+
"GLOB with AND",
438+
'type = "A" AND email GLOB "*@*.org"',
439+
[2, 4],
440+
)
441+
442+
def test_query_language_glob_with_or(self, arkiv_client_http: Arkiv) -> None:
443+
"""Test GLOB with OR: emails from example.org or test.org domains."""
444+
execute_query_test(
445+
arkiv_client_http,
446+
"GLOB with OR",
447+
'(email GLOB "*@example.org" OR email GLOB "*@test.org")',
448+
[2, 4, 6, 8, 10, 12],
449+
)

0 commit comments

Comments
 (0)