python-sql 1.5.1__py3-none-any.whl → 1.5.2__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.5.1.dist-info → python_sql-1.5.2.dist-info}/METADATA +1 -1
- python_sql-1.5.2.dist-info/RECORD +41 -0
- {python_sql-1.5.1.dist-info → python_sql-1.5.2.dist-info}/WHEEL +1 -1
- sql/__init__.py +170 -98
- sql/aggregate.py +21 -6
- sql/functions.py +9 -8
- sql/operators.py +6 -3
- sql/tests/test_aggregate.py +25 -1
- sql/tests/test_alias.py +15 -0
- sql/tests/test_collate.py +0 -5
- sql/tests/test_combining_query.py +5 -1
- sql/tests/test_delete.py +21 -1
- sql/tests/test_excluded.py +15 -0
- sql/tests/test_expression.py +17 -0
- sql/tests/test_flavor.py +46 -0
- sql/tests/test_for.py +4 -0
- sql/tests/test_from.py +25 -0
- sql/tests/test_from_item.py +46 -0
- sql/tests/test_functions.py +17 -1
- sql/tests/test_grouping.py +13 -0
- sql/tests/test_insert.py +57 -1
- sql/tests/test_join.py +23 -0
- sql/tests/test_lateral.py +1 -1
- sql/tests/test_merge.py +43 -5
- sql/tests/test_operators.py +20 -1
- sql/tests/test_order.py +16 -7
- sql/tests/test_rollup.py +13 -0
- sql/tests/test_select.py +56 -0
- sql/tests/test_update.py +8 -0
- sql/tests/test_window.py +24 -0
- sql/tests/test_with.py +4 -0
- python_sql-1.5.1.dist-info/RECORD +0 -34
- {python_sql-1.5.1.dist-info → python_sql-1.5.2.dist-info}/top_level.txt +0 -0
sql/__init__.py
CHANGED
|
@@ -7,7 +7,7 @@ from collections import defaultdict
|
|
|
7
7
|
from itertools import chain
|
|
8
8
|
from threading import current_thread, local
|
|
9
9
|
|
|
10
|
-
__version__ = '1.5.
|
|
10
|
+
__version__ = '1.5.2'
|
|
11
11
|
__all__ = [
|
|
12
12
|
'Flavor', 'Table', 'Values', 'Literal', 'Column', 'Grouping', 'Conflict',
|
|
13
13
|
'Matched', 'MatchedUpdate', 'MatchedDelete',
|
|
@@ -62,17 +62,23 @@ class Flavor(object):
|
|
|
62
62
|
def __init__(self, limitstyle='limit', max_limit=None, paramstyle='format',
|
|
63
63
|
ilike=False, no_as=False, no_boolean=False, null_ordering=True,
|
|
64
64
|
function_mapping=None, filter_=False, escape_empty=False):
|
|
65
|
-
|
|
65
|
+
if limitstyle not in {'fetch', 'limit', 'rownum'}:
|
|
66
|
+
raise ValueError("unsupported limitstyle: %r" % limitstyle)
|
|
66
67
|
self.limitstyle = limitstyle
|
|
68
|
+
if (max_limit is not None
|
|
69
|
+
and not isinstance(max_limit, numbers.Integral)):
|
|
70
|
+
raise ValueError("unsupported max_limit: %r" % max_limit)
|
|
67
71
|
self.max_limit = max_limit
|
|
72
|
+
if paramstyle not in {'format', 'qmark'}:
|
|
73
|
+
raise ValueError("unsupported paramstyle: %r" % paramstyle)
|
|
68
74
|
self.paramstyle = paramstyle
|
|
69
|
-
self.ilike = ilike
|
|
70
|
-
self.no_as = no_as
|
|
71
|
-
self.no_boolean = no_boolean
|
|
72
|
-
self.null_ordering = null_ordering
|
|
73
|
-
self.function_mapping = function_mapping or {}
|
|
74
|
-
self.filter_ = filter_
|
|
75
|
-
self.escape_empty = escape_empty
|
|
75
|
+
self.ilike = bool(ilike)
|
|
76
|
+
self.no_as = bool(no_as)
|
|
77
|
+
self.no_boolean = bool(no_boolean)
|
|
78
|
+
self.null_ordering = bool(null_ordering)
|
|
79
|
+
self.function_mapping = dict(function_mapping or {})
|
|
80
|
+
self.filter_ = bool(filter_)
|
|
81
|
+
self.escape_empty = bool(escape_empty)
|
|
76
82
|
|
|
77
83
|
@property
|
|
78
84
|
def param(self):
|
|
@@ -213,7 +219,8 @@ class WithQuery(Query):
|
|
|
213
219
|
if value is not None:
|
|
214
220
|
if isinstance(value, With):
|
|
215
221
|
value = [value]
|
|
216
|
-
|
|
222
|
+
if any(not isinstance(w, With) for w in value):
|
|
223
|
+
raise ValueError("invalid with: %r" % value)
|
|
217
224
|
self._with = value
|
|
218
225
|
|
|
219
226
|
def _with_str(self):
|
|
@@ -252,7 +259,8 @@ class FromItem(object):
|
|
|
252
259
|
return Column(self, name)
|
|
253
260
|
|
|
254
261
|
def __add__(self, other):
|
|
255
|
-
|
|
262
|
+
if not isinstance(other, FromItem):
|
|
263
|
+
return NotImplemented
|
|
256
264
|
return From((self, other))
|
|
257
265
|
|
|
258
266
|
def select(self, *args, **kwargs):
|
|
@@ -348,7 +356,8 @@ class SelectQuery(WithQuery):
|
|
|
348
356
|
if value is not None:
|
|
349
357
|
if isinstance(value, Expression):
|
|
350
358
|
value = [value]
|
|
351
|
-
|
|
359
|
+
if any(not isinstance(col, Expression) for col in value):
|
|
360
|
+
raise ValueError("invalid order by: %r" % value)
|
|
352
361
|
self._order_by = value
|
|
353
362
|
|
|
354
363
|
@property
|
|
@@ -365,7 +374,8 @@ class SelectQuery(WithQuery):
|
|
|
365
374
|
@limit.setter
|
|
366
375
|
def limit(self, value):
|
|
367
376
|
if value is not None:
|
|
368
|
-
|
|
377
|
+
if not isinstance(value, numbers.Integral):
|
|
378
|
+
raise ValueError("invalid limit: %r" % value)
|
|
369
379
|
self._limit = value
|
|
370
380
|
|
|
371
381
|
@property
|
|
@@ -375,7 +385,8 @@ class SelectQuery(WithQuery):
|
|
|
375
385
|
@offset.setter
|
|
376
386
|
def offset(self, value):
|
|
377
387
|
if value is not None:
|
|
378
|
-
|
|
388
|
+
if not isinstance(value, numbers.Integral):
|
|
389
|
+
raise ValueError("invalid offset: %r" % value)
|
|
379
390
|
self._offset = value
|
|
380
391
|
|
|
381
392
|
@property
|
|
@@ -464,7 +475,8 @@ class Select(FromItem, SelectQuery):
|
|
|
464
475
|
if value is not None:
|
|
465
476
|
if isinstance(value, Expression):
|
|
466
477
|
value = [value]
|
|
467
|
-
|
|
478
|
+
if any(not isinstance(col, Expression) for col in value):
|
|
479
|
+
raise ValueError("invalid distinct on: %r" % value)
|
|
468
480
|
self._distinct_on = value
|
|
469
481
|
|
|
470
482
|
@property
|
|
@@ -473,7 +485,10 @@ class Select(FromItem, SelectQuery):
|
|
|
473
485
|
|
|
474
486
|
@columns.setter
|
|
475
487
|
def columns(self, value):
|
|
476
|
-
|
|
488
|
+
if any(
|
|
489
|
+
not isinstance(col, (Expression, SelectQuery))
|
|
490
|
+
for col in value):
|
|
491
|
+
raise ValueError("invalid columns: %r" % value)
|
|
477
492
|
self._columns = tuple(value)
|
|
478
493
|
|
|
479
494
|
@property
|
|
@@ -484,7 +499,8 @@ class Select(FromItem, SelectQuery):
|
|
|
484
499
|
def where(self, value):
|
|
485
500
|
from sql.operators import And, Or
|
|
486
501
|
if value is not None:
|
|
487
|
-
|
|
502
|
+
if not isinstance(value, (Expression, And, Or)):
|
|
503
|
+
raise ValueError("invalid where: %r" % value)
|
|
488
504
|
self._where = value
|
|
489
505
|
|
|
490
506
|
@property
|
|
@@ -496,7 +512,8 @@ class Select(FromItem, SelectQuery):
|
|
|
496
512
|
if value is not None:
|
|
497
513
|
if isinstance(value, Expression):
|
|
498
514
|
value = [value]
|
|
499
|
-
|
|
515
|
+
if any(not isinstance(col, Expression) for col in value):
|
|
516
|
+
raise ValueError("invalid group by: %r" % value)
|
|
500
517
|
self._group_by = value
|
|
501
518
|
|
|
502
519
|
@property
|
|
@@ -507,7 +524,8 @@ class Select(FromItem, SelectQuery):
|
|
|
507
524
|
def having(self, value):
|
|
508
525
|
from sql.operators import And, Or
|
|
509
526
|
if value is not None:
|
|
510
|
-
|
|
527
|
+
if not isinstance(value, (Expression, And, Or)):
|
|
528
|
+
raise ValueError("invalid having: %r" % value)
|
|
511
529
|
self._having = value
|
|
512
530
|
|
|
513
531
|
@property
|
|
@@ -519,7 +537,8 @@ class Select(FromItem, SelectQuery):
|
|
|
519
537
|
if value is not None:
|
|
520
538
|
if isinstance(value, For):
|
|
521
539
|
value = [value]
|
|
522
|
-
|
|
540
|
+
if any(not isinstance(f, For) for f in value):
|
|
541
|
+
raise ValueError("invalid for: %r" % value)
|
|
523
542
|
self._for_ = value
|
|
524
543
|
|
|
525
544
|
@property
|
|
@@ -547,7 +566,8 @@ class Select(FromItem, SelectQuery):
|
|
|
547
566
|
@windows.setter
|
|
548
567
|
def windows(self, value):
|
|
549
568
|
if value is not None:
|
|
550
|
-
|
|
569
|
+
if any(not isinstance(w, Window) for w in value):
|
|
570
|
+
raise ValueError("invalid windows: %r" % value)
|
|
551
571
|
self._windows = value
|
|
552
572
|
|
|
553
573
|
@staticmethod
|
|
@@ -707,7 +727,8 @@ class Insert(WithQuery):
|
|
|
707
727
|
|
|
708
728
|
@table.setter
|
|
709
729
|
def table(self, value):
|
|
710
|
-
|
|
730
|
+
if not isinstance(value, Table):
|
|
731
|
+
raise ValueError("invalid table: %r" % value)
|
|
711
732
|
self._table = value
|
|
712
733
|
|
|
713
734
|
@property
|
|
@@ -717,8 +738,10 @@ class Insert(WithQuery):
|
|
|
717
738
|
@columns.setter
|
|
718
739
|
def columns(self, value):
|
|
719
740
|
if value is not None:
|
|
720
|
-
|
|
721
|
-
|
|
741
|
+
if any(
|
|
742
|
+
not isinstance(col, Column) or col.table != self.table
|
|
743
|
+
for col in value):
|
|
744
|
+
raise ValueError("invalid columns: %r" % value)
|
|
722
745
|
self._columns = value
|
|
723
746
|
|
|
724
747
|
@property
|
|
@@ -728,7 +751,8 @@ class Insert(WithQuery):
|
|
|
728
751
|
@values.setter
|
|
729
752
|
def values(self, value):
|
|
730
753
|
if value is not None:
|
|
731
|
-
|
|
754
|
+
if not isinstance(value, (list, Select)):
|
|
755
|
+
raise ValueError("invalid values: %r" % value)
|
|
732
756
|
if isinstance(value, list):
|
|
733
757
|
value = Values(value)
|
|
734
758
|
self._values = value
|
|
@@ -740,8 +764,8 @@ class Insert(WithQuery):
|
|
|
740
764
|
@on_conflict.setter
|
|
741
765
|
def on_conflict(self, value):
|
|
742
766
|
if value is not None:
|
|
743
|
-
|
|
744
|
-
|
|
767
|
+
if not isinstance(value, Conflict) or value.table != self.table:
|
|
768
|
+
raise ValueError("invalid on conflict: %r" % value)
|
|
745
769
|
self._on_conflict = value
|
|
746
770
|
|
|
747
771
|
@property
|
|
@@ -751,7 +775,8 @@ class Insert(WithQuery):
|
|
|
751
775
|
@returning.setter
|
|
752
776
|
def returning(self, value):
|
|
753
777
|
if value is not None:
|
|
754
|
-
|
|
778
|
+
if not isinstance(value, list):
|
|
779
|
+
raise ValueError("invalid returning: %r" % value)
|
|
755
780
|
self._returning = value
|
|
756
781
|
|
|
757
782
|
@staticmethod
|
|
@@ -834,7 +859,8 @@ class Conflict(object):
|
|
|
834
859
|
|
|
835
860
|
@table.setter
|
|
836
861
|
def table(self, value):
|
|
837
|
-
|
|
862
|
+
if not isinstance(value, Table):
|
|
863
|
+
raise ValueError("invalid table: %r" % value)
|
|
838
864
|
self._table = value
|
|
839
865
|
|
|
840
866
|
@property
|
|
@@ -844,8 +870,10 @@ class Conflict(object):
|
|
|
844
870
|
@indexed_columns.setter
|
|
845
871
|
def indexed_columns(self, value):
|
|
846
872
|
if value is not None:
|
|
847
|
-
|
|
848
|
-
|
|
873
|
+
if any(
|
|
874
|
+
not isinstance(col, Column) or col.table != self.table
|
|
875
|
+
for col in value):
|
|
876
|
+
raise ValueError("invalid indexed columns: %r" % value)
|
|
849
877
|
self._indexed_columns = value
|
|
850
878
|
|
|
851
879
|
@property
|
|
@@ -856,7 +884,8 @@ class Conflict(object):
|
|
|
856
884
|
def index_where(self, value):
|
|
857
885
|
from sql.operators import And, Or
|
|
858
886
|
if value is not None:
|
|
859
|
-
|
|
887
|
+
if not isinstance(value, (Expression, And, Or)):
|
|
888
|
+
raise ValueError("invalid index where: %r" % value)
|
|
860
889
|
self._index_where = value
|
|
861
890
|
|
|
862
891
|
@property
|
|
@@ -866,8 +895,10 @@ class Conflict(object):
|
|
|
866
895
|
@columns.setter
|
|
867
896
|
def columns(self, value):
|
|
868
897
|
if value is not None:
|
|
869
|
-
|
|
870
|
-
|
|
898
|
+
if any(
|
|
899
|
+
not isinstance(col, Column) or col.table != self.table
|
|
900
|
+
for col in value):
|
|
901
|
+
raise ValueError("invalid columns: %r" % value)
|
|
871
902
|
self._columns = value
|
|
872
903
|
|
|
873
904
|
@property
|
|
@@ -877,7 +908,8 @@ class Conflict(object):
|
|
|
877
908
|
@values.setter
|
|
878
909
|
def values(self, value):
|
|
879
910
|
if value is not None:
|
|
880
|
-
|
|
911
|
+
if not isinstance(value, (list, Select)):
|
|
912
|
+
raise ValueError("invalid values: %r" % value)
|
|
881
913
|
if isinstance(value, list):
|
|
882
914
|
value = Values([value])
|
|
883
915
|
self._values = value
|
|
@@ -890,7 +922,8 @@ class Conflict(object):
|
|
|
890
922
|
def where(self, value):
|
|
891
923
|
from sql.operators import And, Or
|
|
892
924
|
if value is not None:
|
|
893
|
-
|
|
925
|
+
if not isinstance(value, (Expression, And, Or)):
|
|
926
|
+
raise ValueError("invalid where: %r" % value)
|
|
894
927
|
self._where = value
|
|
895
928
|
|
|
896
929
|
def __str__(self):
|
|
@@ -961,7 +994,8 @@ class Update(Insert):
|
|
|
961
994
|
def values(self, value):
|
|
962
995
|
if isinstance(value, Select):
|
|
963
996
|
value = [value]
|
|
964
|
-
|
|
997
|
+
if not isinstance(value, list):
|
|
998
|
+
raise ValueError("invalid values: %r" % value)
|
|
965
999
|
self._values = value
|
|
966
1000
|
|
|
967
1001
|
@property
|
|
@@ -972,9 +1006,14 @@ class Update(Insert):
|
|
|
972
1006
|
def where(self, value):
|
|
973
1007
|
from sql.operators import And, Or
|
|
974
1008
|
if value is not None:
|
|
975
|
-
|
|
1009
|
+
if not isinstance(value, (Expression, And, Or)):
|
|
1010
|
+
raise ValueError("invalid where: %r" % value)
|
|
976
1011
|
self._where = value
|
|
977
1012
|
|
|
1013
|
+
@staticmethod
|
|
1014
|
+
def _format_column(value):
|
|
1015
|
+
return Select._format_column(value)
|
|
1016
|
+
|
|
978
1017
|
def __str__(self):
|
|
979
1018
|
assert all(col.table == self.table for col in self.columns)
|
|
980
1019
|
# Get columns without alias
|
|
@@ -992,7 +1031,7 @@ class Update(Insert):
|
|
|
992
1031
|
returning = ''
|
|
993
1032
|
if self.returning:
|
|
994
1033
|
returning = ' RETURNING ' + ', '.join(
|
|
995
|
-
map(self.
|
|
1034
|
+
map(self._format_column, self.returning))
|
|
996
1035
|
return (self._with_str()
|
|
997
1036
|
+ 'UPDATE %s AS "%s" SET ' % (self.table, self.table.alias)
|
|
998
1037
|
+ values + from_ + where + returning)
|
|
@@ -1037,7 +1076,8 @@ class Delete(WithQuery):
|
|
|
1037
1076
|
|
|
1038
1077
|
@table.setter
|
|
1039
1078
|
def table(self, value):
|
|
1040
|
-
|
|
1079
|
+
if not isinstance(value, Table):
|
|
1080
|
+
raise ValueError("invalid table: %r" % value)
|
|
1041
1081
|
self._table = value
|
|
1042
1082
|
|
|
1043
1083
|
@property
|
|
@@ -1048,7 +1088,8 @@ class Delete(WithQuery):
|
|
|
1048
1088
|
def where(self, value):
|
|
1049
1089
|
from sql.operators import And, Or
|
|
1050
1090
|
if value is not None:
|
|
1051
|
-
|
|
1091
|
+
if not isinstance(value, (Expression, And, Or)):
|
|
1092
|
+
raise ValueError("invalid where: %r" % value)
|
|
1052
1093
|
self._where = value
|
|
1053
1094
|
|
|
1054
1095
|
@property
|
|
@@ -1058,19 +1099,15 @@ class Delete(WithQuery):
|
|
|
1058
1099
|
@returning.setter
|
|
1059
1100
|
def returning(self, value):
|
|
1060
1101
|
if value is not None:
|
|
1061
|
-
|
|
1102
|
+
if any(
|
|
1103
|
+
not isinstance(col, (Expression, SelectQuery))
|
|
1104
|
+
for col in value):
|
|
1105
|
+
raise ValueError("invalid returning: %r" % value)
|
|
1062
1106
|
self._returning = value
|
|
1063
1107
|
|
|
1064
1108
|
@staticmethod
|
|
1065
|
-
def _format(value
|
|
1066
|
-
|
|
1067
|
-
param = Flavor.get().param
|
|
1068
|
-
if isinstance(value, Expression):
|
|
1069
|
-
return str(value)
|
|
1070
|
-
elif isinstance(value, Select):
|
|
1071
|
-
return '(%s)' % value
|
|
1072
|
-
else:
|
|
1073
|
-
return param
|
|
1109
|
+
def _format(value):
|
|
1110
|
+
return Select._format_column(value)
|
|
1074
1111
|
|
|
1075
1112
|
def __str__(self):
|
|
1076
1113
|
with AliasManager(exclude=[self.table]):
|
|
@@ -1118,7 +1155,8 @@ class Merge(WithQuery):
|
|
|
1118
1155
|
|
|
1119
1156
|
@target.setter
|
|
1120
1157
|
def target(self, value):
|
|
1121
|
-
|
|
1158
|
+
if not isinstance(value, Table):
|
|
1159
|
+
raise ValueError("invalid target: %r" % value)
|
|
1122
1160
|
self._target = value
|
|
1123
1161
|
|
|
1124
1162
|
@property
|
|
@@ -1127,7 +1165,8 @@ class Merge(WithQuery):
|
|
|
1127
1165
|
|
|
1128
1166
|
@source.setter
|
|
1129
1167
|
def source(self, value):
|
|
1130
|
-
|
|
1168
|
+
if not isinstance(value, (Table, SelectQuery, Values)):
|
|
1169
|
+
raise ValueError("invalid source: %r" % value)
|
|
1131
1170
|
self._source = value
|
|
1132
1171
|
|
|
1133
1172
|
@property
|
|
@@ -1136,7 +1175,8 @@ class Merge(WithQuery):
|
|
|
1136
1175
|
|
|
1137
1176
|
@condition.setter
|
|
1138
1177
|
def condition(self, value):
|
|
1139
|
-
|
|
1178
|
+
if not isinstance(value, Expression):
|
|
1179
|
+
raise ValueError("invalid condition: %r" % value)
|
|
1140
1180
|
self._condition = value
|
|
1141
1181
|
|
|
1142
1182
|
@property
|
|
@@ -1145,7 +1185,8 @@ class Merge(WithQuery):
|
|
|
1145
1185
|
|
|
1146
1186
|
@whens.setter
|
|
1147
1187
|
def whens(self, value):
|
|
1148
|
-
|
|
1188
|
+
if any(not isinstance(w, Matched) for w in value):
|
|
1189
|
+
raise ValueError("invalid whens: %r" % value)
|
|
1149
1190
|
self._whens = tuple(value)
|
|
1150
1191
|
|
|
1151
1192
|
def __str__(self):
|
|
@@ -1154,10 +1195,7 @@ class Merge(WithQuery):
|
|
|
1154
1195
|
source = '(%s)' % self.source
|
|
1155
1196
|
else:
|
|
1156
1197
|
source = self.source
|
|
1157
|
-
|
|
1158
|
-
condition = 'ON %s' % self.condition
|
|
1159
|
-
else:
|
|
1160
|
-
condition = ''
|
|
1198
|
+
condition = 'ON %s' % self.condition
|
|
1161
1199
|
return (self._with_str()
|
|
1162
1200
|
+ 'MERGE INTO %s AS "%s" ' % (self.target, self.target.alias)
|
|
1163
1201
|
+ 'USING %s AS "%s" ' % (source, self.source.alias)
|
|
@@ -1191,7 +1229,8 @@ class Matched(object):
|
|
|
1191
1229
|
@condition.setter
|
|
1192
1230
|
def condition(self, value):
|
|
1193
1231
|
if value is not None:
|
|
1194
|
-
|
|
1232
|
+
if not isinstance(value, Expression):
|
|
1233
|
+
raise ValueError("invalid condition: %r" % value)
|
|
1195
1234
|
self._condition = value
|
|
1196
1235
|
|
|
1197
1236
|
def _then_str(self):
|
|
@@ -1228,7 +1267,8 @@ class _MatchedValues(Matched):
|
|
|
1228
1267
|
|
|
1229
1268
|
@columns.setter
|
|
1230
1269
|
def columns(self, value):
|
|
1231
|
-
|
|
1270
|
+
if any(not isinstance(col, Column) for col in value):
|
|
1271
|
+
raise ValueError("invalid columns: %r" % value)
|
|
1232
1272
|
self._columns = value
|
|
1233
1273
|
|
|
1234
1274
|
|
|
@@ -1281,13 +1321,15 @@ class NotMatchedInsert(_MatchedValues, NotMatched):
|
|
|
1281
1321
|
|
|
1282
1322
|
@values.setter
|
|
1283
1323
|
def values(self, value):
|
|
1284
|
-
|
|
1324
|
+
if value is not None:
|
|
1325
|
+
value = Values([value])
|
|
1326
|
+
self._values = value
|
|
1285
1327
|
|
|
1286
1328
|
def _then_str(self):
|
|
1287
1329
|
columns = ', '.join(c.column_name for c in self.columns)
|
|
1288
1330
|
columns = '(' + columns + ')'
|
|
1289
1331
|
if self.values is None:
|
|
1290
|
-
values = ' DEFAULT VALUES
|
|
1332
|
+
values = ' DEFAULT VALUES'
|
|
1291
1333
|
else:
|
|
1292
1334
|
values = ' ' + str(self.values)
|
|
1293
1335
|
return 'INSERT ' + columns + values
|
|
@@ -1295,7 +1337,8 @@ class NotMatchedInsert(_MatchedValues, NotMatched):
|
|
|
1295
1337
|
@property
|
|
1296
1338
|
def params(self):
|
|
1297
1339
|
p = list(super().params)
|
|
1298
|
-
|
|
1340
|
+
if self.values:
|
|
1341
|
+
p.extend(self.values.params)
|
|
1299
1342
|
return tuple(p)
|
|
1300
1343
|
|
|
1301
1344
|
|
|
@@ -1304,7 +1347,8 @@ class CombiningQuery(FromItem, SelectQuery):
|
|
|
1304
1347
|
_operator = ''
|
|
1305
1348
|
|
|
1306
1349
|
def __init__(self, *queries, **kwargs):
|
|
1307
|
-
|
|
1350
|
+
if any(not isinstance(q, Query) for q in queries):
|
|
1351
|
+
raise ValueError("invalid queries: %r" % (queries,))
|
|
1308
1352
|
self.queries = queries
|
|
1309
1353
|
self.all_ = kwargs.pop('all_', False)
|
|
1310
1354
|
super(CombiningQuery, self).__init__(**kwargs)
|
|
@@ -1424,7 +1468,8 @@ class Join(FromItem):
|
|
|
1424
1468
|
|
|
1425
1469
|
@left.setter
|
|
1426
1470
|
def left(self, value):
|
|
1427
|
-
|
|
1471
|
+
if not isinstance(value, FromItem):
|
|
1472
|
+
raise ValueError("invalid left: %r" % value)
|
|
1428
1473
|
self._left = value
|
|
1429
1474
|
|
|
1430
1475
|
@property
|
|
@@ -1433,7 +1478,8 @@ class Join(FromItem):
|
|
|
1433
1478
|
|
|
1434
1479
|
@right.setter
|
|
1435
1480
|
def right(self, value):
|
|
1436
|
-
|
|
1481
|
+
if not isinstance(value, FromItem):
|
|
1482
|
+
raise ValueError("invalid right: %r" % value)
|
|
1437
1483
|
self._right = value
|
|
1438
1484
|
|
|
1439
1485
|
@property
|
|
@@ -1444,7 +1490,8 @@ class Join(FromItem):
|
|
|
1444
1490
|
def condition(self, value):
|
|
1445
1491
|
from sql.operators import And, Or
|
|
1446
1492
|
if value is not None:
|
|
1447
|
-
|
|
1493
|
+
if not isinstance(value, (Expression, And, Or)):
|
|
1494
|
+
raise ValueError("invalid condition: %r" % value)
|
|
1448
1495
|
self._condition = value
|
|
1449
1496
|
|
|
1450
1497
|
@property
|
|
@@ -1454,8 +1501,10 @@ class Join(FromItem):
|
|
|
1454
1501
|
@type_.setter
|
|
1455
1502
|
def type_(self, value):
|
|
1456
1503
|
value = value.upper()
|
|
1457
|
-
|
|
1458
|
-
|
|
1504
|
+
if value not in {
|
|
1505
|
+
'INNER', 'LEFT', 'LEFT OUTER', 'RIGHT', 'RIGHT OUTER', 'FULL',
|
|
1506
|
+
'FULL OUTER', 'CROSS'}:
|
|
1507
|
+
raise ValueError("invalid type: %r" % value)
|
|
1459
1508
|
self._type_ = value
|
|
1460
1509
|
|
|
1461
1510
|
def __str__(self):
|
|
@@ -1471,14 +1520,9 @@ class Join(FromItem):
|
|
|
1471
1520
|
def params(self):
|
|
1472
1521
|
p = []
|
|
1473
1522
|
for item in (self.left, self.right):
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
except AttributeError:
|
|
1477
|
-
pass
|
|
1478
|
-
try:
|
|
1523
|
+
p.extend(item.params)
|
|
1524
|
+
if self.condition:
|
|
1479
1525
|
p.extend(self.condition.params)
|
|
1480
|
-
except AttributeError:
|
|
1481
|
-
pass
|
|
1482
1526
|
return tuple(p)
|
|
1483
1527
|
|
|
1484
1528
|
@property
|
|
@@ -1534,8 +1578,10 @@ class From(list):
|
|
|
1534
1578
|
return tuple(p)
|
|
1535
1579
|
|
|
1536
1580
|
def __add__(self, other):
|
|
1537
|
-
|
|
1538
|
-
|
|
1581
|
+
if not isinstance(other, FromItem):
|
|
1582
|
+
return NotImplemented
|
|
1583
|
+
elif isinstance(other, CombiningQuery):
|
|
1584
|
+
return NotImplemented
|
|
1539
1585
|
return From(super(From, self).__add__([other]))
|
|
1540
1586
|
|
|
1541
1587
|
|
|
@@ -1558,7 +1604,7 @@ class Values(list, Query, FromItem):
|
|
|
1558
1604
|
|
|
1559
1605
|
@property
|
|
1560
1606
|
def params(self):
|
|
1561
|
-
p =
|
|
1607
|
+
p = list(super().params)
|
|
1562
1608
|
for values in self:
|
|
1563
1609
|
for value in values:
|
|
1564
1610
|
if isinstance(value, Expression):
|
|
@@ -1823,21 +1869,35 @@ class Cast(Expression):
|
|
|
1823
1869
|
|
|
1824
1870
|
|
|
1825
1871
|
class Collate(Expression):
|
|
1826
|
-
__slots__ = ('
|
|
1872
|
+
__slots__ = ('_expression', '_collation')
|
|
1827
1873
|
|
|
1828
1874
|
def __init__(self, expression, collation):
|
|
1829
1875
|
super(Collate, self).__init__()
|
|
1830
1876
|
self.expression = expression
|
|
1831
1877
|
self.collation = collation
|
|
1832
1878
|
|
|
1879
|
+
@property
|
|
1880
|
+
def expression(self):
|
|
1881
|
+
return self._expression
|
|
1882
|
+
|
|
1883
|
+
@expression.setter
|
|
1884
|
+
def expression(self, value):
|
|
1885
|
+
self._expression = value
|
|
1886
|
+
|
|
1887
|
+
@property
|
|
1888
|
+
def collation(self):
|
|
1889
|
+
return self._collation
|
|
1890
|
+
|
|
1891
|
+
@collation.setter
|
|
1892
|
+
def collation(self, value):
|
|
1893
|
+
self._collation = value
|
|
1894
|
+
|
|
1833
1895
|
def __str__(self):
|
|
1834
1896
|
if isinstance(self.expression, Expression):
|
|
1835
1897
|
value = self.expression
|
|
1836
1898
|
else:
|
|
1837
1899
|
value = Flavor.get().param
|
|
1838
|
-
|
|
1839
|
-
raise ValueError("Wrong collation %s" % self.collation)
|
|
1840
|
-
return '%s COLLATE "%s"' % (value, self.collation)
|
|
1900
|
+
return '%s COLLATE %s' % (value, _escape_identifier(self.collation))
|
|
1841
1901
|
|
|
1842
1902
|
@property
|
|
1843
1903
|
def params(self):
|
|
@@ -1860,8 +1920,11 @@ class Grouping(Expression):
|
|
|
1860
1920
|
|
|
1861
1921
|
@sets.setter
|
|
1862
1922
|
def sets(self, value):
|
|
1863
|
-
|
|
1864
|
-
|
|
1923
|
+
if any(
|
|
1924
|
+
not isinstance(col, Expression)
|
|
1925
|
+
for cols in value
|
|
1926
|
+
for col in cols):
|
|
1927
|
+
raise ValueError("invalid sets: %r" % value)
|
|
1865
1928
|
self._sets = tuple(tuple(cols) for cols in value)
|
|
1866
1929
|
|
|
1867
1930
|
def __str__(self):
|
|
@@ -1888,10 +1951,11 @@ class Rollup(Expression):
|
|
|
1888
1951
|
|
|
1889
1952
|
@expressions.setter
|
|
1890
1953
|
def expressions(self, value):
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1954
|
+
if not all(
|
|
1955
|
+
isinstance(col, Expression)
|
|
1956
|
+
or all(isinstance(c, Expression) for c in col)
|
|
1957
|
+
for col in value):
|
|
1958
|
+
raise ValueError("invalid expressions: %r" % value)
|
|
1895
1959
|
self._expressions = tuple(value)
|
|
1896
1960
|
|
|
1897
1961
|
def __str__(self):
|
|
@@ -1945,7 +2009,8 @@ class Window(object):
|
|
|
1945
2009
|
|
|
1946
2010
|
@partition.setter
|
|
1947
2011
|
def partition(self, value):
|
|
1948
|
-
|
|
2012
|
+
if any(not isinstance(e, Expression) for e in value):
|
|
2013
|
+
raise ValueError("invalid partition: %r" % value)
|
|
1949
2014
|
self._partition = value
|
|
1950
2015
|
|
|
1951
2016
|
@property
|
|
@@ -1957,7 +2022,8 @@ class Window(object):
|
|
|
1957
2022
|
if value is not None:
|
|
1958
2023
|
if isinstance(value, Expression):
|
|
1959
2024
|
value = [value]
|
|
1960
|
-
|
|
2025
|
+
if any(not isinstance(col, Expression) for col in value):
|
|
2026
|
+
raise ValueError("invalid order by: %r" % value)
|
|
1961
2027
|
self._order_by = value
|
|
1962
2028
|
|
|
1963
2029
|
@property
|
|
@@ -1967,7 +2033,8 @@ class Window(object):
|
|
|
1967
2033
|
@frame.setter
|
|
1968
2034
|
def frame(self, value):
|
|
1969
2035
|
if value:
|
|
1970
|
-
|
|
2036
|
+
if value not in {'RANGE', 'ROWS', 'GROUPS'}:
|
|
2037
|
+
raise ValueError("invalid frame: %r" % value)
|
|
1971
2038
|
self._frame = value
|
|
1972
2039
|
|
|
1973
2040
|
@property
|
|
@@ -1977,7 +2044,8 @@ class Window(object):
|
|
|
1977
2044
|
@start.setter
|
|
1978
2045
|
def start(self, value):
|
|
1979
2046
|
if value:
|
|
1980
|
-
|
|
2047
|
+
if not isinstance(value, numbers.Integral):
|
|
2048
|
+
raise ValueError("invalid start: %r" % value)
|
|
1981
2049
|
self._start = value
|
|
1982
2050
|
|
|
1983
2051
|
@property
|
|
@@ -1987,7 +2055,8 @@ class Window(object):
|
|
|
1987
2055
|
@end.setter
|
|
1988
2056
|
def end(self, value):
|
|
1989
2057
|
if value:
|
|
1990
|
-
|
|
2058
|
+
if not isinstance(value, numbers.Integral):
|
|
2059
|
+
raise ValueError("invalid end: %r" % value)
|
|
1991
2060
|
self._end = value
|
|
1992
2061
|
|
|
1993
2062
|
@property
|
|
@@ -1997,7 +2066,8 @@ class Window(object):
|
|
|
1997
2066
|
@exclude.setter
|
|
1998
2067
|
def exclude(self, value):
|
|
1999
2068
|
if value:
|
|
2000
|
-
|
|
2069
|
+
if value not in {'CURRENT ROW', 'GROUP', 'TIES'}:
|
|
2070
|
+
raise ValueError("invalid exclude: %r" % value)
|
|
2001
2071
|
self._exclude = value
|
|
2002
2072
|
|
|
2003
2073
|
@property
|
|
@@ -2070,7 +2140,8 @@ class Order(Expression):
|
|
|
2070
2140
|
|
|
2071
2141
|
@expression.setter
|
|
2072
2142
|
def expression(self, value):
|
|
2073
|
-
|
|
2143
|
+
if not isinstance(value, (Expression, SelectQuery)):
|
|
2144
|
+
raise ValueError("invalid expression: %r" % value)
|
|
2074
2145
|
self._expression = value
|
|
2075
2146
|
|
|
2076
2147
|
def __str__(self):
|
|
@@ -2173,7 +2244,8 @@ class For(object):
|
|
|
2173
2244
|
@type_.setter
|
|
2174
2245
|
def type_(self, value):
|
|
2175
2246
|
value = value.upper()
|
|
2176
|
-
|
|
2247
|
+
if value not in {'UPDATE', 'SHARE'}:
|
|
2248
|
+
raise ValueError("invalid type: %r" % value)
|
|
2177
2249
|
self._type_ = value
|
|
2178
2250
|
|
|
2179
2251
|
def __str__(self):
|