python-sql 1.6.0__py3-none-any.whl → 1.8.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_sql-1.6.0.dist-info → python_sql-1.8.0.dist-info}/METADATA +28 -48
- python_sql-1.8.0.dist-info/RECORD +41 -0
- {python_sql-1.6.0.dist-info → python_sql-1.8.0.dist-info}/WHEEL +1 -2
- python_sql-1.8.0.dist-info/licenses/COPYRIGHT +26 -0
- sql/__init__.py +24 -2
- sql/aggregate.py +16 -6
- sql/functions.py +63 -3
- sql/operators.py +36 -18
- sql/tests/test_aggregate.py +6 -6
- sql/tests/test_combining_query.py +1 -1
- sql/tests/test_conditionals.py +3 -3
- sql/tests/test_delete.py +4 -4
- sql/tests/test_functions.py +36 -4
- sql/tests/test_insert.py +4 -4
- sql/tests/test_join.py +2 -2
- sql/tests/test_lateral.py +1 -1
- sql/tests/test_merge.py +12 -12
- sql/tests/test_operators.py +84 -67
- sql/tests/test_order.py +3 -3
- sql/tests/test_select.py +62 -31
- sql/tests/test_update.py +6 -6
- sql/tests/test_with.py +3 -3
- python_sql-1.6.0.dist-info/RECORD +0 -41
- python_sql-1.6.0.dist-info/top_level.txt +0 -1
sql/tests/test_functions.py
CHANGED
|
@@ -4,7 +4,7 @@ import unittest
|
|
|
4
4
|
|
|
5
5
|
from sql import AliasManager, Flavor, Table, Window
|
|
6
6
|
from sql.functions import (
|
|
7
|
-
Abs, AtTimeZone, CurrentTime, Div, Function, FunctionKeyword,
|
|
7
|
+
Abs, AtTimeZone, CurrentTime, Div, Extract, Function, FunctionKeyword,
|
|
8
8
|
FunctionNotCallable, Overlay, Rank, Trim, WindowFunction)
|
|
9
9
|
|
|
10
10
|
|
|
@@ -70,7 +70,7 @@ class TestFunctions(unittest.TestCase):
|
|
|
70
70
|
abs_ = Abs(self.table.select(self.table.c1,
|
|
71
71
|
where=self.table.c2 == 'foo'))
|
|
72
72
|
self.assertEqual(str(abs_),
|
|
73
|
-
'ABS((SELECT "a"."c1" FROM "t" AS "a" WHERE
|
|
73
|
+
'ABS((SELECT "a"."c1" FROM "t" AS "a" WHERE "a"."c2" = %s))')
|
|
74
74
|
self.assertEqual(abs_.params, ('foo',))
|
|
75
75
|
|
|
76
76
|
def test_overlay(self):
|
|
@@ -110,7 +110,7 @@ class TestFunctions(unittest.TestCase):
|
|
|
110
110
|
self.table.select(self.table.tz, where=self.table.c1 == 'foo'))
|
|
111
111
|
self.assertEqual(str(time_zone),
|
|
112
112
|
'"c1" AT TIME ZONE '
|
|
113
|
-
'(SELECT "a"."tz" FROM "t" AS "a" WHERE
|
|
113
|
+
'(SELECT "a"."tz" FROM "t" AS "a" WHERE "a"."c1" = %s)')
|
|
114
114
|
self.assertEqual(time_zone.params, ('foo',))
|
|
115
115
|
|
|
116
116
|
def test_at_time_zone_mapping(self):
|
|
@@ -139,6 +139,38 @@ class TestFunctions(unittest.TestCase):
|
|
|
139
139
|
self.assertEqual(str(current_time), 'CURRENT_TIME')
|
|
140
140
|
self.assertEqual(current_time.params, ())
|
|
141
141
|
|
|
142
|
+
def test_extract(self):
|
|
143
|
+
extract = Extract(Extract.Fields.DAY, self.table.c)
|
|
144
|
+
self.assertEqual(str(extract), 'EXTRACT(DAY FROM "c")')
|
|
145
|
+
self.assertEqual(extract.params, ())
|
|
146
|
+
|
|
147
|
+
extract = Extract('day', self.table.c)
|
|
148
|
+
self.assertEqual(str(extract), 'EXTRACT(DAY FROM "c")')
|
|
149
|
+
self.assertEqual(extract.params, ())
|
|
150
|
+
|
|
151
|
+
extract = Extract(Extract.Fields.DAY, '2000-01-01')
|
|
152
|
+
self.assertEqual(str(extract), 'EXTRACT(DAY FROM %s)')
|
|
153
|
+
self.assertEqual(extract.params, ('2000-01-01',))
|
|
154
|
+
|
|
155
|
+
def test_extract_mapping(self):
|
|
156
|
+
class MyExtract(Function):
|
|
157
|
+
_function = 'MY_EXTRACT'
|
|
158
|
+
|
|
159
|
+
extract = Extract(Extract.Fields.DAY, '2000-01-01')
|
|
160
|
+
flavor = Flavor(function_mapping={
|
|
161
|
+
Extract: MyExtract,
|
|
162
|
+
})
|
|
163
|
+
Flavor.set(flavor)
|
|
164
|
+
try:
|
|
165
|
+
self.assertEqual(str(extract), 'MY_EXTRACT(%s, %s)')
|
|
166
|
+
self.assertEqual(extract.params, ('DAY', '2000-01-01'))
|
|
167
|
+
finally:
|
|
168
|
+
Flavor.set(Flavor())
|
|
169
|
+
|
|
170
|
+
def test_extract_invalid_field(self):
|
|
171
|
+
with self.assertRaises(ValueError):
|
|
172
|
+
Extract('foo', self.table.c)
|
|
173
|
+
|
|
142
174
|
|
|
143
175
|
class TestWindowFunction(unittest.TestCase):
|
|
144
176
|
|
|
@@ -160,7 +192,7 @@ class TestWindowFunction(unittest.TestCase):
|
|
|
160
192
|
|
|
161
193
|
with AliasManager():
|
|
162
194
|
self.assertEqual(str(function),
|
|
163
|
-
'RANK("a"."c") FILTER (WHERE
|
|
195
|
+
'RANK("a"."c") FILTER (WHERE "a"."c" > %s) OVER ()')
|
|
164
196
|
self.assertEqual(function.params, (0,))
|
|
165
197
|
|
|
166
198
|
def test_invalid_filter(self):
|
sql/tests/test_insert.py
CHANGED
|
@@ -73,7 +73,7 @@ class TestInsert(unittest.TestCase):
|
|
|
73
73
|
self.assertEqual(str(query),
|
|
74
74
|
'INSERT INTO "t1" AS "b" ("c") VALUES (%s) '
|
|
75
75
|
'RETURNING (SELECT "a"."c" FROM "t2" AS "a" '
|
|
76
|
-
'WHERE (
|
|
76
|
+
'WHERE ("a"."c1" = "b"."c") AND ("a"."c2" = %s))')
|
|
77
77
|
self.assertEqual(tuple(query.params), ('foo', 'bar'))
|
|
78
78
|
|
|
79
79
|
def test_insert_invalid_returning(self):
|
|
@@ -160,7 +160,7 @@ class TestInsert(unittest.TestCase):
|
|
|
160
160
|
|
|
161
161
|
self.assertEqual(str(query),
|
|
162
162
|
'INSERT INTO "t" AS "a" ("c1") VALUES (%s) '
|
|
163
|
-
'ON CONFLICT ("c1") WHERE
|
|
163
|
+
'ON CONFLICT ("c1") WHERE "a"."c2" = %s DO NOTHING')
|
|
164
164
|
self.assertEqual(tuple(query.params), ('foo', 'bar'))
|
|
165
165
|
|
|
166
166
|
def test_upsert_update(self):
|
|
@@ -188,7 +188,7 @@ class TestInsert(unittest.TestCase):
|
|
|
188
188
|
self.assertEqual(str(query),
|
|
189
189
|
'INSERT INTO "t" AS "a" ("c1") VALUES (%s) '
|
|
190
190
|
'ON CONFLICT DO UPDATE SET "c1" = (%s) '
|
|
191
|
-
'WHERE
|
|
191
|
+
'WHERE "a"."c2" = %s')
|
|
192
192
|
self.assertEqual(tuple(query.params), ('baz', 'foo', 'bar'))
|
|
193
193
|
|
|
194
194
|
def test_upsert_update_subquery(self):
|
|
@@ -218,7 +218,7 @@ class TestInsert(unittest.TestCase):
|
|
|
218
218
|
|
|
219
219
|
self.assertEqual(str(query),
|
|
220
220
|
'INSERT INTO "t" AS "a" ("c1") VALUES (%s) '
|
|
221
|
-
'ON CONFLICT DO UPDATE SET "c1" = (
|
|
221
|
+
'ON CONFLICT DO UPDATE SET "c1" = ("EXCLUDED"."c1" + %s)')
|
|
222
222
|
self.assertEqual(tuple(query.params), (1, 2))
|
|
223
223
|
|
|
224
224
|
def test_conflict_invalid_table(self):
|
sql/tests/test_join.py
CHANGED
|
@@ -18,7 +18,7 @@ class TestJoin(unittest.TestCase):
|
|
|
18
18
|
join.condition = t1.c == t2.c
|
|
19
19
|
with AliasManager():
|
|
20
20
|
self.assertEqual(str(join),
|
|
21
|
-
'"t1" AS "a" INNER JOIN "t2" AS "b" ON
|
|
21
|
+
'"t1" AS "a" INNER JOIN "t2" AS "b" ON "a"."c" = "b"."c"')
|
|
22
22
|
|
|
23
23
|
def test_join_invalid_left(self):
|
|
24
24
|
with self.assertRaises(ValueError):
|
|
@@ -45,7 +45,7 @@ class TestJoin(unittest.TestCase):
|
|
|
45
45
|
with AliasManager():
|
|
46
46
|
self.assertEqual(str(join),
|
|
47
47
|
'"t1" AS "a" INNER JOIN (SELECT * FROM "t2" AS "c") AS "b" '
|
|
48
|
-
'ON
|
|
48
|
+
'ON "a"."c" = "b"."c"')
|
|
49
49
|
self.assertEqual(tuple(join.params), ())
|
|
50
50
|
|
|
51
51
|
def test_join_function(self):
|
sql/tests/test_lateral.py
CHANGED
|
@@ -16,7 +16,7 @@ class TestLateral(unittest.TestCase):
|
|
|
16
16
|
|
|
17
17
|
self.assertEqual(str(query),
|
|
18
18
|
'SELECT * FROM "t1" AS "a", LATERAL '
|
|
19
|
-
'(SELECT * FROM "t2" AS "c" WHERE
|
|
19
|
+
'(SELECT * FROM "t2" AS "c" WHERE "c"."id" = "a"."t2") AS "b"')
|
|
20
20
|
self.assertEqual(tuple(query.params), ())
|
|
21
21
|
|
|
22
22
|
def test_lateral_function(self):
|
sql/tests/test_merge.py
CHANGED
|
@@ -18,7 +18,7 @@ class TestMerge(unittest.TestCase):
|
|
|
18
18
|
self.assertEqual(
|
|
19
19
|
str(query),
|
|
20
20
|
'MERGE INTO "t" AS "a" USING "s" AS "b" '
|
|
21
|
-
'ON
|
|
21
|
+
'ON "a"."c1" = "b"."c2" '
|
|
22
22
|
'WHEN MATCHED THEN DO NOTHING')
|
|
23
23
|
self.assertEqual(query.params, ())
|
|
24
24
|
|
|
@@ -46,7 +46,7 @@ class TestMerge(unittest.TestCase):
|
|
|
46
46
|
self.assertEqual(
|
|
47
47
|
str(query),
|
|
48
48
|
'MERGE INTO "t" AS "a" USING "s" AS "b" '
|
|
49
|
-
'ON (
|
|
49
|
+
'ON ("a"."c1" = "b"."c2") AND ("a"."c3" = %s) '
|
|
50
50
|
'WHEN MATCHED THEN DO NOTHING')
|
|
51
51
|
self.assertEqual(query.params, (42,))
|
|
52
52
|
|
|
@@ -58,9 +58,9 @@ class TestMerge(unittest.TestCase):
|
|
|
58
58
|
self.assertEqual(
|
|
59
59
|
str(query),
|
|
60
60
|
'MERGE INTO "t" AS "a" USING "s" AS "b" '
|
|
61
|
-
'ON
|
|
61
|
+
'ON "a"."c1" = "b"."c2" '
|
|
62
62
|
'WHEN MATCHED '
|
|
63
|
-
'AND (
|
|
63
|
+
'AND ("b"."c3" = %s) AND ("a"."c4" = "b"."c5") '
|
|
64
64
|
'THEN DO NOTHING')
|
|
65
65
|
self.assertEqual(query.params, (42,))
|
|
66
66
|
|
|
@@ -73,9 +73,9 @@ class TestMerge(unittest.TestCase):
|
|
|
73
73
|
self.assertEqual(
|
|
74
74
|
str(query),
|
|
75
75
|
'MERGE INTO "t" AS "a" USING "s" AS "b" '
|
|
76
|
-
'ON
|
|
76
|
+
'ON "a"."c1" = "b"."c2" '
|
|
77
77
|
'WHEN MATCHED THEN '
|
|
78
|
-
'UPDATE SET "c1" =
|
|
78
|
+
'UPDATE SET "c1" = "a"."c1" + "b"."c2", "c2" = %s')
|
|
79
79
|
self.assertEqual(query.params, (42,))
|
|
80
80
|
|
|
81
81
|
def test_matched_delete(self):
|
|
@@ -84,7 +84,7 @@ class TestMerge(unittest.TestCase):
|
|
|
84
84
|
self.assertEqual(
|
|
85
85
|
str(query),
|
|
86
86
|
'MERGE INTO "t" AS "a" USING "s" AS "b" '
|
|
87
|
-
'ON
|
|
87
|
+
'ON "a"."c1" = "b"."c2" '
|
|
88
88
|
'WHEN MATCHED THEN DELETE')
|
|
89
89
|
self.assertEqual(query.params, ())
|
|
90
90
|
|
|
@@ -94,7 +94,7 @@ class TestMerge(unittest.TestCase):
|
|
|
94
94
|
self.assertEqual(
|
|
95
95
|
str(query),
|
|
96
96
|
'MERGE INTO "t" AS "a" USING "s" AS "b" '
|
|
97
|
-
'ON
|
|
97
|
+
'ON "a"."c1" = "b"."c2" '
|
|
98
98
|
'WHEN NOT MATCHED THEN DO NOTHING')
|
|
99
99
|
self.assertEqual(query.params, ())
|
|
100
100
|
|
|
@@ -107,7 +107,7 @@ class TestMerge(unittest.TestCase):
|
|
|
107
107
|
self.assertEqual(
|
|
108
108
|
str(query),
|
|
109
109
|
'MERGE INTO "t" AS "a" USING "s" AS "b" '
|
|
110
|
-
'ON
|
|
110
|
+
'ON "a"."c1" = "b"."c2" '
|
|
111
111
|
'WHEN NOT MATCHED THEN '
|
|
112
112
|
'INSERT ("c1", "c2") VALUES ("b"."c3", "b"."c4")')
|
|
113
113
|
self.assertEqual(query.params, ())
|
|
@@ -119,7 +119,7 @@ class TestMerge(unittest.TestCase):
|
|
|
119
119
|
self.assertEqual(
|
|
120
120
|
str(query),
|
|
121
121
|
'MERGE INTO "t" AS "a" USING "s" AS "b" '
|
|
122
|
-
'ON
|
|
122
|
+
'ON "a"."c1" = "b"."c2" '
|
|
123
123
|
'WHEN NOT MATCHED THEN '
|
|
124
124
|
'INSERT ("c1", "c2") DEFAULT VALUES')
|
|
125
125
|
self.assertEqual(query.params, ())
|
|
@@ -141,9 +141,9 @@ class TestMerge(unittest.TestCase):
|
|
|
141
141
|
source, self.target.c1 == source.c2, Matched(), with_=[w])
|
|
142
142
|
self.assertEqual(
|
|
143
143
|
str(query),
|
|
144
|
-
'WITH "a" AS (SELECT * FROM "t1" AS "d" WHERE
|
|
144
|
+
'WITH "a" AS (SELECT * FROM "t1" AS "d" WHERE "d"."c2" = %s) '
|
|
145
145
|
'MERGE INTO "t" AS "b" '
|
|
146
146
|
'USING (SELECT * FROM "a" AS "a") AS "c" '
|
|
147
|
-
'ON
|
|
147
|
+
'ON "b"."c1" = "c"."c2" '
|
|
148
148
|
'WHEN MATCHED THEN DO NOTHING')
|
|
149
149
|
self.assertEqual(query.params, (42,))
|