-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_select.py
More file actions
366 lines (298 loc) · 11.7 KB
/
test_select.py
File metadata and controls
366 lines (298 loc) · 11.7 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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
"""Tests for SELECT query building."""
import pytest
from sqlink import Query, Table, F, Func, Raw, Subquery
from sqlink.expressions import OrderExpr
class TestBasicSelect:
def test_select_all_default(self):
sql, params = Query("users").select_all().build()
assert sql == 'SELECT * FROM "users"'
assert params == []
def test_select_specific_columns(self):
sql, params = Query("users").select("id", "name", "email").build()
assert sql == 'SELECT "id", "name", "email" FROM "users"'
assert params == []
def test_select_star(self):
sql, params = Query("users").select("*").build()
assert sql == 'SELECT * FROM "users"'
def test_select_with_alias(self):
sql, params = Query("users", alias="u").select("id").build()
assert sql == 'SELECT "id" FROM "users" AS "u"'
def test_select_distinct(self):
sql, params = Query("users").select("name").distinct().build()
assert sql == 'SELECT DISTINCT "name" FROM "users"'
def test_add_select(self):
q = Query("users").select("id").add_select("name", "email")
sql, params = q.build()
assert sql == 'SELECT "id", "name", "email" FROM "users"'
def test_from_table(self):
sql, params = Query().select("id").from_table("users").build()
assert sql == 'SELECT "id" FROM "users"'
def test_from_table_with_alias(self):
sql, params = Query().select("id").from_table("users", "u").build()
assert sql == 'SELECT "id" FROM "users" AS "u"'
class TestWhere:
def test_simple_eq(self):
sql, params = Query("users").select("*").where(F("id") == 1).build()
assert sql == 'SELECT * FROM "users" WHERE "id" = ?'
assert params == [1]
def test_not_equal(self):
sql, params = Query("users").select("*").where(F("status") != "deleted").build()
assert sql == 'SELECT * FROM "users" WHERE "status" != ?'
assert params == ["deleted"]
def test_greater_than(self):
sql, params = Query("users").select("*").where(F("age") > 18).build()
assert sql == 'SELECT * FROM "users" WHERE "age" > ?'
assert params == [18]
def test_greater_equal(self):
sql, params = Query("users").select("*").where(F("age") >= 18).build()
assert sql == 'SELECT * FROM "users" WHERE "age" >= ?'
assert params == [18]
def test_less_than(self):
sql, params = Query("users").select("*").where(F("age") < 65).build()
assert sql == 'SELECT * FROM "users" WHERE "age" < ?'
assert params == [65]
def test_less_equal(self):
sql, params = Query("users").select("*").where(F("age") <= 65).build()
assert sql == 'SELECT * FROM "users" WHERE "age" <= ?'
assert params == [65]
def test_multiple_where(self):
sql, params = (
Query("users")
.select("*")
.where(F("age") > 18, F("active") == True)
.build()
)
assert "WHERE" in sql
assert '"age" > ?' in sql
assert '"active" = ?' in sql
assert params == [18, True]
def test_where_raw(self):
sql, params = (
Query("users")
.select("*")
.where_raw('"score" > ? AND "level" < ?', [100, 5])
.build()
)
assert '"score" > ? AND "level" < ?' in sql
assert params == [100, 5]
def test_where_is_null(self):
sql, params = Query("users").select("*").where(F("deleted_at") == None).build()
assert '"deleted_at" IS NULL' in sql
assert params == []
def test_where_is_not_null(self):
sql, params = Query("users").select("*").where(F("email") != None).build()
assert '"email" IS NOT NULL' in sql
assert params == []
class TestExpressions:
def test_and_expr(self):
expr = (F("a") > 1) & (F("b") < 10)
sql, params = Query("t").select("*").where(expr).build()
assert '("a" > ? AND "b" < ?)' in sql
assert params == [1, 10]
def test_or_expr(self):
expr = (F("a") > 1) | (F("b") < 10)
sql, params = Query("t").select("*").where(expr).build()
assert '("a" > ? OR "b" < ?)' in sql
assert params == [1, 10]
def test_not_expr(self):
expr = ~(F("active") == True)
sql, params = Query("t").select("*").where(expr).build()
assert 'NOT ("active" = ?)' in sql
assert params == [True]
def test_in_expr(self):
sql, params = Query("users").select("*").where(F("id").is_in([1, 2, 3])).build()
assert '"id" IN (?, ?, ?)' in sql
assert params == [1, 2, 3]
def test_in_empty(self):
sql, params = Query("users").select("*").where(F("id").is_in([])).build()
assert "1 = 0" in sql
assert params == []
def test_not_in(self):
sql, params = Query("users").select("*").where(F("id").not_in([4, 5])).build()
assert '"id" NOT IN (?, ?)' in sql
assert params == [4, 5]
def test_not_in_empty(self):
sql, params = Query("users").select("*").where(F("id").not_in([])).build()
assert "1 = 1" in sql
def test_between(self):
sql, params = Query("users").select("*").where(F("age").between(18, 65)).build()
assert '"age" BETWEEN ? AND ?' in sql
assert params == [18, 65]
def test_like(self):
sql, params = Query("users").select("*").where(F("name").like("%john%")).build()
assert '"name" LIKE ?' in sql
assert params == ["%john%"]
def test_is_null_method(self):
sql, params = Query("users").select("*").where(F("email").is_null()).build()
assert '"email" IS NULL' in sql
def test_is_not_null_method(self):
sql, params = Query("users").select("*").where(F("email").is_not_null()).build()
assert '"email" IS NOT NULL' in sql
class TestOrderBy:
def test_order_by_string(self):
sql, _ = Query("users").select("*").order_by("name").build()
assert 'ORDER BY "name"' in sql
def test_order_by_asc(self):
sql, _ = Query("users").select("*").order_by_asc("name").build()
assert 'ORDER BY "name" ASC' in sql
def test_order_by_desc(self):
sql, _ = Query("users").select("*").order_by_desc("created_at").build()
assert 'ORDER BY "created_at" DESC' in sql
def test_order_by_f_asc(self):
sql, _ = Query("users").select("*").order_by(F("name").asc()).build()
assert 'ORDER BY "name" ASC' in sql
def test_order_by_f_desc(self):
sql, _ = Query("users").select("*").order_by(F("age").desc()).build()
assert 'ORDER BY "age" DESC' in sql
def test_multiple_order_by(self):
sql, _ = (
Query("users")
.select("*")
.order_by(F("name").asc(), F("age").desc())
.build()
)
assert '"name" ASC' in sql
assert '"age" DESC' in sql
class TestLimitOffset:
def test_limit(self):
sql, _ = Query("users").select("*").limit(10).build()
assert "LIMIT 10" in sql
def test_offset(self):
sql, _ = Query("users").select("*").offset(20).build()
assert "OFFSET 20" in sql
def test_limit_offset(self):
sql, _ = Query("users").select("*").limit(10).offset(20).build()
assert "LIMIT 10" in sql
assert "OFFSET 20" in sql
def test_paginate(self):
sql, _ = Query("users").select("*").paginate(page=3, per_page=10).build()
assert "LIMIT 10" in sql
assert "OFFSET 20" in sql
def test_paginate_first_page(self):
sql, _ = Query("users").select("*").paginate(page=1, per_page=25).build()
assert "LIMIT 25" in sql
assert "OFFSET 0" in sql
class TestGroupBy:
def test_group_by(self):
sql, _ = Query("orders").select("status").group_by("status").build()
assert 'GROUP BY "status"' in sql
def test_group_by_multiple(self):
sql, _ = (
Query("orders")
.select("status", "country")
.group_by("status", "country")
.build()
)
assert 'GROUP BY "status", "country"' in sql
def test_having(self):
sql, params = (
Query("orders")
.select("status", Raw("COUNT(*) as cnt"))
.group_by("status")
.having(Raw("COUNT(*) > ?", [5]))
.build()
)
assert "HAVING COUNT(*) > ?" in sql
assert params == [5]
class TestJoin:
def test_inner_join(self):
sql, params = (
Query("users")
.select("users.id", "orders.total")
.join("orders", Raw('"users"."id" = "orders"."user_id"'))
.build()
)
assert 'INNER JOIN "orders"' in sql
def test_left_join(self):
sql, _ = (
Query("users")
.select("*")
.left_join("orders", Raw('"users"."id" = "orders"."user_id"'))
.build()
)
assert 'LEFT JOIN "orders"' in sql
def test_right_join(self):
sql, _ = (
Query("users")
.select("*")
.right_join("orders", Raw('"users"."id" = "orders"."user_id"'))
.build()
)
assert 'RIGHT JOIN "orders"' in sql
def test_full_join(self):
sql, _ = (
Query("users")
.select("*")
.full_join("orders", Raw('"users"."id" = "orders"."user_id"'))
.build()
)
assert 'FULL OUTER JOIN "orders"' in sql
def test_cross_join(self):
sql, _ = Query("users").select("*").cross_join("colors").build()
assert 'CROSS JOIN "colors"' in sql
def test_join_with_alias(self):
sql, _ = (
Query("users")
.select("*")
.join("orders", Raw('"u"."id" = "o"."user_id"'), alias="o")
.build()
)
assert '"orders" AS "o"' in sql
def test_join_raw(self):
sql, _ = (
Query("users")
.select("*")
.join_raw("NATURAL JOIN orders")
.build()
)
assert "NATURAL JOIN orders" in sql
class TestSubquery:
def test_from_subquery(self):
inner = Query("orders").select("user_id", Raw("SUM(total) as total_sum")).group_by("user_id")
sql, params = (
Query()
.select("user_id", "total_sum")
.from_subquery(inner, "sub")
.build()
)
assert "FROM (SELECT" in sql
assert "AS sub" in sql
def test_where_subquery(self):
from sqlink import Exists
sub = Query("orders").select("1").where(Raw('"orders"."user_id" = "users"."id"'))
sql, params = (
Query("users")
.select("*")
.where(Exists(sub))
.build()
)
assert "EXISTS (SELECT" in sql
class TestClone:
def test_clone_independence(self):
q1 = Query("users").select("*").where(F("active") == True)
q2 = q1.clone().where(F("age") > 18)
sql1, p1 = q1.build()
sql2, p2 = q2.build()
assert len(p1) == 1
assert len(p2) == 2
def test_clone_preserves_original(self):
q = Query("users").select("id", "name")
q2 = q.clone().limit(10)
sql1, _ = q.build()
sql2, _ = q2.build()
assert "LIMIT" not in sql1
assert "LIMIT 10" in sql2
class TestTable:
def test_table_select(self):
users = Table("users")
sql, _ = users.select("id", "name").build()
assert 'SELECT "id", "name" FROM "users"' == sql
def test_table_delete(self):
users = Table("users")
sql, params = users.delete().where(F("id") == 1).build()
assert 'DELETE FROM "users"' in sql
assert params == [1]
def test_table_with_alias(self):
users = Table("users", alias="u")
sql, _ = users.select("id").build()
assert '"users" AS "u"' in sql