velocity-python 0.0.131__py3-none-any.whl → 0.0.132__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.

Files changed (35) hide show
  1. velocity/__init__.py +1 -1
  2. velocity/db/servers/base/__init__.py +9 -0
  3. velocity/db/servers/base/initializer.py +69 -0
  4. velocity/db/servers/base/operators.py +98 -0
  5. velocity/db/servers/base/sql.py +503 -0
  6. velocity/db/servers/base/types.py +135 -0
  7. velocity/db/servers/mysql/__init__.py +64 -0
  8. velocity/db/servers/mysql/operators.py +54 -0
  9. velocity/db/servers/{mysql_reserved.py → mysql/reserved.py} +2 -14
  10. velocity/db/servers/mysql/sql.py +569 -0
  11. velocity/db/servers/mysql/types.py +107 -0
  12. velocity/db/servers/postgres/__init__.py +40 -0
  13. velocity/db/servers/postgres/operators.py +34 -0
  14. velocity/db/servers/postgres/sql.py +4 -3
  15. velocity/db/servers/postgres/types.py +88 -2
  16. velocity/db/servers/sqlite/__init__.py +52 -0
  17. velocity/db/servers/sqlite/operators.py +52 -0
  18. velocity/db/servers/sqlite/reserved.py +20 -0
  19. velocity/db/servers/sqlite/sql.py +530 -0
  20. velocity/db/servers/sqlite/types.py +92 -0
  21. velocity/db/servers/sqlserver/__init__.py +64 -0
  22. velocity/db/servers/sqlserver/operators.py +47 -0
  23. velocity/db/servers/sqlserver/reserved.py +32 -0
  24. velocity/db/servers/sqlserver/sql.py +625 -0
  25. velocity/db/servers/sqlserver/types.py +114 -0
  26. {velocity_python-0.0.131.dist-info → velocity_python-0.0.132.dist-info}/METADATA +1 -1
  27. {velocity_python-0.0.131.dist-info → velocity_python-0.0.132.dist-info}/RECORD +30 -16
  28. velocity/db/servers/mysql.py +0 -640
  29. velocity/db/servers/sqlite.py +0 -968
  30. velocity/db/servers/sqlite_reserved.py +0 -208
  31. velocity/db/servers/sqlserver.py +0 -921
  32. velocity/db/servers/sqlserver_reserved.py +0 -314
  33. {velocity_python-0.0.131.dist-info → velocity_python-0.0.132.dist-info}/WHEEL +0 -0
  34. {velocity_python-0.0.131.dist-info → velocity_python-0.0.132.dist-info}/licenses/LICENSE +0 -0
  35. {velocity_python-0.0.131.dist-info → velocity_python-0.0.132.dist-info}/top_level.txt +0 -0
@@ -1,640 +0,0 @@
1
- import re
2
- import hashlib
3
- import decimal
4
- import datetime
5
- from velocity.db import exceptions
6
- from .mysql_reserved import reserved_words
7
-
8
-
9
- def initialize(config):
10
- from velocity.db.core.engine import Engine
11
- import mysql.connector
12
-
13
- return Engine(mysql.connector, config, SQL)
14
-
15
-
16
- def make_where(where, sql, vals, is_join=False):
17
- if not where:
18
- return
19
- sql.append("WHERE")
20
- if isinstance(where, str):
21
- sql.append(where)
22
- return
23
- if isinstance(where, dict):
24
- where = where.items()
25
- if isinstance(where, list):
26
- join = ""
27
- for key, val in where:
28
- if join:
29
- sql.append(join)
30
- if is_join:
31
- if "." not in key:
32
- key = "A." + key
33
- if val is None:
34
- if "!" in key:
35
- key = key.replace("!", "")
36
- sql.append("{} is not NULL".format(quote(key.lower())))
37
- else:
38
- sql.append("{} is NULL".format(quote(key.lower())))
39
- elif isinstance(val, (list, tuple)):
40
- if "!" in key:
41
- key = key.replace("!", "")
42
- sql.append("{} not in %s".format(quote(key.lower())))
43
- vals.append(tuple(val))
44
- else:
45
- sql.append("{} in %s".format(quote(key.lower())))
46
- vals.append(tuple(val))
47
- else:
48
- if "<>" in key:
49
- key = key.replace("<>", "")
50
- op = "<>"
51
- elif "!=" in key:
52
- key = key.replace("!=", "")
53
- op = "<>"
54
- elif "!%" in key:
55
- key = key.replace("!%", "")
56
- op = "not like"
57
- elif "%%" in key:
58
- key = key.replace("%%", "")
59
- op = "%"
60
- elif "%>" in key:
61
- key = key.replace("%>", "")
62
- op = "%>"
63
- elif "<%" in key:
64
- key = key.replace("<%", "")
65
- op = "<%"
66
- elif "==" in key:
67
- key = key.replace("==", "")
68
- op = "="
69
- elif "<=" in key:
70
- key = key.replace("<=", "")
71
- op = "<="
72
- elif ">=" in key:
73
- key = key.replace(">=", "")
74
- op = ">="
75
- elif "<" in key:
76
- key = key.replace("<", "")
77
- op = "<"
78
- elif ">" in key:
79
- key = key.replace(">", "")
80
- op = ">"
81
- elif "%" in key:
82
- key = key.replace("%", "")
83
- op = "like"
84
- elif "!" in key:
85
- key = key.replace("!", "")
86
- op = "<>"
87
- elif "=" in key:
88
- key = key.replace("=", "")
89
- op = "="
90
- else:
91
- op = "="
92
- if isinstance(val, str) and val[:2] == "@@":
93
- sql.append("{} {} {}".format(quote(key.lower()), op, val[2:]))
94
- else:
95
- if "like" in op:
96
- sql.append(
97
- "lower({}) {} lower(%s)".format(quote(key.lower()), op)
98
- )
99
- else:
100
- sql.append("{} {} %s".format(quote(key.lower()), op))
101
- vals.append(val)
102
- join = "AND"
103
-
104
-
105
- def quote(data):
106
- if isinstance(data, list):
107
- new = []
108
- for item in data:
109
- new.append(quote(item))
110
- return new
111
- else:
112
- parts = data.split(".")
113
- new = []
114
- for part in parts:
115
- if "`" in part:
116
- new.append(part)
117
- elif part.upper() in reserved_words:
118
- new.append("`" + part + "`")
119
- elif re.findall("[/]", part):
120
- new.append("`" + part + "`")
121
- else:
122
- new.append(part)
123
- return ".".join(new)
124
-
125
-
126
- class SQL:
127
- server = "MySQL"
128
- type_column_identifier = "DATA_TYPE"
129
- is_nullable = "IS_NULLABLE"
130
-
131
- default_schema = "mydb"
132
-
133
- ApplicationErrorCodes = []
134
-
135
- DatabaseMissingErrorCodes = []
136
- TableMissingErrorCodes = [1146]
137
- ColumnMissingErrorCodes = [1054]
138
- ForeignKeyMissingErrorCodes = []
139
-
140
- ConnectionErrorCodes = []
141
- DuplicateKeyErrorCodes = [] # Handled in regex check.
142
- RetryTransactionCodes = []
143
- TruncationErrorCodes = []
144
- LockTimeoutErrorCodes = []
145
- DatabaseObjectExistsErrorCodes = []
146
-
147
- def get_error(self, e):
148
- error_code, error_mesg = e.args[:2]
149
- return error_code, error_mesg
150
-
151
- @classmethod
152
- def __has_pointer(cls, columns):
153
- if columns:
154
- if isinstance(columns, list):
155
- columns = ",".join(columns)
156
- if ">" in columns:
157
- return True
158
- return False
159
-
160
- @classmethod
161
- def alter_add(cls, table, columns, null_allowed=True):
162
- sql = []
163
- null = "NOT NULL" if not null_allowed else ""
164
- if isinstance(columns, dict):
165
- for key, val in columns.items():
166
- key = re.sub("<>!=%", "", key.lower())
167
- sql.append(
168
- "ALTER TABLE {} ADD {} {} {};".format(
169
- quote(table), quote(key), cls.get_type(val), null
170
- )
171
- )
172
- return "\n\t".join(sql), tuple()
173
-
174
- @classmethod
175
- def columns(cls, name):
176
- if "." in name:
177
- return """
178
- SELECT COLUMN_NAME
179
- FROM INFORMATION_SCHEMA.columns
180
- WHERE TABLE_SCHEMA = %s
181
- AND TABLE_NAME = %s
182
- """, tuple(
183
- name.split(".")
184
- )
185
- else:
186
- return """
187
- SELECT COLUMN_NAME
188
- FROM INFORMATION_SCHEMA.columns
189
- WHERE TABLE_SCHEMA = %s
190
- """, tuple(
191
- [
192
- name,
193
- ]
194
- )
195
-
196
- @classmethod
197
- def create_foreign_key(
198
- cls, table, columns, key_to_table, key_to_columns, name=None, schema=None
199
- ):
200
- if "." not in table and schema:
201
- if schema is None:
202
- schema = cls.default_schema
203
- table = "{}.{}".format(schema, table)
204
- if isinstance(key_to_columns, str):
205
- key_to_columns = [key_to_columns]
206
- if isinstance(columns, str):
207
- columns = [columns]
208
- if not name:
209
- m = hashlib.md5()
210
- m.update(table)
211
- m.update(" ".join(columns))
212
- m.update(key_to_table)
213
- m.update(" ".join(key_to_columns))
214
- name = "FK_" + m.hexdigest()
215
- sql = "ALTER TABLE {} ADD CONSTRAINT {} FOREIGN KEY ({}) REFERENCES {} ({}) ON DELETE CASCADE ON UPDATE CASCADE;".format(
216
- table, name, ",".join(columns), key_to_table, ",".join(key_to_columns)
217
- )
218
-
219
- return sql, tuple()
220
-
221
- @classmethod
222
- def create_index(
223
- cls,
224
- table=None,
225
- columns=None,
226
- unique=False,
227
- direction=None,
228
- where=None,
229
- name=None,
230
- schema=None,
231
- trigram=None,
232
- tbl=None,
233
- ):
234
- if "." not in table and schema:
235
- table = "{}.{}".format(schema, table)
236
- if isinstance(columns, (list, set)):
237
- columns = ",".join([quote(c.lower()) for c in sorted(columns)])
238
- else:
239
- columns = quote(columns)
240
- sql = ["CREATE"]
241
- if unique:
242
- sql.append("UNIQUE")
243
- sql.append("INDEX")
244
- tablename = quote(table)
245
- if not name:
246
- name = re.sub(r"\([^)]*\)", "", columns.replace(",", "_"))
247
- sql.append("IDX__{}__{}".format(table.replace(".", "_"), name))
248
- sql.append("ON")
249
- sql.append(tablename)
250
- sql.append("(")
251
- sql.append(columns)
252
- sql.append(")")
253
- return " ".join(sql), tuple()
254
-
255
- @classmethod
256
- def create_table(cls, name, columns={}, drop=False):
257
- sql = []
258
- if drop:
259
- sql.append(cls.drop_table(name))
260
- sql.append(
261
- """
262
- CREATE TABLE {0} (
263
- sys_id SERIAL PRIMARY KEY AUTO_INCREMENT,
264
- sys_modified TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
265
- sys_created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
266
- )ENGINE=InnoDB AUTO_INCREMENT=1000;
267
- """.format(
268
- quote(name)
269
- )
270
- )
271
-
272
- for key, val in columns.items():
273
- key = re.sub("<>!=%", "", key.lower())
274
- if key in ["sys_id", "sys_created", "sys_modified"]:
275
- continue
276
- sql.append(
277
- "ALTER TABLE {} ADD COLUMN {} {};".format(
278
- quote(name), quote(key), cls.get_type(val)
279
- )
280
- )
281
- return "\n\t".join(sql), tuple()
282
-
283
- @classmethod
284
- def delete(cls, table, where):
285
- sql = ["DELETE FROM {}".format(table)]
286
- vals = []
287
- make_where(where, sql, vals)
288
- return " ".join(sql), tuple(vals)
289
-
290
- @classmethod
291
- def drop_table(cls, name):
292
- return "DROP TABLE IF EXISTS %s CASCADE;" % quote(name), tuple()
293
-
294
- @classmethod
295
- def foreign_key_info(cls, table=None, column=None, schema=None):
296
- if "." in table:
297
- schema, table = table.split(".")
298
-
299
- sql = [
300
- """
301
- SELECT
302
- TABLE_NAME AS FK_TABLE_NAME
303
- ,COLUMN_NAME AS FK_COLUMN_NAME
304
- ,CONSTRAINT_NAME AS REFERENCED_CONSTRAINT_NAME
305
- ,REFERENCED_TABLE_NAME
306
- ,REFERENCED_COLUMN_NAME
307
- FROM
308
- INFORMATION_SCHEMA.KEY_COLUMN_USAGE
309
- """
310
- ]
311
- vals = []
312
- where = {}
313
- if schema:
314
- where["LOWER(REFERENCED_TABLE_SCHEMA)"] = schema.lower()
315
- if table:
316
- where["LOWER(REFERENCED_TABLE_NAME)"] = table.lower()
317
- if column:
318
- where["LOWER(REFERENCED_COLUMN_NAME)"] = column.lower()
319
- make_where(where, sql, vals)
320
- return " ".join(sql), tuple(vals)
321
-
322
- @classmethod
323
- def get_type(cls, v):
324
- if isinstance(v, str):
325
- if v[:2] == "@@":
326
- return v[2:] or cls.TYPES.TEXT
327
- elif isinstance(v, (str, bytes)) or v is str or v is bytes:
328
- return cls.TYPES.TEXT
329
- elif isinstance(v, bool) or v is bool:
330
- return cls.TYPES.BOOLEAN
331
- elif isinstance(v, int) or v is int:
332
- if v is int:
333
- return cls.TYPES.INTEGER
334
- if v > 2147483647 or v < -2147483648:
335
- return cls.TYPES.BIGINT
336
- else:
337
- return cls.TYPES.INTEGER
338
- elif isinstance(v, float) or v is float:
339
- return cls.TYPES.NUMERIC + "(19, 6)"
340
- elif isinstance(v, decimal.Decimal) or v is decimal.Decimal:
341
- return cls.TYPES.NUMERIC + "(19, 6)"
342
- elif isinstance(v, datetime.datetime) or v is datetime.datetime:
343
- return cls.TYPES.DATETIME
344
- elif isinstance(v, datetime.date) or v is datetime.date:
345
- return cls.TYPES.DATE
346
- elif isinstance(v, datetime.time) or v is datetime.time:
347
- return cls.TYPES.TIME
348
- elif isinstance(v, datetime.timedelta) or v is datetime.timedelta:
349
- return cls.TYPES.INTERVAL
350
- elif isinstance(v, bytearray) or v is bytearray:
351
- return cls.TYPES.BINARY
352
- # Everything else defaults to TEXT, incl. None
353
- return cls.TYPES.TEXT
354
-
355
- @classmethod
356
- def insert(cls, table, data):
357
- keys = []
358
- vals = []
359
- args = []
360
- for key, val in data.items():
361
- keys.append(quote(key.lower()))
362
- if isinstance(val, str) and len(val) > 2 and val[:2] == "@@":
363
- vals.append(val[2:])
364
- else:
365
- vals.append("%s")
366
- args.append(val)
367
-
368
- sql = ["INSERT INTO"]
369
- sql.append(quote(table))
370
- sql.append("(")
371
- sql.append(",".join(keys))
372
- sql.append(")")
373
- sql.append("VALUES")
374
- sql.append("(")
375
- sql.append(",".join(vals))
376
- sql.append(")")
377
- sql = " ".join(sql)
378
- return sql, tuple(args)
379
-
380
- @classmethod
381
- def last_id(cls, table):
382
- return "SELECT LAST_INSERT_ID();", tuple()
383
-
384
- @classmethod
385
- def create_savepoint(cls, sp):
386
- return None, tuple()
387
-
388
- @classmethod
389
- def rollback_savepoint(cls, sp):
390
- return None, tuple()
391
-
392
- @classmethod
393
- def release_savepoint(cls, sp):
394
- return None, tuple()
395
-
396
- @classmethod
397
- def create_view(cls, name, query, temp=False, silent=True):
398
- sql = ["CREATE"]
399
- if silent:
400
- sql.append("OR REPLACE")
401
- if temp:
402
- sql.append("TEMPORARY")
403
- sql.append("VIEW")
404
- sql.append(name)
405
- sql.append("AS")
406
- sql.append(query)
407
- return " ".join(sql), tuple()
408
-
409
- @classmethod
410
- def drop_view(cls, name, silent=True):
411
- sql = ["DROP VIEW"]
412
- if silent:
413
- sql.append("IF EXISTS")
414
- sql.append(name)
415
- return " ".join(sql), tuple()
416
-
417
- @classmethod
418
- def rename_column(cls, table, orig, new):
419
- return (
420
- "ALTER TABLE {} RENAME COLUMN {} TO {};".format(
421
- quote(table), quote(orig), quote(new)
422
- ),
423
- tuple(),
424
- )
425
-
426
- @classmethod
427
- def select(
428
- cls,
429
- columns=None,
430
- table=None,
431
- where=None,
432
- orderby=None,
433
- groupby=None,
434
- having=None,
435
- start=None,
436
- qty=None,
437
- tbl=None,
438
- ):
439
- is_join = False
440
-
441
- if isinstance(columns, str) and "distinct" in columns.lower():
442
- sql = [
443
- "SELECT",
444
- columns,
445
- "FROM",
446
- quote(table),
447
- ]
448
- elif cls.__has_pointer(columns):
449
- is_join = True
450
- if isinstance(columns, str):
451
- columns = columns.split(",")
452
- letter = 65
453
- tables = {table: chr(letter)}
454
- letter += 1
455
- __select = []
456
- __from = ["{} AS {}".format(quote(table), tables.get(table))]
457
- __left_join = []
458
-
459
- for column in columns:
460
- if ">" in column:
461
- is_join = True
462
- parts = column.split(">")
463
- foreign = tbl.foreign_key_info(parts[0])
464
- if not foreign:
465
- raise exceptions.DbApplicationError("Foreign key not defined")
466
- ref_table = foreign["referenced_table_name"]
467
- ref_schema = foreign["referenced_table_schema"]
468
- ref_column = foreign["referenced_column_name"]
469
- lookup = "{}:{}".format(ref_table, parts[0])
470
- if tables.has_key(lookup):
471
- __select.append(
472
- '{}."{}" as "{}"'.format(
473
- tables.get(lookup), parts[1], "_".join(parts)
474
- )
475
- )
476
- else:
477
- tables[lookup] = chr(letter)
478
- letter += 1
479
- __select.append(
480
- '{}."{}" as "{}"'.format(
481
- tables.get(lookup), parts[1], "_".join(parts)
482
- )
483
- )
484
- __left_join.append(
485
- 'LEFT OUTER JOIN "{}"."{}" AS {}'.format(
486
- ref_schema, ref_table, tables.get(lookup)
487
- )
488
- )
489
- __left_join.append(
490
- 'ON {}."{}" = {}."{}"'.format(
491
- tables.get(table),
492
- parts[0],
493
- tables.get(lookup),
494
- ref_column,
495
- )
496
- )
497
- if orderby and column in orderby:
498
- orderby = orderby.replace(
499
- column, "{}.{}".format(tables.get(lookup), parts[1])
500
- )
501
-
502
- else:
503
- if "(" in column:
504
- __select.append(column)
505
- else:
506
- __select.append("{}.{}".format(tables.get(table), column))
507
- sql = ["SELECT"]
508
- sql.append(",".join(__select))
509
- sql.append("FROM")
510
- sql.extend(__from)
511
- sql.extend(__left_join)
512
- else:
513
- if columns:
514
- if isinstance(columns, str):
515
- columns = columns.split(",")
516
- if isinstance(columns, list):
517
- columns = quote(columns)
518
- columns = ",".join(columns)
519
- else:
520
- columns = "*"
521
- sql = [
522
- "SELECT",
523
- columns,
524
- "FROM",
525
- quote(table),
526
- ]
527
- vals = []
528
- make_where(where, sql, vals, is_join)
529
- if groupby:
530
- sql.append("GROUP BY")
531
- if isinstance(groupby, (list, tuple)):
532
- groupby = ",".join(groupby)
533
- sql.append(groupby)
534
- if having:
535
- sql.append("HAVING")
536
- if isinstance(having, (list, tuple)):
537
- having = ",".join(having)
538
- sql.append(having)
539
- if orderby:
540
- sql.append("ORDER BY")
541
- if isinstance(orderby, (list, tuple)):
542
- orderby = ",".join(orderby)
543
- sql.append(orderby)
544
- if start and qty:
545
- sql.append("OFFSET {} ROWS FETCH NEXT {} ROWS ONLY".format(start, qty))
546
- elif start:
547
- sql.append("OFFSET {} ROWS".format(start))
548
- elif qty:
549
- sql.append("FETCH NEXT {} ROWS ONLY".format(qty))
550
- sql = " ".join(sql)
551
- return sql, tuple(vals)
552
-
553
- @classmethod
554
- def update(cls, table, data, pk):
555
- sql = ["UPDATE"]
556
- sql.append(quote(table))
557
- sql.append("SET")
558
- vals = []
559
- join = ""
560
- for key in data.keys():
561
- val = data[key]
562
- if join:
563
- sql.append(join)
564
- if isinstance(val, str) and val[:2] == "@@":
565
- sql.append("{} = {}".format(quote(key.lower()), val[2:]))
566
- else:
567
- sql.append("{} = %s".format(quote(key.lower())))
568
- vals.append(val)
569
- join = ","
570
- make_where(pk, sql, vals)
571
- return " ".join(sql), tuple(vals)
572
-
573
- @classmethod
574
- def upsert(cls, table, data, pk):
575
- keys = []
576
- vals = []
577
- args = []
578
- for key, val in data.items():
579
- keys.append(quote(key.lower()))
580
- if isinstance(val, str) and len(val) > 2 and val[:2] == "@@":
581
- vals.append(val[2:])
582
- else:
583
- vals.append("%s")
584
- args.append(val)
585
- for key, val in pk.items():
586
- keys.append(quote(key.lower()))
587
- if isinstance(val, str) and len(val) > 2 and val[:2] == "@@":
588
- vals.append(val[2:])
589
- else:
590
- vals.append("%s")
591
- args.append(val)
592
- sql = ["INSERT INTO"]
593
- sql.append(quote(table))
594
- sql.append("(")
595
- sql.append(",".join(keys))
596
- sql.append(")")
597
- sql.append("VALUES")
598
- sql.append("(")
599
- sql.append(",".join(vals))
600
- sql.append(")")
601
- sql.append("ON DUPLICATE KEY UPDATE")
602
- join = ""
603
- for key in data.keys():
604
- val = data[key]
605
- if join:
606
- sql.append(join)
607
- if isinstance(val, str) and val[:2] == "@@":
608
- sql.append("{} = {}".format(quote(key.lower()), val[2:]))
609
- else:
610
- sql.append("{} = %s".format(quote(key.lower())))
611
- args.append(val)
612
- join = ","
613
- return " ".join(sql), tuple(args)
614
-
615
- @classmethod
616
- def views(cls, system=False):
617
- if system:
618
- return (
619
- "SELECT TABLE_SCHEMA, TABLE_NAME FROM information_schema.tables WHERE TABLE_TYPE LIKE 'VIEW';",
620
- tuple(),
621
- )
622
- else:
623
- return (
624
- "SELECT TABLE_SCHEMA, TABLE_NAME FROM information_schema.tables WHERE TABLE_TYPE LIKE 'VIEW';",
625
- tuple(),
626
- )
627
-
628
- class TYPES(object):
629
- TEXT = "TEXT"
630
- INTEGER = "INTEGER"
631
- NUMERIC = "NUMERIC"
632
- DATETIME = "DATETIME"
633
- TIMESTAMP = "TIMESTAMP"
634
- DATE = "DATE"
635
- TIME = "TIME"
636
- BIGINT = "BIGINT"
637
- SMALLINT = "SMALLINT"
638
- BOOLEAN = "BIT"
639
- BINARY = "BLOB"
640
- INTERVAL = "INTERVAL"