velocity-python 0.0.33__py3-none-any.whl → 0.0.35__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.
Potentially problematic release.
This version of velocity-python might be problematic. Click here for more details.
- velocity/__init__.py +1 -1
- velocity/db/core/decorators.py +2 -0
- velocity/db/core/engine.py +3 -0
- velocity/db/core/transaction.py +13 -0
- velocity/db/servers/mysql.py +1 -237
- velocity/db/servers/mysql_reserved.py +237 -0
- velocity/db/servers/postgres.py +83 -357
- velocity/db/servers/postgres_reserved.py +254 -0
- velocity/db/servers/sqlite.py +1 -210
- velocity/db/servers/sqlite_reserved.py +208 -0
- velocity/db/servers/sqlserver.py +1 -316
- velocity/db/servers/sqlserver_reserved.py +314 -0
- {velocity_python-0.0.33.dist-info → velocity_python-0.0.35.dist-info}/METADATA +1 -1
- {velocity_python-0.0.33.dist-info → velocity_python-0.0.35.dist-info}/RECORD +17 -13
- {velocity_python-0.0.33.dist-info → velocity_python-0.0.35.dist-info}/LICENSE +0 -0
- {velocity_python-0.0.33.dist-info → velocity_python-0.0.35.dist-info}/WHEEL +0 -0
- {velocity_python-0.0.33.dist-info → velocity_python-0.0.35.dist-info}/top_level.txt +0 -0
velocity/db/servers/postgres.py
CHANGED
|
@@ -7,6 +7,7 @@ import datetime
|
|
|
7
7
|
from ..core import exceptions
|
|
8
8
|
from ..core import engine
|
|
9
9
|
from ..core.table import Query
|
|
10
|
+
from .postgres_reserved import reserved_words
|
|
10
11
|
|
|
11
12
|
system_fields = [
|
|
12
13
|
"sys_id",
|
|
@@ -26,14 +27,12 @@ default_config = {
|
|
|
26
27
|
"password": os.environ["DBPassword"],
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
|
|
30
30
|
def initialize(config=None, **kwargs):
|
|
31
31
|
if not config:
|
|
32
32
|
config = default_config.copy()
|
|
33
33
|
config.update(kwargs)
|
|
34
34
|
return engine.Engine(psycopg2, config, SQL)
|
|
35
35
|
|
|
36
|
-
|
|
37
36
|
def make_where(where, sql, vals, is_join=False):
|
|
38
37
|
if not where:
|
|
39
38
|
return
|
|
@@ -54,23 +53,23 @@ def make_where(where, sql, vals, is_join=False):
|
|
|
54
53
|
sql.append(connect)
|
|
55
54
|
if is_join:
|
|
56
55
|
if "." not in key:
|
|
57
|
-
key = alias
|
|
58
|
-
if val
|
|
56
|
+
key = f"{alias}.{quote(key.lower())}"
|
|
57
|
+
if val is None:
|
|
59
58
|
if "!" in key:
|
|
60
59
|
key = key.replace("!", "")
|
|
61
|
-
sql.append("{} is not NULL"
|
|
60
|
+
sql.append(f"{key} is not NULL")
|
|
62
61
|
else:
|
|
63
|
-
sql.append("{} is NULL"
|
|
62
|
+
sql.append(f"{key} is NULL")
|
|
64
63
|
elif isinstance(val, (list, tuple)) and "><" not in key:
|
|
65
64
|
if "!" in key:
|
|
66
65
|
key = key.replace("!", "")
|
|
67
|
-
sql.append("{} not in %s"
|
|
66
|
+
sql.append(f"{key} not in %s")
|
|
68
67
|
vals.append(tuple(val))
|
|
69
68
|
else:
|
|
70
|
-
sql.append("{} in %s"
|
|
69
|
+
sql.append(f"{key} in %s")
|
|
71
70
|
vals.append(tuple(val))
|
|
72
71
|
elif isinstance(val, Query):
|
|
73
|
-
sql.append("{} in ({})"
|
|
72
|
+
sql.append(f"{key} in ({val})")
|
|
74
73
|
else:
|
|
75
74
|
case = None
|
|
76
75
|
if "<>" in key:
|
|
@@ -116,23 +115,15 @@ def make_where(where, sql, vals, is_join=False):
|
|
|
116
115
|
key = key.replace("%", "")
|
|
117
116
|
op = "ilike"
|
|
118
117
|
elif "!~*" in key:
|
|
119
|
-
# String does not match regular expression, case insensitively
|
|
120
|
-
# 'thomas' !~* 'T.*ma' → False
|
|
121
118
|
key = key.replace("!~*", "")
|
|
122
119
|
op = "!~*"
|
|
123
120
|
elif "~*" in key:
|
|
124
|
-
# String matches regular expression, case insensitively
|
|
125
|
-
# 'thomas' ~* 'T.*ma' → True
|
|
126
121
|
key = key.replace("~*", "")
|
|
127
122
|
op = "~*"
|
|
128
123
|
elif "!~" in key:
|
|
129
|
-
# String does not match regular expression, case sensitively
|
|
130
|
-
# 'thomas' !~ 't.*max' → True
|
|
131
124
|
key = key.replace("!~", "")
|
|
132
125
|
op = "!~"
|
|
133
126
|
elif "~" in key:
|
|
134
|
-
# String matches regular expression, case sensitively
|
|
135
|
-
# 'thomas' ~ 't.*ma' → True
|
|
136
127
|
key = key.replace("~", "")
|
|
137
128
|
op = "~"
|
|
138
129
|
elif "!" in key:
|
|
@@ -148,19 +139,18 @@ def make_where(where, sql, vals, is_join=False):
|
|
|
148
139
|
op = "="
|
|
149
140
|
case = "lower"
|
|
150
141
|
if isinstance(val, str) and val[:2] == "@@" and val[2:]:
|
|
151
|
-
sql.append("{} {} {
|
|
142
|
+
sql.append(f"{key} {op} {val[2:]}")
|
|
152
143
|
elif op in ["between", "not between"]:
|
|
153
|
-
sql.append("{} {} %s and %s"
|
|
144
|
+
sql.append(f"{key} {op} %s and %s")
|
|
154
145
|
vals.extend(val)
|
|
155
146
|
else:
|
|
156
147
|
if case:
|
|
157
|
-
sql.append("{
|
|
148
|
+
sql.append(f"{case}({key}) {op} {case}(%s)")
|
|
158
149
|
else:
|
|
159
|
-
sql.append("{
|
|
150
|
+
sql.append(f"{key} {op} %s")
|
|
160
151
|
vals.append(val)
|
|
161
152
|
connect = "AND"
|
|
162
153
|
|
|
163
|
-
|
|
164
154
|
def quote(data):
|
|
165
155
|
if isinstance(data, list):
|
|
166
156
|
new = []
|
|
@@ -177,14 +167,13 @@ def quote(data):
|
|
|
177
167
|
if '"' in part:
|
|
178
168
|
new.append(part)
|
|
179
169
|
elif part.upper() in reserved_words:
|
|
180
|
-
new.append('"
|
|
170
|
+
new.append(f'"{part}"')
|
|
181
171
|
elif re.findall("[/]", part):
|
|
182
|
-
new.append('"
|
|
172
|
+
new.append(f'"{part}"')
|
|
183
173
|
else:
|
|
184
174
|
new.append(part)
|
|
185
175
|
return ".".join(new)
|
|
186
176
|
|
|
187
|
-
|
|
188
177
|
class SQL(object):
|
|
189
178
|
server = "PostGreSQL"
|
|
190
179
|
type_column_identifier = "data_type"
|
|
@@ -199,10 +188,10 @@ class SQL(object):
|
|
|
199
188
|
ColumnMissingErrorCodes = ["42703"]
|
|
200
189
|
ForeignKeyMissingErrorCodes = ["42704"]
|
|
201
190
|
|
|
202
|
-
ConnectionErrorCodes = ["08001", "08S01"]
|
|
191
|
+
ConnectionErrorCodes = ["08001", "08S01","57P03", "08006", "53300"]
|
|
203
192
|
DuplicateKeyErrorCodes = [] # Handled in regex check.
|
|
204
193
|
RetryTransactionCodes = []
|
|
205
|
-
TruncationErrorCodes = []
|
|
194
|
+
TruncationErrorCodes = ["22001"]
|
|
206
195
|
LockTimeoutErrorCodes = ["55P03"]
|
|
207
196
|
DatabaseObjectExistsErrorCodes = ["42710", "42P07", "42P04"]
|
|
208
197
|
DataIntegrityErrorCodes = ["23503"]
|
|
@@ -307,7 +296,7 @@ class SQL(object):
|
|
|
307
296
|
tables = {table: chr(letter)}
|
|
308
297
|
letter += 1
|
|
309
298
|
__select = []
|
|
310
|
-
__from = ["{} AS {
|
|
299
|
+
__from = [f"{quote(table)} AS {tables.get(table)}"]
|
|
311
300
|
__left_join = []
|
|
312
301
|
|
|
313
302
|
for column in columns:
|
|
@@ -321,44 +310,33 @@ class SQL(object):
|
|
|
321
310
|
ref_table = foreign["referenced_table_name"]
|
|
322
311
|
ref_schema = foreign["referenced_table_schema"]
|
|
323
312
|
ref_column = foreign["referenced_column_name"]
|
|
324
|
-
lookup = "{}:{
|
|
313
|
+
lookup = f"{ref_table}:{parts[0]}"
|
|
325
314
|
if lookup in tables:
|
|
326
315
|
__select.append(
|
|
327
|
-
'{}."{}" as "{}"'
|
|
328
|
-
tables.get(lookup), parts[1], "_".join(parts)
|
|
329
|
-
)
|
|
316
|
+
f'{tables.get(lookup)}."{parts[1]}" as "{'_'.join(parts)}"'
|
|
330
317
|
)
|
|
331
318
|
else:
|
|
332
319
|
tables[lookup] = chr(letter)
|
|
333
320
|
letter += 1
|
|
334
321
|
__select.append(
|
|
335
|
-
'{}."{}" as "{}"'
|
|
336
|
-
tables.get(lookup), parts[1], "_".join(parts)
|
|
337
|
-
)
|
|
322
|
+
f'{tables.get(lookup)}."{parts[1]}" as "{'_'.join(parts)}"'
|
|
338
323
|
)
|
|
339
324
|
__left_join.append(
|
|
340
|
-
'LEFT OUTER JOIN "{}"."{}" AS {}'
|
|
341
|
-
ref_schema, ref_table, tables.get(lookup)
|
|
342
|
-
)
|
|
325
|
+
f'LEFT OUTER JOIN "{ref_schema}"."{ref_table}" AS {tables.get(lookup)}'
|
|
343
326
|
)
|
|
344
327
|
__left_join.append(
|
|
345
|
-
'ON {}."{}" = {}."{}"'
|
|
346
|
-
tables.get(table),
|
|
347
|
-
parts[0],
|
|
348
|
-
tables.get(lookup),
|
|
349
|
-
ref_column,
|
|
350
|
-
)
|
|
328
|
+
f'ON {tables.get(table)}."{parts[0]}" = {tables.get(lookup)}."{ref_column}"'
|
|
351
329
|
)
|
|
352
330
|
if orderby and column in orderby:
|
|
353
331
|
orderby = orderby.replace(
|
|
354
|
-
column, "{
|
|
332
|
+
column, f"{tables.get(lookup)}.{parts[1]}"
|
|
355
333
|
)
|
|
356
334
|
|
|
357
335
|
else:
|
|
358
336
|
if "(" in column:
|
|
359
337
|
__select.append(column)
|
|
360
338
|
else:
|
|
361
|
-
__select.append("{
|
|
339
|
+
__select.append(f"{tables.get(table)}.{column}")
|
|
362
340
|
sql = ["SELECT"]
|
|
363
341
|
sql.append(",".join(__select))
|
|
364
342
|
sql.append("FROM")
|
|
@@ -397,11 +375,11 @@ class SQL(object):
|
|
|
397
375
|
orderby = ",".join(orderby)
|
|
398
376
|
sql.append(orderby)
|
|
399
377
|
if start and qty:
|
|
400
|
-
sql.append("OFFSET {} ROWS FETCH NEXT {} ROWS ONLY"
|
|
378
|
+
sql.append(f"OFFSET {start} ROWS FETCH NEXT {qty} ROWS ONLY")
|
|
401
379
|
elif start:
|
|
402
|
-
sql.append("OFFSET {} ROWS"
|
|
380
|
+
sql.append(f"OFFSET {start} ROWS")
|
|
403
381
|
elif qty:
|
|
404
|
-
sql.append("FETCH NEXT {} ROWS ONLY"
|
|
382
|
+
sql.append(f"FETCH NEXT {qty} ROWS ONLY")
|
|
405
383
|
if lock or skip_locked:
|
|
406
384
|
sql.append("FOR UPDATE")
|
|
407
385
|
if skip_locked:
|
|
@@ -411,7 +389,7 @@ class SQL(object):
|
|
|
411
389
|
|
|
412
390
|
@classmethod
|
|
413
391
|
def create_database(cls, name):
|
|
414
|
-
return "create database "
|
|
392
|
+
return f"create database {name}", tuple()
|
|
415
393
|
|
|
416
394
|
@classmethod
|
|
417
395
|
def last_id(cls, table):
|
|
@@ -432,23 +410,22 @@ class SQL(object):
|
|
|
432
410
|
|
|
433
411
|
@classmethod
|
|
434
412
|
def drop_database(cls, name):
|
|
435
|
-
return "drop database if exists "
|
|
413
|
+
return f"drop database if exists {name}", tuple()
|
|
436
414
|
|
|
437
415
|
@classmethod
|
|
438
416
|
def create_table(cls, name, columns={}, drop=False):
|
|
439
417
|
if "." in name:
|
|
440
418
|
fqtn = name
|
|
441
419
|
else:
|
|
442
|
-
fqtn = "public."
|
|
420
|
+
fqtn = f"public.{name}"
|
|
443
421
|
schema, table = fqtn.split(".")
|
|
444
422
|
name = fqtn.replace(".", "_")
|
|
445
|
-
trigger = "".format(name)
|
|
446
423
|
sql = []
|
|
447
424
|
if drop:
|
|
448
|
-
sql.append(cls.drop_table(fqtn))
|
|
425
|
+
sql.append(cls.drop_table(fqtn)[0])
|
|
449
426
|
sql.append(
|
|
450
|
-
"""
|
|
451
|
-
CREATE TABLE {
|
|
427
|
+
f"""
|
|
428
|
+
CREATE TABLE {fqtn} (
|
|
452
429
|
sys_id BIGSERIAL PRIMARY KEY,
|
|
453
430
|
sys_modified TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
454
431
|
sys_created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
@@ -458,9 +435,9 @@ class SQL(object):
|
|
|
458
435
|
description TEXT
|
|
459
436
|
);
|
|
460
437
|
|
|
461
|
-
SELECT SETVAL(PG_GET_SERIAL_SEQUENCE('{
|
|
438
|
+
SELECT SETVAL(PG_GET_SERIAL_SEQUENCE('{fqtn}', 'sys_id'),1000,TRUE);
|
|
462
439
|
|
|
463
|
-
CREATE OR REPLACE FUNCTION {
|
|
440
|
+
CREATE OR REPLACE FUNCTION {schema}.on_sys_modified()
|
|
464
441
|
RETURNS TRIGGER AS
|
|
465
442
|
$BODY$
|
|
466
443
|
BEGIN
|
|
@@ -480,13 +457,11 @@ class SQL(object):
|
|
|
480
457
|
LANGUAGE plpgsql VOLATILE
|
|
481
458
|
COST 100;
|
|
482
459
|
|
|
483
|
-
CREATE TRIGGER on_update_row_{
|
|
484
|
-
BEFORE INSERT OR UPDATE ON {
|
|
485
|
-
FOR EACH ROW EXECUTE PROCEDURE {
|
|
460
|
+
CREATE TRIGGER on_update_row_{fqtn.replace('.', '_')}
|
|
461
|
+
BEFORE INSERT OR UPDATE ON {fqtn}
|
|
462
|
+
FOR EACH ROW EXECUTE PROCEDURE {schema}.on_sys_modified();
|
|
486
463
|
|
|
487
|
-
"""
|
|
488
|
-
fqtn, schema, table, fqtn.replace(".", "_")
|
|
489
|
-
)
|
|
464
|
+
"""
|
|
490
465
|
)
|
|
491
466
|
|
|
492
467
|
for key, val in columns.items():
|
|
@@ -494,26 +469,24 @@ class SQL(object):
|
|
|
494
469
|
if key in system_fields:
|
|
495
470
|
continue
|
|
496
471
|
sql.append(
|
|
497
|
-
"ALTER TABLE {} ADD COLUMN {} {};"
|
|
498
|
-
quote(fqtn), quote(key), cls.get_type(val)
|
|
499
|
-
)
|
|
472
|
+
f"ALTER TABLE {quote(fqtn)} ADD COLUMN {quote(key)} {cls.get_type(val)};"
|
|
500
473
|
)
|
|
501
474
|
return "\n\t".join(sql), tuple()
|
|
502
475
|
|
|
503
476
|
@classmethod
|
|
504
477
|
def drop_table(cls, name):
|
|
505
|
-
return "drop table if exists
|
|
478
|
+
return f"drop table if exists {quote(name)} cascade;", tuple()
|
|
506
479
|
|
|
507
480
|
@classmethod
|
|
508
481
|
def drop_column(cls, table, name, cascade=True):
|
|
509
482
|
if cascade:
|
|
510
483
|
return (
|
|
511
|
-
"ALTER TABLE
|
|
484
|
+
f"ALTER TABLE {quote(table)} DROP COLUMN {quote(name)} CASCADE",
|
|
512
485
|
tuple(),
|
|
513
486
|
)
|
|
514
487
|
else:
|
|
515
488
|
return (
|
|
516
|
-
"ALTER TABLE
|
|
489
|
+
f"ALTER TABLE {quote(table)} DROP COLUMN {quote(name)}",
|
|
517
490
|
tuple(),
|
|
518
491
|
)
|
|
519
492
|
|
|
@@ -651,7 +624,7 @@ class SQL(object):
|
|
|
651
624
|
cls, table, columns, key_to_table, key_to_columns, name=None, schema=None
|
|
652
625
|
):
|
|
653
626
|
if "." not in table and schema:
|
|
654
|
-
table = "{}.{}"
|
|
627
|
+
table = f"{schema}.{table}"
|
|
655
628
|
if isinstance(key_to_columns, str):
|
|
656
629
|
key_to_columns = [key_to_columns]
|
|
657
630
|
if isinstance(columns, str):
|
|
@@ -662,10 +635,8 @@ class SQL(object):
|
|
|
662
635
|
m.update(" ".join(columns).encode("utf-8"))
|
|
663
636
|
m.update(key_to_table.encode("utf-8"))
|
|
664
637
|
m.update(" ".join(key_to_columns).encode("utf-8"))
|
|
665
|
-
name = "FK_
|
|
666
|
-
sql = "ALTER TABLE {} ADD CONSTRAINT {} FOREIGN KEY ({}) REFERENCES {} ({});"
|
|
667
|
-
table, name, ",".join(columns), key_to_table, ",".join(key_to_columns)
|
|
668
|
-
)
|
|
638
|
+
name = f"FK_{m.hexdigest()}"
|
|
639
|
+
sql = f"ALTER TABLE {table} ADD CONSTRAINT {name} FOREIGN KEY ({','.join(columns)}) REFERENCES {key_to_table} ({','.join(key_to_columns)});"
|
|
669
640
|
|
|
670
641
|
return sql, tuple()
|
|
671
642
|
|
|
@@ -680,7 +651,7 @@ class SQL(object):
|
|
|
680
651
|
schema=None,
|
|
681
652
|
):
|
|
682
653
|
if "." not in table and schema:
|
|
683
|
-
table = "{}.{}"
|
|
654
|
+
table = f"{schema}.{table}"
|
|
684
655
|
if isinstance(key_to_columns, str):
|
|
685
656
|
key_to_columns = [key_to_columns]
|
|
686
657
|
if isinstance(columns, str):
|
|
@@ -691,8 +662,8 @@ class SQL(object):
|
|
|
691
662
|
m.update(" ".join(columns).encode("utf-8"))
|
|
692
663
|
m.update(key_to_table.encode("utf-8"))
|
|
693
664
|
m.update(" ".join(key_to_columns).encode("utf-8"))
|
|
694
|
-
name = "FK_
|
|
695
|
-
sql = "ALTER TABLE {} DROP CONSTRAINT {};"
|
|
665
|
+
name = f"FK_{m.hexdigest()}"
|
|
666
|
+
sql = f"ALTER TABLE {table} DROP CONSTRAINT {name};"
|
|
696
667
|
return sql, tuple()
|
|
697
668
|
|
|
698
669
|
@classmethod
|
|
@@ -715,7 +686,7 @@ class SQL(object):
|
|
|
715
686
|
CREATE EXTENSION btree_gist; is required to use gist
|
|
716
687
|
"""
|
|
717
688
|
if "." not in table and schema:
|
|
718
|
-
table = "{}.{}"
|
|
689
|
+
table = f"{schema}.{table}"
|
|
719
690
|
if isinstance(columns, (list, set)):
|
|
720
691
|
columns = ",".join([quote(c.lower()) for c in columns])
|
|
721
692
|
else:
|
|
@@ -733,12 +704,10 @@ class SQL(object):
|
|
|
733
704
|
)
|
|
734
705
|
if trigram:
|
|
735
706
|
sql.append(
|
|
736
|
-
"IDX__TRGM_{}_{}__{}"
|
|
737
|
-
table.replace(".", "_"), trigram.upper(), name
|
|
738
|
-
)
|
|
707
|
+
f"IDX__TRGM_{table.replace('.', '_')}_{trigram.upper()}__{name}"
|
|
739
708
|
)
|
|
740
709
|
else:
|
|
741
|
-
sql.append("IDX__{
|
|
710
|
+
sql.append(f"IDX__{table.replace('.', '_')}__{name}")
|
|
742
711
|
sql.append("ON")
|
|
743
712
|
sql.append(quote(tablename))
|
|
744
713
|
|
|
@@ -755,7 +724,7 @@ class SQL(object):
|
|
|
755
724
|
column = tbl.column(column_name)
|
|
756
725
|
if column.py_type == str:
|
|
757
726
|
if lower:
|
|
758
|
-
sql.append("lower({
|
|
727
|
+
sql.append(f"lower({quote(column_name)})")
|
|
759
728
|
else:
|
|
760
729
|
sql.append(quote(column_name))
|
|
761
730
|
else:
|
|
@@ -764,7 +733,7 @@ class SQL(object):
|
|
|
764
733
|
else:
|
|
765
734
|
sql.append(columns)
|
|
766
735
|
if trigram:
|
|
767
|
-
sql.append("{
|
|
736
|
+
sql.append(f"{trigram.lower()}_trgm_ops")
|
|
768
737
|
sql.append(")")
|
|
769
738
|
vals = []
|
|
770
739
|
|
|
@@ -774,7 +743,7 @@ class SQL(object):
|
|
|
774
743
|
@classmethod
|
|
775
744
|
def drop_index(cls, table=None, columns=None, name=None, schema=None, trigram=None):
|
|
776
745
|
if "." not in table and schema:
|
|
777
|
-
table = "{}.{}"
|
|
746
|
+
table = f"{schema}.{table}"
|
|
778
747
|
if isinstance(columns, (list, set)):
|
|
779
748
|
columns = ",".join([quote(c.lower()) for c in columns])
|
|
780
749
|
else:
|
|
@@ -790,12 +759,10 @@ class SQL(object):
|
|
|
790
759
|
)
|
|
791
760
|
if trigram:
|
|
792
761
|
sql.append(
|
|
793
|
-
"IDX__TRGM_{}_{}__{}"
|
|
794
|
-
table.replace(".", "_"), trigram.upper(), name
|
|
795
|
-
)
|
|
762
|
+
f"IDX__TRGM_{table.replace('.', '_')}_{trigram.upper()}__{name}"
|
|
796
763
|
)
|
|
797
764
|
else:
|
|
798
|
-
sql.append("IDX__{
|
|
765
|
+
sql.append(f"IDX__{table.replace('.', '_')}__{name}")
|
|
799
766
|
return " ".join(sql), tuple()
|
|
800
767
|
|
|
801
768
|
@classmethod
|
|
@@ -874,12 +841,12 @@ class SQL(object):
|
|
|
874
841
|
if connect:
|
|
875
842
|
sql.append(connect)
|
|
876
843
|
if isinstance(val, str) and val[:2] == "@@" and val[2:]:
|
|
877
|
-
sql.append("{} = {
|
|
844
|
+
sql.append(f"{key} = {val[2:]}")
|
|
878
845
|
else:
|
|
879
846
|
if excluded:
|
|
880
|
-
sql.append("{} = EXCLUDED.{}"
|
|
847
|
+
sql.append(f"{key} = EXCLUDED.{key}")
|
|
881
848
|
else:
|
|
882
|
-
sql.append("{} = %s"
|
|
849
|
+
sql.append(f"{key} = %s")
|
|
883
850
|
vals.append(val)
|
|
884
851
|
connect = ","
|
|
885
852
|
if is_join:
|
|
@@ -920,18 +887,10 @@ class SQL(object):
|
|
|
920
887
|
return cls.TYPES.BOOLEAN
|
|
921
888
|
elif isinstance(v, int) or v is int:
|
|
922
889
|
return cls.TYPES.BIGINT
|
|
923
|
-
# elif isinstance(v, int) \
|
|
924
|
-
# or v is int:
|
|
925
|
-
# if v is int:
|
|
926
|
-
# return cls.TYPES.INTEGER
|
|
927
|
-
# if v > 2147483647 or v < -2147483648:
|
|
928
|
-
# return cls.TYPES.BIGINT
|
|
929
|
-
# else:
|
|
930
|
-
# return cls.TYPES.INTEGER
|
|
931
890
|
elif isinstance(v, float) or v is float:
|
|
932
|
-
return cls.TYPES.NUMERIC
|
|
891
|
+
return f"{cls.TYPES.NUMERIC}(19, 6)"
|
|
933
892
|
elif isinstance(v, decimal.Decimal) or v is decimal.Decimal:
|
|
934
|
-
return cls.TYPES.NUMERIC
|
|
893
|
+
return f"{cls.TYPES.NUMERIC}(19, 6)"
|
|
935
894
|
elif isinstance(v, datetime.datetime) or v is datetime.datetime:
|
|
936
895
|
return cls.TYPES.DATETIME
|
|
937
896
|
elif isinstance(v, datetime.date) or v is datetime.date:
|
|
@@ -942,7 +901,6 @@ class SQL(object):
|
|
|
942
901
|
return cls.TYPES.INTERVAL
|
|
943
902
|
elif isinstance(v, bytes) or v is bytes:
|
|
944
903
|
return cls.TYPES.BINARY
|
|
945
|
-
# Everything else defaults to TEXT, incl. None
|
|
946
904
|
return cls.TYPES.TEXT
|
|
947
905
|
|
|
948
906
|
@classmethod
|
|
@@ -956,14 +914,6 @@ class SQL(object):
|
|
|
956
914
|
return cls.TYPES.BOOLEAN
|
|
957
915
|
elif isinstance(v, int) or v is int:
|
|
958
916
|
return cls.TYPES.BIGINT
|
|
959
|
-
# elif isinstance(v, int) \
|
|
960
|
-
# or v is int:
|
|
961
|
-
# if v is int:
|
|
962
|
-
# return cls.TYPES.INTEGER
|
|
963
|
-
# if v > 2147483647 or v < -2147483648:
|
|
964
|
-
# return cls.TYPES.BIGINT
|
|
965
|
-
# else:
|
|
966
|
-
# return cls.TYPES.INTEGER
|
|
967
917
|
elif isinstance(v, float) or v is float:
|
|
968
918
|
return cls.TYPES.NUMERIC
|
|
969
919
|
elif isinstance(v, decimal.Decimal) or v is decimal.Decimal:
|
|
@@ -978,7 +928,6 @@ class SQL(object):
|
|
|
978
928
|
return cls.TYPES.INTERVAL
|
|
979
929
|
elif isinstance(v, bytes) or v is bytes:
|
|
980
930
|
return cls.TYPES.BINARY
|
|
981
|
-
# Everything else defaults to TEXT, incl. None
|
|
982
931
|
return cls.TYPES.TEXT
|
|
983
932
|
|
|
984
933
|
@classmethod
|
|
@@ -1011,22 +960,15 @@ class SQL(object):
|
|
|
1011
960
|
elif v == cls.TYPES.INTERVAL_TZ:
|
|
1012
961
|
return datetime.timedelta
|
|
1013
962
|
else:
|
|
1014
|
-
raise Exception("unmapped type
|
|
963
|
+
raise Exception(f"unmapped type {v}")
|
|
1015
964
|
|
|
1016
965
|
@classmethod
|
|
1017
966
|
def massage_data(cls, data):
|
|
1018
|
-
"""
|
|
1019
|
-
|
|
1020
|
-
:param :
|
|
1021
|
-
:param :
|
|
1022
|
-
:param :
|
|
1023
|
-
:returns:
|
|
1024
|
-
"""
|
|
1025
967
|
data = {key.lower(): val for key, val in data.items()}
|
|
1026
968
|
primaryKey = set(cls.GetPrimaryKeyColumnNames())
|
|
1027
969
|
if not primaryKey:
|
|
1028
970
|
if not cls.Exists():
|
|
1029
|
-
raise DbTableMissingError
|
|
971
|
+
raise exceptions.DbTableMissingError
|
|
1030
972
|
dataKeys = set(data.keys()).intersection(primaryKey)
|
|
1031
973
|
dataColumns = set(data.keys()).difference(primaryKey)
|
|
1032
974
|
pk = {}
|
|
@@ -1043,62 +985,58 @@ class SQL(object):
|
|
|
1043
985
|
for key, val in columns.items():
|
|
1044
986
|
key = re.sub("<>!=%", "", key.lower())
|
|
1045
987
|
sql.append(
|
|
1046
|
-
"ALTER TABLE {} ADD {} {} {};"
|
|
1047
|
-
quote(table), quote(key), cls.get_type(val), null
|
|
1048
|
-
)
|
|
988
|
+
f"ALTER TABLE {quote(table)} ADD {quote(key)} {cls.get_type(val)} {null};"
|
|
1049
989
|
)
|
|
1050
990
|
return "\n\t".join(sql), tuple()
|
|
1051
991
|
|
|
1052
992
|
@classmethod
|
|
1053
993
|
def alter_drop(cls, table, columns):
|
|
1054
|
-
sql = ["ALTER TABLE {} DROP COLUMN"
|
|
994
|
+
sql = [f"ALTER TABLE {quote(table)} DROP COLUMN"]
|
|
1055
995
|
if isinstance(columns, dict):
|
|
1056
996
|
for key, val in columns.items():
|
|
1057
997
|
key = re.sub("<>!=%", "", key.lower())
|
|
1058
|
-
sql.append("{},"
|
|
998
|
+
sql.append(f"{key},")
|
|
1059
999
|
if sql[-1][-1] == ",":
|
|
1060
1000
|
sql[-1] = sql[-1][:-1]
|
|
1061
1001
|
return "\n\t".join(sql), tuple()
|
|
1062
1002
|
|
|
1063
1003
|
@classmethod
|
|
1064
1004
|
def alter_column_by_type(cls, table, column, value, nullable=True):
|
|
1065
|
-
sql = ["ALTER TABLE {} ALTER COLUMN"
|
|
1066
|
-
sql.append("{} TYPE {
|
|
1067
|
-
sql.append("USING {
|
|
1005
|
+
sql = [f"ALTER TABLE {quote(table)} ALTER COLUMN"]
|
|
1006
|
+
sql.append(f"{quote(column)} TYPE {cls.get_type(value)}")
|
|
1007
|
+
sql.append(f"USING {quote(column)}::{cls.get_conv(value)}")
|
|
1068
1008
|
if not nullable:
|
|
1069
1009
|
sql.append("NOT NULL")
|
|
1070
1010
|
return "\n\t".join(sql), tuple()
|
|
1071
1011
|
|
|
1072
1012
|
@classmethod
|
|
1073
1013
|
def alter_column_by_sql(cls, table, column, value):
|
|
1074
|
-
sql = ["ALTER TABLE {} ALTER COLUMN"
|
|
1075
|
-
sql.append("{
|
|
1014
|
+
sql = [f"ALTER TABLE {quote(table)} ALTER COLUMN"]
|
|
1015
|
+
sql.append(f"{quote(column)} {value}")
|
|
1076
1016
|
return " ".join(sql), tuple()
|
|
1077
1017
|
|
|
1078
1018
|
@classmethod
|
|
1079
1019
|
def rename_column(cls, table, orig, new):
|
|
1080
1020
|
return (
|
|
1081
|
-
"ALTER TABLE {} RENAME COLUMN {} TO {};"
|
|
1082
|
-
quote(table), quote(orig), quote(new)
|
|
1083
|
-
),
|
|
1021
|
+
f"ALTER TABLE {quote(table)} RENAME COLUMN {quote(orig)} TO {quote(new)};",
|
|
1084
1022
|
tuple(),
|
|
1085
1023
|
)
|
|
1086
1024
|
|
|
1087
1025
|
@classmethod
|
|
1088
1026
|
def rename_table(cls, table, new):
|
|
1089
|
-
return "ALTER TABLE {} RENAME TO {
|
|
1027
|
+
return f"ALTER TABLE {quote(table)} RENAME TO {quote(new)};", tuple()
|
|
1090
1028
|
|
|
1091
1029
|
@classmethod
|
|
1092
1030
|
def create_savepoint(cls, sp):
|
|
1093
|
-
return 'SAVEPOINT "{}"'
|
|
1031
|
+
return f'SAVEPOINT "{sp}"', tuple()
|
|
1094
1032
|
|
|
1095
1033
|
@classmethod
|
|
1096
1034
|
def release_savepoint(cls, sp):
|
|
1097
|
-
return 'RELEASE SAVEPOINT "{}"'
|
|
1035
|
+
return f'RELEASE SAVEPOINT "{sp}"', tuple()
|
|
1098
1036
|
|
|
1099
1037
|
@classmethod
|
|
1100
1038
|
def rollback_savepoint(cls, sp):
|
|
1101
|
-
return 'ROLLBACK TO SAVEPOINT "{}"'
|
|
1039
|
+
return f'ROLLBACK TO SAVEPOINT "{sp}"', tuple()
|
|
1102
1040
|
|
|
1103
1041
|
@classmethod
|
|
1104
1042
|
def duplicate_rows(cls, table, columns, where={}):
|
|
@@ -1113,14 +1051,14 @@ class SQL(object):
|
|
|
1113
1051
|
|
|
1114
1052
|
@classmethod
|
|
1115
1053
|
def delete(cls, table, where):
|
|
1116
|
-
sql = ["DELETE FROM {}"
|
|
1054
|
+
sql = [f"DELETE FROM {table}"]
|
|
1117
1055
|
vals = []
|
|
1118
1056
|
make_where(where, sql, vals)
|
|
1119
1057
|
return " ".join(sql), tuple(vals)
|
|
1120
1058
|
|
|
1121
1059
|
@classmethod
|
|
1122
1060
|
def truncate(cls, table):
|
|
1123
|
-
return "truncate table {
|
|
1061
|
+
return f"truncate table {quote(table)}", tuple()
|
|
1124
1062
|
|
|
1125
1063
|
@classmethod
|
|
1126
1064
|
def create_view(cls, name, query, temp=False, silent=True):
|
|
@@ -1145,23 +1083,21 @@ class SQL(object):
|
|
|
1145
1083
|
|
|
1146
1084
|
@classmethod
|
|
1147
1085
|
def alter_trigger(cls, table, state="ENABLE", name="USER"):
|
|
1148
|
-
return "ALTER TABLE {} {} TRIGGER {}"
|
|
1086
|
+
return f"ALTER TABLE {table} {state} TRIGGER {name}", tuple()
|
|
1149
1087
|
|
|
1150
1088
|
@classmethod
|
|
1151
1089
|
def set_sequence(cls, table, next_value):
|
|
1152
1090
|
return (
|
|
1153
|
-
"SELECT SETVAL(PG_GET_SERIAL_SEQUENCE('{
|
|
1154
|
-
table, next_value
|
|
1155
|
-
),
|
|
1091
|
+
f"SELECT SETVAL(PG_GET_SERIAL_SEQUENCE('{table}', 'sys_id'),{next_value},FALSE)",
|
|
1156
1092
|
tuple(),
|
|
1157
1093
|
)
|
|
1158
1094
|
|
|
1159
1095
|
@classmethod
|
|
1160
1096
|
def missing(cls, table, list, column="SYS_ID", where=None):
|
|
1161
1097
|
sql = [
|
|
1162
|
-
"SELECT * FROM",
|
|
1098
|
+
f"SELECT * FROM",
|
|
1163
1099
|
f"UNNEST('{{{','.join([str(x) for x in list])}}}'::int[]) id",
|
|
1164
|
-
"EXCEPT ALL",
|
|
1100
|
+
f"EXCEPT ALL",
|
|
1165
1101
|
f"SELECT {column} FROM {table}",
|
|
1166
1102
|
]
|
|
1167
1103
|
vals = []
|
|
@@ -1184,213 +1120,3 @@ class SQL(object):
|
|
|
1184
1120
|
BOOLEAN = "BOOLEAN"
|
|
1185
1121
|
BINARY = "BYTEA"
|
|
1186
1122
|
INTERVAL = "INTERVAL"
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
reserved_words = [
|
|
1190
|
-
"ADMIN",
|
|
1191
|
-
"ALIAS",
|
|
1192
|
-
"ALL",
|
|
1193
|
-
"ALLOCATE",
|
|
1194
|
-
"ANALYSE",
|
|
1195
|
-
"ANALYZE",
|
|
1196
|
-
"AND",
|
|
1197
|
-
"ANY",
|
|
1198
|
-
"ARE",
|
|
1199
|
-
"ARRAY",
|
|
1200
|
-
"AS",
|
|
1201
|
-
"ASC",
|
|
1202
|
-
"AUTHORIZATION",
|
|
1203
|
-
"BETWEEN",
|
|
1204
|
-
"BINARY",
|
|
1205
|
-
"BLOB",
|
|
1206
|
-
"BOTH",
|
|
1207
|
-
"BREADTH",
|
|
1208
|
-
"CALL",
|
|
1209
|
-
"CASCADED",
|
|
1210
|
-
"CASE",
|
|
1211
|
-
"CAST",
|
|
1212
|
-
"CATALOG",
|
|
1213
|
-
"CHECK",
|
|
1214
|
-
"CLOB",
|
|
1215
|
-
"COLLATE",
|
|
1216
|
-
"COLLATION",
|
|
1217
|
-
"COLUMN",
|
|
1218
|
-
"COMPLETION",
|
|
1219
|
-
"CONNECT",
|
|
1220
|
-
"CONNECTION",
|
|
1221
|
-
"CONSTRAINT",
|
|
1222
|
-
"CONSTRUCTOR",
|
|
1223
|
-
"CONTINUE",
|
|
1224
|
-
"CORRESPONDING",
|
|
1225
|
-
"CREATE",
|
|
1226
|
-
"CROSS",
|
|
1227
|
-
"CUBE",
|
|
1228
|
-
"CURRENT",
|
|
1229
|
-
"CURRENT_DATE",
|
|
1230
|
-
"CURRENT_PATH",
|
|
1231
|
-
"CURRENT_ROLE",
|
|
1232
|
-
"CURRENT_TIME",
|
|
1233
|
-
"CURRENT_TIMESTAMP",
|
|
1234
|
-
"CURRENT_USER",
|
|
1235
|
-
"DATA",
|
|
1236
|
-
"DATE",
|
|
1237
|
-
"DEFAULT",
|
|
1238
|
-
"DEFERRABLE",
|
|
1239
|
-
"DEPTH",
|
|
1240
|
-
"DEREF",
|
|
1241
|
-
"DESC",
|
|
1242
|
-
"DESCRIBE",
|
|
1243
|
-
"DESCRIPTOR",
|
|
1244
|
-
"DESTROY",
|
|
1245
|
-
"DESTRUCTOR",
|
|
1246
|
-
"DETERMINISTIC",
|
|
1247
|
-
"DIAGNOSTICS",
|
|
1248
|
-
"DICTIONARY",
|
|
1249
|
-
"DISCONNECT",
|
|
1250
|
-
"DISTINCT",
|
|
1251
|
-
"DO",
|
|
1252
|
-
"DYNAMIC",
|
|
1253
|
-
"ELSE",
|
|
1254
|
-
"END",
|
|
1255
|
-
"END-EXEC",
|
|
1256
|
-
"EQUALS",
|
|
1257
|
-
"EVERY",
|
|
1258
|
-
"EXCEPT",
|
|
1259
|
-
"EXCEPTION",
|
|
1260
|
-
"EXEC",
|
|
1261
|
-
"FALSE",
|
|
1262
|
-
"FIRST",
|
|
1263
|
-
"FOR",
|
|
1264
|
-
"FOREIGN",
|
|
1265
|
-
"FOUND",
|
|
1266
|
-
"FREE",
|
|
1267
|
-
"FREEZE",
|
|
1268
|
-
"FROM",
|
|
1269
|
-
"FULL",
|
|
1270
|
-
"GENERAL",
|
|
1271
|
-
"GO",
|
|
1272
|
-
"GOTO",
|
|
1273
|
-
"GRANT",
|
|
1274
|
-
"GROUP",
|
|
1275
|
-
"GROUPING",
|
|
1276
|
-
"HAVING",
|
|
1277
|
-
"HOST",
|
|
1278
|
-
"IDENTITY",
|
|
1279
|
-
"IGNORE",
|
|
1280
|
-
"ILIKE",
|
|
1281
|
-
"IN",
|
|
1282
|
-
"INDICATOR",
|
|
1283
|
-
"INITIALIZE",
|
|
1284
|
-
"INITIALLY",
|
|
1285
|
-
"INNER",
|
|
1286
|
-
"INTERSECT",
|
|
1287
|
-
"INTO",
|
|
1288
|
-
"IS",
|
|
1289
|
-
"ISNULL",
|
|
1290
|
-
"ITERATE",
|
|
1291
|
-
"JOIN",
|
|
1292
|
-
"LARGE",
|
|
1293
|
-
"LAST",
|
|
1294
|
-
"LATERAL",
|
|
1295
|
-
"LEADING",
|
|
1296
|
-
"LEFT",
|
|
1297
|
-
"LESS",
|
|
1298
|
-
"LIKE",
|
|
1299
|
-
"LIMIT",
|
|
1300
|
-
"LOCALTIME",
|
|
1301
|
-
"LOCALTIMESTAMP",
|
|
1302
|
-
"LOCATOR",
|
|
1303
|
-
"MAP",
|
|
1304
|
-
"MODIFIES",
|
|
1305
|
-
"MODIFY",
|
|
1306
|
-
"MODULE",
|
|
1307
|
-
"NAME",
|
|
1308
|
-
"NATURAL",
|
|
1309
|
-
"NCLOB",
|
|
1310
|
-
"NEW",
|
|
1311
|
-
"NOT",
|
|
1312
|
-
"NOTNULL",
|
|
1313
|
-
"NULL",
|
|
1314
|
-
"OBJECT",
|
|
1315
|
-
"OFF",
|
|
1316
|
-
"OFFSET",
|
|
1317
|
-
"OLD",
|
|
1318
|
-
"ON",
|
|
1319
|
-
"ONLY",
|
|
1320
|
-
"OPEN",
|
|
1321
|
-
"OPERATION",
|
|
1322
|
-
"OR",
|
|
1323
|
-
"ORDER",
|
|
1324
|
-
"ORDINALITY",
|
|
1325
|
-
"OUTER",
|
|
1326
|
-
"OUTPUT",
|
|
1327
|
-
"OVERLAPS",
|
|
1328
|
-
"PAD",
|
|
1329
|
-
"PARAMETER",
|
|
1330
|
-
"PARAMETERS",
|
|
1331
|
-
"PLACING",
|
|
1332
|
-
"POSTFIX",
|
|
1333
|
-
"PREFIX",
|
|
1334
|
-
"PREORDER",
|
|
1335
|
-
"PRESERVE",
|
|
1336
|
-
"PRIMARY",
|
|
1337
|
-
"PUBLIC",
|
|
1338
|
-
"READS",
|
|
1339
|
-
"RECURSIVE",
|
|
1340
|
-
"REF",
|
|
1341
|
-
"REFERENCES",
|
|
1342
|
-
"REFERENCING",
|
|
1343
|
-
"RESULT",
|
|
1344
|
-
"RETURN",
|
|
1345
|
-
"RIGHT",
|
|
1346
|
-
"ROLE",
|
|
1347
|
-
"ROLLUP",
|
|
1348
|
-
"ROUTINE",
|
|
1349
|
-
"ROWS",
|
|
1350
|
-
"SAVEPOINT",
|
|
1351
|
-
"SCOPE",
|
|
1352
|
-
"SEARCH",
|
|
1353
|
-
"SECTION",
|
|
1354
|
-
"SELECT",
|
|
1355
|
-
"SESSION_USER",
|
|
1356
|
-
"SETS",
|
|
1357
|
-
"SIMILAR",
|
|
1358
|
-
"SIZE",
|
|
1359
|
-
"SOME",
|
|
1360
|
-
"SPACE",
|
|
1361
|
-
"SPECIFIC",
|
|
1362
|
-
"SPECIFICTYPE",
|
|
1363
|
-
"SQL",
|
|
1364
|
-
"SQLCODE",
|
|
1365
|
-
"SQLERROR",
|
|
1366
|
-
"SQLEXCEPTION",
|
|
1367
|
-
"SQLSTATE",
|
|
1368
|
-
"SQLWARNING",
|
|
1369
|
-
"STATE",
|
|
1370
|
-
"STATIC",
|
|
1371
|
-
"STRUCTURE",
|
|
1372
|
-
"SYSTEM_USER",
|
|
1373
|
-
"TABLE",
|
|
1374
|
-
"TERMINATE",
|
|
1375
|
-
"THAN",
|
|
1376
|
-
"THEN",
|
|
1377
|
-
"TIMESTAMP",
|
|
1378
|
-
"TIMEZONE_HOUR",
|
|
1379
|
-
"TIMEZONE_MINUTE",
|
|
1380
|
-
"TO",
|
|
1381
|
-
"TRAILING",
|
|
1382
|
-
"TRANSLATION",
|
|
1383
|
-
"TRUE",
|
|
1384
|
-
"UNDER",
|
|
1385
|
-
"UNION",
|
|
1386
|
-
"UNIQUE",
|
|
1387
|
-
"UNNEST",
|
|
1388
|
-
"USER",
|
|
1389
|
-
"USING",
|
|
1390
|
-
"VALUE",
|
|
1391
|
-
"VARIABLE",
|
|
1392
|
-
"VERBOSE",
|
|
1393
|
-
"WHEN",
|
|
1394
|
-
"WHENEVER",
|
|
1395
|
-
"WHERE",
|
|
1396
|
-
]
|