python-sql 1.5.0__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.
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.0'
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
- assert limitstyle in ['fetch', 'limit', 'rownum']
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
- assert all(isinstance(w, With) for w in value)
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
- assert isinstance(other, FromItem)
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
- assert all(isinstance(col, Expression) for col in value)
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
- assert isinstance(value, numbers.Integral)
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,18 +385,20 @@ class SelectQuery(WithQuery):
375
385
  @offset.setter
376
386
  def offset(self, value):
377
387
  if value is not None:
378
- assert isinstance(value, numbers.Integral)
388
+ if not isinstance(value, numbers.Integral):
389
+ raise ValueError("invalid offset: %r" % value)
379
390
  self._offset = value
380
391
 
381
392
  @property
382
393
  def _limit_offset_str(self):
394
+ param = Flavor.get().param
383
395
  if Flavor.get().limitstyle == 'limit':
384
396
  offset = ''
385
397
  if self.offset:
386
- offset = ' OFFSET %s' % self.offset
398
+ offset = ' OFFSET %s' % param
387
399
  limit = ''
388
400
  if self.limit is not None:
389
- limit = ' LIMIT %s' % self.limit
401
+ limit = ' LIMIT %s' % param
390
402
  elif self.offset:
391
403
  max_limit = Flavor.get().max_limit
392
404
  if max_limit:
@@ -395,12 +407,27 @@ class SelectQuery(WithQuery):
395
407
  else:
396
408
  offset = ''
397
409
  if self.offset:
398
- offset = ' OFFSET (%s) ROWS' % self.offset
410
+ offset = ' OFFSET (%s) ROWS' % param
399
411
  fetch = ''
400
412
  if self.limit is not None:
401
- fetch = ' FETCH FIRST (%s) ROWS ONLY' % self.limit
413
+ fetch = ' FETCH FIRST (%s) ROWS ONLY' % param
402
414
  return offset + fetch
403
415
 
416
+ @property
417
+ def _limit_offset_params(self):
418
+ p = []
419
+ if Flavor.get().limitstyle == 'limit':
420
+ if self.limit is not None:
421
+ p.append(self.limit)
422
+ if self.offset:
423
+ p.append(self.offset)
424
+ else:
425
+ if self.offset:
426
+ p.append(self.offset)
427
+ if self.limit is not None:
428
+ p.append(self.limit)
429
+ return tuple(p)
430
+
404
431
  def as_(self, output_name):
405
432
  return As(self, output_name)
406
433
 
@@ -448,7 +475,8 @@ class Select(FromItem, SelectQuery):
448
475
  if value is not None:
449
476
  if isinstance(value, Expression):
450
477
  value = [value]
451
- assert all(isinstance(col, Expression) for col in value)
478
+ if any(not isinstance(col, Expression) for col in value):
479
+ raise ValueError("invalid distinct on: %r" % value)
452
480
  self._distinct_on = value
453
481
 
454
482
  @property
@@ -457,7 +485,10 @@ class Select(FromItem, SelectQuery):
457
485
 
458
486
  @columns.setter
459
487
  def columns(self, value):
460
- assert all(isinstance(col, (Expression, SelectQuery)) for col in value)
488
+ if any(
489
+ not isinstance(col, (Expression, SelectQuery))
490
+ for col in value):
491
+ raise ValueError("invalid columns: %r" % value)
461
492
  self._columns = tuple(value)
462
493
 
463
494
  @property
@@ -468,7 +499,8 @@ class Select(FromItem, SelectQuery):
468
499
  def where(self, value):
469
500
  from sql.operators import And, Or
470
501
  if value is not None:
471
- assert isinstance(value, (Expression, And, Or))
502
+ if not isinstance(value, (Expression, And, Or)):
503
+ raise ValueError("invalid where: %r" % value)
472
504
  self._where = value
473
505
 
474
506
  @property
@@ -480,7 +512,8 @@ class Select(FromItem, SelectQuery):
480
512
  if value is not None:
481
513
  if isinstance(value, Expression):
482
514
  value = [value]
483
- assert all(isinstance(col, Expression) for col in value)
515
+ if any(not isinstance(col, Expression) for col in value):
516
+ raise ValueError("invalid group by: %r" % value)
484
517
  self._group_by = value
485
518
 
486
519
  @property
@@ -491,7 +524,8 @@ class Select(FromItem, SelectQuery):
491
524
  def having(self, value):
492
525
  from sql.operators import And, Or
493
526
  if value is not None:
494
- assert isinstance(value, (Expression, And, Or))
527
+ if not isinstance(value, (Expression, And, Or)):
528
+ raise ValueError("invalid having: %r" % value)
495
529
  self._having = value
496
530
 
497
531
  @property
@@ -503,7 +537,8 @@ class Select(FromItem, SelectQuery):
503
537
  if value is not None:
504
538
  if isinstance(value, For):
505
539
  value = [value]
506
- assert all(isinstance(f, For) for f in value)
540
+ if any(not isinstance(f, For) for f in value):
541
+ raise ValueError("invalid for: %r" % value)
507
542
  self._for_ = value
508
543
 
509
544
  @property
@@ -531,7 +566,8 @@ class Select(FromItem, SelectQuery):
531
566
  @windows.setter
532
567
  def windows(self, value):
533
568
  if value is not None:
534
- assert all(isinstance(w, Window) for w in value)
569
+ if any(not isinstance(w, Window) for w in value):
570
+ raise ValueError("invalid windows: %r" % value)
535
571
  self._windows = value
536
572
 
537
573
  @staticmethod
@@ -663,6 +699,7 @@ class Select(FromItem, SelectQuery):
663
699
  p.extend(self.having.params)
664
700
  for window in self.windows:
665
701
  p.extend(window.params)
702
+ p.extend(self._limit_offset_params)
666
703
  return tuple(p)
667
704
 
668
705
 
@@ -690,7 +727,8 @@ class Insert(WithQuery):
690
727
 
691
728
  @table.setter
692
729
  def table(self, value):
693
- assert isinstance(value, Table)
730
+ if not isinstance(value, Table):
731
+ raise ValueError("invalid table: %r" % value)
694
732
  self._table = value
695
733
 
696
734
  @property
@@ -700,8 +738,10 @@ class Insert(WithQuery):
700
738
  @columns.setter
701
739
  def columns(self, value):
702
740
  if value is not None:
703
- assert all(isinstance(col, Column) for col in value)
704
- assert all(col.table == self.table for col in value)
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)
705
745
  self._columns = value
706
746
 
707
747
  @property
@@ -711,7 +751,8 @@ class Insert(WithQuery):
711
751
  @values.setter
712
752
  def values(self, value):
713
753
  if value is not None:
714
- assert isinstance(value, (list, Select))
754
+ if not isinstance(value, (list, Select)):
755
+ raise ValueError("invalid values: %r" % value)
715
756
  if isinstance(value, list):
716
757
  value = Values(value)
717
758
  self._values = value
@@ -723,8 +764,8 @@ class Insert(WithQuery):
723
764
  @on_conflict.setter
724
765
  def on_conflict(self, value):
725
766
  if value is not None:
726
- assert isinstance(value, Conflict)
727
- assert value.table == self.table
767
+ if not isinstance(value, Conflict) or value.table != self.table:
768
+ raise ValueError("invalid on conflict: %r" % value)
728
769
  self._on_conflict = value
729
770
 
730
771
  @property
@@ -734,7 +775,8 @@ class Insert(WithQuery):
734
775
  @returning.setter
735
776
  def returning(self, value):
736
777
  if value is not None:
737
- assert isinstance(value, list)
778
+ if not isinstance(value, list):
779
+ raise ValueError("invalid returning: %r" % value)
738
780
  self._returning = value
739
781
 
740
782
  @staticmethod
@@ -817,7 +859,8 @@ class Conflict(object):
817
859
 
818
860
  @table.setter
819
861
  def table(self, value):
820
- assert isinstance(value, Table)
862
+ if not isinstance(value, Table):
863
+ raise ValueError("invalid table: %r" % value)
821
864
  self._table = value
822
865
 
823
866
  @property
@@ -827,8 +870,10 @@ class Conflict(object):
827
870
  @indexed_columns.setter
828
871
  def indexed_columns(self, value):
829
872
  if value is not None:
830
- assert all(isinstance(col, Column) for col in value)
831
- assert all(col.table == self.table for col in value)
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)
832
877
  self._indexed_columns = value
833
878
 
834
879
  @property
@@ -839,7 +884,8 @@ class Conflict(object):
839
884
  def index_where(self, value):
840
885
  from sql.operators import And, Or
841
886
  if value is not None:
842
- assert isinstance(value, (Expression, And, Or))
887
+ if not isinstance(value, (Expression, And, Or)):
888
+ raise ValueError("invalid index where: %r" % value)
843
889
  self._index_where = value
844
890
 
845
891
  @property
@@ -849,8 +895,10 @@ class Conflict(object):
849
895
  @columns.setter
850
896
  def columns(self, value):
851
897
  if value is not None:
852
- assert all(isinstance(col, Column) for col in value)
853
- assert all(col.table == self.table for col in value)
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)
854
902
  self._columns = value
855
903
 
856
904
  @property
@@ -860,7 +908,8 @@ class Conflict(object):
860
908
  @values.setter
861
909
  def values(self, value):
862
910
  if value is not None:
863
- assert isinstance(value, (list, Select))
911
+ if not isinstance(value, (list, Select)):
912
+ raise ValueError("invalid values: %r" % value)
864
913
  if isinstance(value, list):
865
914
  value = Values([value])
866
915
  self._values = value
@@ -873,7 +922,8 @@ class Conflict(object):
873
922
  def where(self, value):
874
923
  from sql.operators import And, Or
875
924
  if value is not None:
876
- assert isinstance(value, (Expression, And, Or))
925
+ if not isinstance(value, (Expression, And, Or)):
926
+ raise ValueError("invalid where: %r" % value)
877
927
  self._where = value
878
928
 
879
929
  def __str__(self):
@@ -944,7 +994,8 @@ class Update(Insert):
944
994
  def values(self, value):
945
995
  if isinstance(value, Select):
946
996
  value = [value]
947
- assert isinstance(value, list)
997
+ if not isinstance(value, list):
998
+ raise ValueError("invalid values: %r" % value)
948
999
  self._values = value
949
1000
 
950
1001
  @property
@@ -955,9 +1006,14 @@ class Update(Insert):
955
1006
  def where(self, value):
956
1007
  from sql.operators import And, Or
957
1008
  if value is not None:
958
- assert isinstance(value, (Expression, And, Or))
1009
+ if not isinstance(value, (Expression, And, Or)):
1010
+ raise ValueError("invalid where: %r" % value)
959
1011
  self._where = value
960
1012
 
1013
+ @staticmethod
1014
+ def _format_column(value):
1015
+ return Select._format_column(value)
1016
+
961
1017
  def __str__(self):
962
1018
  assert all(col.table == self.table for col in self.columns)
963
1019
  # Get columns without alias
@@ -975,7 +1031,7 @@ class Update(Insert):
975
1031
  returning = ''
976
1032
  if self.returning:
977
1033
  returning = ' RETURNING ' + ', '.join(
978
- map(self._format, self.returning))
1034
+ map(self._format_column, self.returning))
979
1035
  return (self._with_str()
980
1036
  + 'UPDATE %s AS "%s" SET ' % (self.table, self.table.alias)
981
1037
  + values + from_ + where + returning)
@@ -1020,7 +1076,8 @@ class Delete(WithQuery):
1020
1076
 
1021
1077
  @table.setter
1022
1078
  def table(self, value):
1023
- assert isinstance(value, Table)
1079
+ if not isinstance(value, Table):
1080
+ raise ValueError("invalid table: %r" % value)
1024
1081
  self._table = value
1025
1082
 
1026
1083
  @property
@@ -1031,7 +1088,8 @@ class Delete(WithQuery):
1031
1088
  def where(self, value):
1032
1089
  from sql.operators import And, Or
1033
1090
  if value is not None:
1034
- assert isinstance(value, (Expression, And, Or))
1091
+ if not isinstance(value, (Expression, And, Or)):
1092
+ raise ValueError("invalid where: %r" % value)
1035
1093
  self._where = value
1036
1094
 
1037
1095
  @property
@@ -1041,19 +1099,15 @@ class Delete(WithQuery):
1041
1099
  @returning.setter
1042
1100
  def returning(self, value):
1043
1101
  if value is not None:
1044
- assert isinstance(value, list)
1102
+ if any(
1103
+ not isinstance(col, (Expression, SelectQuery))
1104
+ for col in value):
1105
+ raise ValueError("invalid returning: %r" % value)
1045
1106
  self._returning = value
1046
1107
 
1047
1108
  @staticmethod
1048
- def _format(value, param=None):
1049
- if param is None:
1050
- param = Flavor.get().param
1051
- if isinstance(value, Expression):
1052
- return str(value)
1053
- elif isinstance(value, Select):
1054
- return '(%s)' % value
1055
- else:
1056
- return param
1109
+ def _format(value):
1110
+ return Select._format_column(value)
1057
1111
 
1058
1112
  def __str__(self):
1059
1113
  with AliasManager(exclude=[self.table]):
@@ -1101,7 +1155,8 @@ class Merge(WithQuery):
1101
1155
 
1102
1156
  @target.setter
1103
1157
  def target(self, value):
1104
- assert isinstance(value, Table)
1158
+ if not isinstance(value, Table):
1159
+ raise ValueError("invalid target: %r" % value)
1105
1160
  self._target = value
1106
1161
 
1107
1162
  @property
@@ -1110,7 +1165,8 @@ class Merge(WithQuery):
1110
1165
 
1111
1166
  @source.setter
1112
1167
  def source(self, value):
1113
- assert isinstance(value, (Table, SelectQuery, Values))
1168
+ if not isinstance(value, (Table, SelectQuery, Values)):
1169
+ raise ValueError("invalid source: %r" % value)
1114
1170
  self._source = value
1115
1171
 
1116
1172
  @property
@@ -1119,7 +1175,8 @@ class Merge(WithQuery):
1119
1175
 
1120
1176
  @condition.setter
1121
1177
  def condition(self, value):
1122
- assert isinstance(value, Expression)
1178
+ if not isinstance(value, Expression):
1179
+ raise ValueError("invalid condition: %r" % value)
1123
1180
  self._condition = value
1124
1181
 
1125
1182
  @property
@@ -1128,7 +1185,8 @@ class Merge(WithQuery):
1128
1185
 
1129
1186
  @whens.setter
1130
1187
  def whens(self, value):
1131
- assert all(isinstance(w, Matched) for w in value)
1188
+ if any(not isinstance(w, Matched) for w in value):
1189
+ raise ValueError("invalid whens: %r" % value)
1132
1190
  self._whens = tuple(value)
1133
1191
 
1134
1192
  def __str__(self):
@@ -1137,10 +1195,7 @@ class Merge(WithQuery):
1137
1195
  source = '(%s)' % self.source
1138
1196
  else:
1139
1197
  source = self.source
1140
- if self.condition:
1141
- condition = 'ON %s' % self.condition
1142
- else:
1143
- condition = ''
1198
+ condition = 'ON %s' % self.condition
1144
1199
  return (self._with_str()
1145
1200
  + 'MERGE INTO %s AS "%s" ' % (self.target, self.target.alias)
1146
1201
  + 'USING %s AS "%s" ' % (source, self.source.alias)
@@ -1174,7 +1229,8 @@ class Matched(object):
1174
1229
  @condition.setter
1175
1230
  def condition(self, value):
1176
1231
  if value is not None:
1177
- assert isinstance(value, Expression)
1232
+ if not isinstance(value, Expression):
1233
+ raise ValueError("invalid condition: %r" % value)
1178
1234
  self._condition = value
1179
1235
 
1180
1236
  def _then_str(self):
@@ -1211,7 +1267,8 @@ class _MatchedValues(Matched):
1211
1267
 
1212
1268
  @columns.setter
1213
1269
  def columns(self, value):
1214
- assert all(isinstance(col, Column) for col in value)
1270
+ if any(not isinstance(col, Column) for col in value):
1271
+ raise ValueError("invalid columns: %r" % value)
1215
1272
  self._columns = value
1216
1273
 
1217
1274
 
@@ -1264,13 +1321,15 @@ class NotMatchedInsert(_MatchedValues, NotMatched):
1264
1321
 
1265
1322
  @values.setter
1266
1323
  def values(self, value):
1267
- self._values = Values([value])
1324
+ if value is not None:
1325
+ value = Values([value])
1326
+ self._values = value
1268
1327
 
1269
1328
  def _then_str(self):
1270
1329
  columns = ', '.join(c.column_name for c in self.columns)
1271
1330
  columns = '(' + columns + ')'
1272
1331
  if self.values is None:
1273
- values = ' DEFAULT VALUES '
1332
+ values = ' DEFAULT VALUES'
1274
1333
  else:
1275
1334
  values = ' ' + str(self.values)
1276
1335
  return 'INSERT ' + columns + values
@@ -1278,7 +1337,8 @@ class NotMatchedInsert(_MatchedValues, NotMatched):
1278
1337
  @property
1279
1338
  def params(self):
1280
1339
  p = list(super().params)
1281
- p.extend(self.values.params)
1340
+ if self.values:
1341
+ p.extend(self.values.params)
1282
1342
  return tuple(p)
1283
1343
 
1284
1344
 
@@ -1287,7 +1347,8 @@ class CombiningQuery(FromItem, SelectQuery):
1287
1347
  _operator = ''
1288
1348
 
1289
1349
  def __init__(self, *queries, **kwargs):
1290
- assert all(isinstance(q, Query) for q in queries)
1350
+ if any(not isinstance(q, Query) for q in queries):
1351
+ raise ValueError("invalid queries: %r" % (queries,))
1291
1352
  self.queries = queries
1292
1353
  self.all_ = kwargs.pop('all_', False)
1293
1354
  super(CombiningQuery, self).__init__(**kwargs)
@@ -1407,7 +1468,8 @@ class Join(FromItem):
1407
1468
 
1408
1469
  @left.setter
1409
1470
  def left(self, value):
1410
- assert isinstance(value, FromItem)
1471
+ if not isinstance(value, FromItem):
1472
+ raise ValueError("invalid left: %r" % value)
1411
1473
  self._left = value
1412
1474
 
1413
1475
  @property
@@ -1416,7 +1478,8 @@ class Join(FromItem):
1416
1478
 
1417
1479
  @right.setter
1418
1480
  def right(self, value):
1419
- assert isinstance(value, FromItem)
1481
+ if not isinstance(value, FromItem):
1482
+ raise ValueError("invalid right: %r" % value)
1420
1483
  self._right = value
1421
1484
 
1422
1485
  @property
@@ -1427,7 +1490,8 @@ class Join(FromItem):
1427
1490
  def condition(self, value):
1428
1491
  from sql.operators import And, Or
1429
1492
  if value is not None:
1430
- assert isinstance(value, (Expression, And, Or))
1493
+ if not isinstance(value, (Expression, And, Or)):
1494
+ raise ValueError("invalid condition: %r" % value)
1431
1495
  self._condition = value
1432
1496
 
1433
1497
  @property
@@ -1437,8 +1501,10 @@ class Join(FromItem):
1437
1501
  @type_.setter
1438
1502
  def type_(self, value):
1439
1503
  value = value.upper()
1440
- assert value in ('INNER', 'LEFT', 'LEFT OUTER',
1441
- 'RIGHT', 'RIGHT OUTER', 'FULL', 'FULL OUTER', 'CROSS')
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)
1442
1508
  self._type_ = value
1443
1509
 
1444
1510
  def __str__(self):
@@ -1454,14 +1520,9 @@ class Join(FromItem):
1454
1520
  def params(self):
1455
1521
  p = []
1456
1522
  for item in (self.left, self.right):
1457
- try:
1458
- p.extend(item.params)
1459
- except AttributeError:
1460
- pass
1461
- try:
1523
+ p.extend(item.params)
1524
+ if self.condition:
1462
1525
  p.extend(self.condition.params)
1463
- except AttributeError:
1464
- pass
1465
1526
  return tuple(p)
1466
1527
 
1467
1528
  @property
@@ -1517,8 +1578,10 @@ class From(list):
1517
1578
  return tuple(p)
1518
1579
 
1519
1580
  def __add__(self, other):
1520
- assert isinstance(other, FromItem)
1521
- assert not isinstance(other, CombiningQuery)
1581
+ if not isinstance(other, FromItem):
1582
+ return NotImplemented
1583
+ elif isinstance(other, CombiningQuery):
1584
+ return NotImplemented
1522
1585
  return From(super(From, self).__add__([other]))
1523
1586
 
1524
1587
 
@@ -1541,7 +1604,7 @@ class Values(list, Query, FromItem):
1541
1604
 
1542
1605
  @property
1543
1606
  def params(self):
1544
- p = []
1607
+ p = list(super().params)
1545
1608
  for values in self:
1546
1609
  for value in values:
1547
1610
  if isinstance(value, Expression):
@@ -1806,21 +1869,35 @@ class Cast(Expression):
1806
1869
 
1807
1870
 
1808
1871
  class Collate(Expression):
1809
- __slots__ = ('expression', 'collation')
1872
+ __slots__ = ('_expression', '_collation')
1810
1873
 
1811
1874
  def __init__(self, expression, collation):
1812
1875
  super(Collate, self).__init__()
1813
1876
  self.expression = expression
1814
1877
  self.collation = collation
1815
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
+
1816
1895
  def __str__(self):
1817
1896
  if isinstance(self.expression, Expression):
1818
1897
  value = self.expression
1819
1898
  else:
1820
1899
  value = Flavor.get().param
1821
- if '"' in self.collation:
1822
- raise ValueError("Wrong collation %s" % self.collation)
1823
- return '%s COLLATE "%s"' % (value, self.collation)
1900
+ return '%s COLLATE %s' % (value, _escape_identifier(self.collation))
1824
1901
 
1825
1902
  @property
1826
1903
  def params(self):
@@ -1843,8 +1920,11 @@ class Grouping(Expression):
1843
1920
 
1844
1921
  @sets.setter
1845
1922
  def sets(self, value):
1846
- assert all(
1847
- isinstance(col, Expression) for cols in value for col in cols)
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)
1848
1928
  self._sets = tuple(tuple(cols) for cols in value)
1849
1929
 
1850
1930
  def __str__(self):
@@ -1871,10 +1951,11 @@ class Rollup(Expression):
1871
1951
 
1872
1952
  @expressions.setter
1873
1953
  def expressions(self, value):
1874
- assert all(
1875
- isinstance(col, Expression)
1876
- or all(isinstance(c, Expression) for c in col)
1877
- for col in value)
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)
1878
1959
  self._expressions = tuple(value)
1879
1960
 
1880
1961
  def __str__(self):
@@ -1928,7 +2009,8 @@ class Window(object):
1928
2009
 
1929
2010
  @partition.setter
1930
2011
  def partition(self, value):
1931
- assert all(isinstance(e, Expression) for e in value)
2012
+ if any(not isinstance(e, Expression) for e in value):
2013
+ raise ValueError("invalid partition: %r" % value)
1932
2014
  self._partition = value
1933
2015
 
1934
2016
  @property
@@ -1940,7 +2022,8 @@ class Window(object):
1940
2022
  if value is not None:
1941
2023
  if isinstance(value, Expression):
1942
2024
  value = [value]
1943
- assert all(isinstance(col, Expression) for col in value)
2025
+ if any(not isinstance(col, Expression) for col in value):
2026
+ raise ValueError("invalid order by: %r" % value)
1944
2027
  self._order_by = value
1945
2028
 
1946
2029
  @property
@@ -1950,7 +2033,8 @@ class Window(object):
1950
2033
  @frame.setter
1951
2034
  def frame(self, value):
1952
2035
  if value:
1953
- assert value in ['RANGE', 'ROWS', 'GROUPS']
2036
+ if value not in {'RANGE', 'ROWS', 'GROUPS'}:
2037
+ raise ValueError("invalid frame: %r" % value)
1954
2038
  self._frame = value
1955
2039
 
1956
2040
  @property
@@ -1960,7 +2044,8 @@ class Window(object):
1960
2044
  @start.setter
1961
2045
  def start(self, value):
1962
2046
  if value:
1963
- assert isinstance(value, numbers.Integral)
2047
+ if not isinstance(value, numbers.Integral):
2048
+ raise ValueError("invalid start: %r" % value)
1964
2049
  self._start = value
1965
2050
 
1966
2051
  @property
@@ -1970,7 +2055,8 @@ class Window(object):
1970
2055
  @end.setter
1971
2056
  def end(self, value):
1972
2057
  if value:
1973
- assert isinstance(value, numbers.Integral)
2058
+ if not isinstance(value, numbers.Integral):
2059
+ raise ValueError("invalid end: %r" % value)
1974
2060
  self._end = value
1975
2061
 
1976
2062
  @property
@@ -1980,7 +2066,8 @@ class Window(object):
1980
2066
  @exclude.setter
1981
2067
  def exclude(self, value):
1982
2068
  if value:
1983
- assert value in ['CURRENT ROW', 'GROUP', 'TIES']
2069
+ if value not in {'CURRENT ROW', 'GROUP', 'TIES'}:
2070
+ raise ValueError("invalid exclude: %r" % value)
1984
2071
  self._exclude = value
1985
2072
 
1986
2073
  @property
@@ -1992,6 +2079,7 @@ class Window(object):
1992
2079
  return AliasManager.contains(self)
1993
2080
 
1994
2081
  def __str__(self):
2082
+ param = Flavor.get().param
1995
2083
  partition = ''
1996
2084
  if self.partition:
1997
2085
  partition = 'PARTITION BY ' + ', '.join(map(str, self.partition))
@@ -2005,9 +2093,9 @@ class Window(object):
2005
2093
  elif not frame:
2006
2094
  return 'CURRENT ROW'
2007
2095
  elif frame < 0:
2008
- return '%s PRECEDING' % -frame
2096
+ return '%s PRECEDING' % param
2009
2097
  elif frame > 0:
2010
- return '%s FOLLOWING' % frame
2098
+ return '%s FOLLOWING' % param
2011
2099
 
2012
2100
  frame = ''
2013
2101
  if self.frame:
@@ -2028,6 +2116,11 @@ class Window(object):
2028
2116
  if self.order_by:
2029
2117
  for expression in self.order_by:
2030
2118
  p.extend(expression.params)
2119
+ if self.frame:
2120
+ if self.start:
2121
+ p.append(abs(self.start))
2122
+ if self.end:
2123
+ p.append(abs(self.end))
2031
2124
  return tuple(p)
2032
2125
 
2033
2126
 
@@ -2047,7 +2140,8 @@ class Order(Expression):
2047
2140
 
2048
2141
  @expression.setter
2049
2142
  def expression(self, value):
2050
- assert isinstance(value, (Expression, SelectQuery))
2143
+ if not isinstance(value, (Expression, SelectQuery)):
2144
+ raise ValueError("invalid expression: %r" % value)
2051
2145
  self._expression = value
2052
2146
 
2053
2147
  def __str__(self):
@@ -2150,7 +2244,8 @@ class For(object):
2150
2244
  @type_.setter
2151
2245
  def type_(self, value):
2152
2246
  value = value.upper()
2153
- assert value in ('UPDATE', 'SHARE')
2247
+ if value not in {'UPDATE', 'SHARE'}:
2248
+ raise ValueError("invalid type: %r" % value)
2154
2249
  self._type_ = value
2155
2250
 
2156
2251
  def __str__(self):