velocity-python 0.0.27__py3-none-any.whl → 0.0.29__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 +60 -41
- velocity/db/core/row.py +33 -21
- velocity/db/core/table.py +318 -169
- velocity/db/core/transaction.py +54 -31
- velocity/db/servers/postgres.py +810 -689
- {velocity_python-0.0.27.dist-info → velocity_python-0.0.29.dist-info}/METADATA +1 -1
- {velocity_python-0.0.27.dist-info → velocity_python-0.0.29.dist-info}/RECORD +11 -12
- velocity/db/servers/sql.py +0 -558
- {velocity_python-0.0.27.dist-info → velocity_python-0.0.29.dist-info}/LICENSE +0 -0
- {velocity_python-0.0.27.dist-info → velocity_python-0.0.29.dist-info}/WHEEL +0 -0
- {velocity_python-0.0.27.dist-info → velocity_python-0.0.29.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: velocity-python
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.29
|
|
4
4
|
Summary: A rapid application development library for interfacing with data storage
|
|
5
5
|
Author-email: Paul Perez <pperez@codeclubs.org>
|
|
6
6
|
Project-URL: Homepage, https://codeclubs.org/projects/velocity
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
velocity/__init__.py,sha256=
|
|
1
|
+
velocity/__init__.py,sha256=iVTlJ417T2VFb7sCoHxNQyxcJyZcz24nEWWJO8V_STU,88
|
|
2
2
|
velocity/aws/__init__.py,sha256=ukvGrS0R8p6HtYajexOAJ7Kn9CJNlx6yb58W7o-JrAg,620
|
|
3
3
|
velocity/aws/handlers/__init__.py,sha256=xnpFZJVlC2uoeeFW4zuPST8wA8ajaQDky5Y6iXZzi3A,172
|
|
4
4
|
velocity/aws/handlers/context.py,sha256=UIjNR83y2NSIyK8HMPX8t5tpJHFNabiZvNgmmdQL3HA,1822
|
|
@@ -9,18 +9,17 @@ velocity/db/__init__.py,sha256=vrn2AFNAKaqTdnPwLFS0OcREcCtzUCOodlmH54U7ADg,200
|
|
|
9
9
|
velocity/db/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
10
|
velocity/db/core/column.py,sha256=vB7dCrcIWFvRG1fgyzDQnEu7j_0KYxUuDSTCWVCYlPc,6153
|
|
11
11
|
velocity/db/core/database.py,sha256=i1hzCkte6onEInH8ZtTI7D2Xj8q3uwU-uL3wn7Ix5oU,1860
|
|
12
|
-
velocity/db/core/decorators.py,sha256=
|
|
12
|
+
velocity/db/core/decorators.py,sha256=q3_0j06vZF9J-pPcLjsR2wftp4iXjlGgJ2l70WdtbUo,3271
|
|
13
13
|
velocity/db/core/engine.py,sha256=94wVlnapVVmJCRp6NPGrwnqSxCDlC-848Vu42p9RtCs,14643
|
|
14
14
|
velocity/db/core/exceptions.py,sha256=3ZyRq-idtCdtOGyT4rbNsmEyjfP75BMBq9y-Phakxow,684
|
|
15
15
|
velocity/db/core/result.py,sha256=keE-SKn4Uw08uoiA_8FdaMzBfiaAIxidQEEsl3TM86U,4945
|
|
16
|
-
velocity/db/core/row.py,sha256=
|
|
16
|
+
velocity/db/core/row.py,sha256=AHopXrrQUp5dCXEMLEDm0iAhswKDtMUdBxjTtPQ7Udk,5659
|
|
17
17
|
velocity/db/core/sequence.py,sha256=6sUaHJ29ItthNYoAvQy0SMAZURRdDS8bomnmQspJaT4,1083
|
|
18
|
-
velocity/db/core/table.py,sha256=
|
|
19
|
-
velocity/db/core/transaction.py,sha256=
|
|
18
|
+
velocity/db/core/table.py,sha256=d7KyIXAinBBzIqvxIZClJ8d-DGskPucruFiFFT4PtCM,19805
|
|
19
|
+
velocity/db/core/transaction.py,sha256=XeqGkgrleIqC8krrDcqVXWiBAjXx9z67ZecJNjELgiw,6641
|
|
20
20
|
velocity/db/servers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
21
|
velocity/db/servers/mysql.py,sha256=c0yUG00jvgnhLMJcV8BuOlTL7uGJ3uRPjJ0xVJingbk,21975
|
|
22
|
-
velocity/db/servers/postgres.py,sha256=
|
|
23
|
-
velocity/db/servers/sql.py,sha256=8yxljVYjMMY4weLCrugpLb7R3FEriHqamR-8lFaNfZg,21856
|
|
22
|
+
velocity/db/servers/postgres.py,sha256=aA4Fkz-PTo-Vi9kpDvWWMt2snv4r93PtQYDzgCg1XIs,42723
|
|
24
23
|
velocity/db/servers/sqlite.py,sha256=QVdr_ytvCuSSKVgcP_PI05yTU0gNyFRtTmH4XQlQVjQ,34047
|
|
25
24
|
velocity/db/servers/sqlserver.py,sha256=5kRNLNKbaszMww8JrlUvs2viSIb2hDZfn6nSvR52MEU,31593
|
|
26
25
|
velocity/misc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -33,8 +32,8 @@ velocity/misc/timer.py,sha256=wMbV-1yNXeCJo_UPi5sTSslu9hPzokLaIKgd98tyG_4,536
|
|
|
33
32
|
velocity/misc/conv/__init__.py,sha256=-caOuiqo0mzjP30Rh-3T0bSlt4M-SzJ4SPr2COk9wmg,39
|
|
34
33
|
velocity/misc/conv/iconv.py,sha256=V-PcpDXq7wCmyxZ3sXfzpmVH5Nc9OHScvMH26K7N3bI,4375
|
|
35
34
|
velocity/misc/conv/oconv.py,sha256=TGC6vTcOACtwp_Gpce33ZiVmgqBYQnwBcMNQ1MP6Qdc,4121
|
|
36
|
-
velocity_python-0.0.
|
|
37
|
-
velocity_python-0.0.
|
|
38
|
-
velocity_python-0.0.
|
|
39
|
-
velocity_python-0.0.
|
|
40
|
-
velocity_python-0.0.
|
|
35
|
+
velocity_python-0.0.29.dist-info/LICENSE,sha256=aoN245GG8s9oRUU89KNiGTU4_4OtnNmVi4hQeChg6rM,1076
|
|
36
|
+
velocity_python-0.0.29.dist-info/METADATA,sha256=waMEshl4l17tG_tx62zRXVypL1b5aSzjUls8q9JwFPM,8522
|
|
37
|
+
velocity_python-0.0.29.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
38
|
+
velocity_python-0.0.29.dist-info/top_level.txt,sha256=JW2vJPmodgdgSz7H6yoZvnxF8S3fTMIv-YJWCT1sNW0,9
|
|
39
|
+
velocity_python-0.0.29.dist-info/RECORD,,
|
velocity/db/servers/sql.py
DELETED
|
@@ -1,558 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import decimal
|
|
3
|
-
import datetime
|
|
4
|
-
import re
|
|
5
|
-
from velocity.db import exceptions
|
|
6
|
-
|
|
7
|
-
class Query(str):
|
|
8
|
-
pass
|
|
9
|
-
|
|
10
|
-
class SQL(object):
|
|
11
|
-
server = "Generic SQL"
|
|
12
|
-
type_column_identifier = 'data_type'
|
|
13
|
-
default_schema = 'schema'
|
|
14
|
-
lquote = '"'
|
|
15
|
-
rquote = '"'
|
|
16
|
-
|
|
17
|
-
DatabaseMissingErrorCodes = []
|
|
18
|
-
TableMissingErrorCodes = []
|
|
19
|
-
ColumnMissingErrorCodes = []
|
|
20
|
-
ForeignKeyMissingErrorCodes =[]
|
|
21
|
-
|
|
22
|
-
ConnectionErrorCodes = []
|
|
23
|
-
DuplicateKeyErrorCodes = []
|
|
24
|
-
RetryTransactionCodes = []
|
|
25
|
-
TruncationErrorCodes = []
|
|
26
|
-
LockTimeoutErrorCodes = []
|
|
27
|
-
DatabaseObjectExistsErrorCodes = []
|
|
28
|
-
|
|
29
|
-
@classmethod
|
|
30
|
-
def quote(self, data):
|
|
31
|
-
if isinstance(data, list):
|
|
32
|
-
new = []
|
|
33
|
-
for item in data:
|
|
34
|
-
new.append(self.quote(item))
|
|
35
|
-
return new
|
|
36
|
-
else:
|
|
37
|
-
parts = data.split('.')
|
|
38
|
-
new = []
|
|
39
|
-
for part in parts:
|
|
40
|
-
if self.lquote in part:
|
|
41
|
-
new.append(part)
|
|
42
|
-
elif part.upper() in reserved_words:
|
|
43
|
-
new.append(self.lquote+part+self.rquote)
|
|
44
|
-
elif re.findall('[/]',part):
|
|
45
|
-
new.append(self.lquote+part+self.rquote)
|
|
46
|
-
else:
|
|
47
|
-
new.append(part)
|
|
48
|
-
return '.'.join(new)
|
|
49
|
-
|
|
50
|
-
@classmethod
|
|
51
|
-
def version(cls):
|
|
52
|
-
return "select @@version"
|
|
53
|
-
|
|
54
|
-
@classmethod
|
|
55
|
-
def timestamp(cls):
|
|
56
|
-
return "select current_timestamp"
|
|
57
|
-
|
|
58
|
-
@classmethod
|
|
59
|
-
def user(cls):
|
|
60
|
-
return "select current_user"
|
|
61
|
-
|
|
62
|
-
@classmethod
|
|
63
|
-
def databases(cls):
|
|
64
|
-
return "select name from master.dbo.sysdatabases"
|
|
65
|
-
|
|
66
|
-
@classmethod
|
|
67
|
-
def schemas(cls):
|
|
68
|
-
return 'select schema_name from information_schema.schemata'
|
|
69
|
-
|
|
70
|
-
@classmethod
|
|
71
|
-
def current_schema(cls):
|
|
72
|
-
return 'select schema_name()'
|
|
73
|
-
|
|
74
|
-
@classmethod
|
|
75
|
-
def current_database(cls):
|
|
76
|
-
return 'select db_name() as current_database'
|
|
77
|
-
|
|
78
|
-
@classmethod
|
|
79
|
-
def tables(cls, system=False):
|
|
80
|
-
return """
|
|
81
|
-
select table_schema, table_name
|
|
82
|
-
from information_schema.tables
|
|
83
|
-
where table_type = 'BASE TABLE'
|
|
84
|
-
order by table_schema,table_name
|
|
85
|
-
"""
|
|
86
|
-
|
|
87
|
-
@classmethod
|
|
88
|
-
def views(cls, system=False):
|
|
89
|
-
return """
|
|
90
|
-
select table_schema, table_name
|
|
91
|
-
from information_schema.views
|
|
92
|
-
order by table_schema,table_name
|
|
93
|
-
"""
|
|
94
|
-
|
|
95
|
-
@classmethod
|
|
96
|
-
def __has_pointer(cls,columns):
|
|
97
|
-
if columns:
|
|
98
|
-
if isinstance(columns,list):
|
|
99
|
-
columns = ','.join(columns)
|
|
100
|
-
if '>' in columns:
|
|
101
|
-
return True
|
|
102
|
-
return False
|
|
103
|
-
|
|
104
|
-
@classmethod
|
|
105
|
-
def select(cls,columns=None,table=None,where=None,orderby=None,groupby=None,having=None,start=None,qty=None):
|
|
106
|
-
if cls.__has_pointer(columns):
|
|
107
|
-
if isinstance(columns,str):
|
|
108
|
-
columns = columns.split(',')
|
|
109
|
-
letter = 65
|
|
110
|
-
tables = {table: chr(letter)}
|
|
111
|
-
letter += 1
|
|
112
|
-
__select = []
|
|
113
|
-
__from = ['{} AS {}'.format(self.quote(table),tables.get(table))]
|
|
114
|
-
__left_join = []
|
|
115
|
-
|
|
116
|
-
for column in columns:
|
|
117
|
-
if '>' in column:
|
|
118
|
-
parts = column.split('>')
|
|
119
|
-
foreign = self.GetForeignKeyInfo(parts[0])
|
|
120
|
-
ref_table = foreign[0]['referenced_table_name']
|
|
121
|
-
ref_schema = foreign[0]['referenced_table_schema']
|
|
122
|
-
ref_column = foreign[0]['referenced_column_name']
|
|
123
|
-
lookup = "{}:{}".format(ref_table,parts[0])
|
|
124
|
-
if lookup in tables:
|
|
125
|
-
__select.append('{}."{}" as "{}"'.format(tables.get(lookup),parts[1],'_'.join(parts)))
|
|
126
|
-
else:
|
|
127
|
-
tables[lookup] = chr(letter)
|
|
128
|
-
letter += 1
|
|
129
|
-
__select.append('{}."{}" as "{}"'.format(tables.get(lookup),parts[1],'_'.join(parts)))
|
|
130
|
-
__left_join.append('LEFT OUTER JOIN "{}"."{}" AS {}'.format(ref_schema,ref_table,tables.get(lookup)))
|
|
131
|
-
__left_join.append('ON {}."{}" = {}."{}"'.format(
|
|
132
|
-
tables.get(table),
|
|
133
|
-
parts[0],
|
|
134
|
-
tables.get(lookup),
|
|
135
|
-
ref_column
|
|
136
|
-
))
|
|
137
|
-
if orderby and column in orderby:
|
|
138
|
-
orderby = orderby.replace(column,"{}.{}".format(tables.get(lookup),parts[1]))
|
|
139
|
-
else:
|
|
140
|
-
if '(' in column:
|
|
141
|
-
__select.append(column)
|
|
142
|
-
else:
|
|
143
|
-
__select.append("{}.{}".format(tables.get(self.table),column))
|
|
144
|
-
sql = ['SELECT']
|
|
145
|
-
sql.append(','.join(__select))
|
|
146
|
-
sql.append('FROM')
|
|
147
|
-
sql.extend(__from)
|
|
148
|
-
sql.extend(__left_join)
|
|
149
|
-
else:
|
|
150
|
-
if columns:
|
|
151
|
-
if isinstance(columns,str):
|
|
152
|
-
columns = columns.split(',')
|
|
153
|
-
if isinstance(columns,list):
|
|
154
|
-
columns = self.quote(columns)
|
|
155
|
-
columns = ','.join(columns)
|
|
156
|
-
else:
|
|
157
|
-
columns = '*'
|
|
158
|
-
sql = [
|
|
159
|
-
'SELECT',
|
|
160
|
-
columns,
|
|
161
|
-
'FROM',
|
|
162
|
-
self.quote(table),
|
|
163
|
-
]
|
|
164
|
-
values = []
|
|
165
|
-
if where:
|
|
166
|
-
sql.append('WHERE')
|
|
167
|
-
if isinstance(where,dict):
|
|
168
|
-
join = ''
|
|
169
|
-
for key in sorted(where.keys()):
|
|
170
|
-
if join: sql.append(join)
|
|
171
|
-
if where[key] == None:
|
|
172
|
-
sql.append('{} is NULL'.format(self.quote(key.lower())))
|
|
173
|
-
else:
|
|
174
|
-
sql.append('{} = %s'.format(self.quote(key.lower())))
|
|
175
|
-
values.append(where[key])
|
|
176
|
-
join = 'AND'
|
|
177
|
-
else:
|
|
178
|
-
sql.append(where)
|
|
179
|
-
if groupby:
|
|
180
|
-
sql.append('GROUP BY')
|
|
181
|
-
sql.append(groupby)
|
|
182
|
-
if having:
|
|
183
|
-
sql.append('HAVING')
|
|
184
|
-
sql.append(having)
|
|
185
|
-
if orderby:
|
|
186
|
-
sql.append('ORDER BY')
|
|
187
|
-
sql.append(orderby)
|
|
188
|
-
if start and qty:
|
|
189
|
-
sql.append('OFFSET {} ROWS FETCH NEXT {} ROWS ONLY'.format(start,qty))
|
|
190
|
-
elif start:
|
|
191
|
-
sql.append('OFFSET {} ROWS'.format(start))
|
|
192
|
-
elif qty:
|
|
193
|
-
sql.append('FETCH {} ROWS ONLY'.format(qty))
|
|
194
|
-
sql = ' '.join(sql)
|
|
195
|
-
values = cls.massage_values(values)
|
|
196
|
-
return sql, values
|
|
197
|
-
|
|
198
|
-
@classmethod
|
|
199
|
-
def create_database(cls, name):
|
|
200
|
-
return 'create database ' + name
|
|
201
|
-
|
|
202
|
-
@classmethod
|
|
203
|
-
def drop_database(cls, name):
|
|
204
|
-
return 'drop database ' + name
|
|
205
|
-
|
|
206
|
-
@classmethod
|
|
207
|
-
def create_table(cls, name, columns={}, drop=False):
|
|
208
|
-
if '.' in name:
|
|
209
|
-
fqtn = name
|
|
210
|
-
else:
|
|
211
|
-
fqtn = cls.default_schema + name
|
|
212
|
-
schema,table = fqtn.split('.')
|
|
213
|
-
name = fqtn.replace('.','_')
|
|
214
|
-
trigger = 'on_update_row_{0}'.format(name)
|
|
215
|
-
sql = []
|
|
216
|
-
sql.append('DECLARE @script1 nVarChar(MAX);')
|
|
217
|
-
sql.append('DECLARE @script2 nVarChar(MAX);')
|
|
218
|
-
if drop:
|
|
219
|
-
sql.append(cls.drop_table(fqtn))
|
|
220
|
-
sql.append("""
|
|
221
|
-
SET @script1 = '
|
|
222
|
-
CREATE TABLE {0} (
|
|
223
|
-
sys_id int identity(1000,1) primary key,
|
|
224
|
-
sys_modified datetime not null default(getdate()),
|
|
225
|
-
sys_created datetime not null default(getdate())
|
|
226
|
-
)'
|
|
227
|
-
""".format(fqtn, table, trigger))
|
|
228
|
-
sql.append("""
|
|
229
|
-
SET @script2 = '
|
|
230
|
-
CREATE TRIGGER {2}
|
|
231
|
-
ON {0}
|
|
232
|
-
AFTER UPDATE
|
|
233
|
-
AS
|
|
234
|
-
BEGIN
|
|
235
|
-
UPDATE t
|
|
236
|
-
SET t.sys_modified = CURRENT_TIMESTAMP,
|
|
237
|
-
t.sys_created = d.sys_created
|
|
238
|
-
FROM {0} AS t
|
|
239
|
-
INNER JOIN deleted AS d on t.sys_id=i.sys_id
|
|
240
|
-
END'
|
|
241
|
-
""".format(fqtn, table, trigger))
|
|
242
|
-
sql.append('EXEC (@script1);')
|
|
243
|
-
sql.append('EXEC (@script2);')
|
|
244
|
-
for key,val in columns.items():
|
|
245
|
-
sql.append("ALTER TABLE {} ADD COLUMN {} {};".format(fqtn,key,cls.get_type(val)))
|
|
246
|
-
return '\n\t'.join(sql)
|
|
247
|
-
|
|
248
|
-
@classmethod
|
|
249
|
-
def drop_table(cls, name):
|
|
250
|
-
return "IF OBJECT_ID('%s', 'U') IS NOT NULL DROP TABLE %s;" % (self.quote(name),self.quote(name))
|
|
251
|
-
|
|
252
|
-
@classmethod
|
|
253
|
-
def columns(cls, name):
|
|
254
|
-
if '.' in name:
|
|
255
|
-
return """
|
|
256
|
-
select column_name
|
|
257
|
-
from information_schema.columns
|
|
258
|
-
where UPPER(table_schema ) = UPPER(%s)
|
|
259
|
-
and UPPER(table_name) = UPPER(%s)
|
|
260
|
-
""", tuple(name.split('.'))
|
|
261
|
-
else:
|
|
262
|
-
return """
|
|
263
|
-
select column_name
|
|
264
|
-
from information_schema.columns
|
|
265
|
-
where UPPER(table_name) = UPPER(%s)
|
|
266
|
-
""", tuple([name])
|
|
267
|
-
|
|
268
|
-
@classmethod
|
|
269
|
-
def column_info(cls, table, name):
|
|
270
|
-
params = table.split('.')
|
|
271
|
-
params.append(name)
|
|
272
|
-
if '.' in table:
|
|
273
|
-
return """
|
|
274
|
-
select *
|
|
275
|
-
from information_schema.columns
|
|
276
|
-
where UPPER(table_schema ) = UPPER(%s)
|
|
277
|
-
and UPPER(table_name) = UPPER(%s)
|
|
278
|
-
and UPPER(column_name) = UPPER(%s)
|
|
279
|
-
""", tuple(params)
|
|
280
|
-
else:
|
|
281
|
-
return """
|
|
282
|
-
select *
|
|
283
|
-
from information_schema.columns
|
|
284
|
-
where UPPER(table_name) = UPPER(%s)
|
|
285
|
-
and UPPER(column_name) = UPPER(%s)
|
|
286
|
-
""", tuple(params)
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
@classmethod
|
|
290
|
-
def primary_keys(cls, table):
|
|
291
|
-
params = table.split('.')
|
|
292
|
-
if '.' in table:
|
|
293
|
-
return """
|
|
294
|
-
SELECT COLUMN_NAME
|
|
295
|
-
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
|
|
296
|
-
WHERE OBJECTPROPERTY(OBJECT_ID(CONSTRAINT_SCHEMA + '.' + QUOTENAME(CONSTRAINT_NAME)), 'IsPrimaryKey') = 1
|
|
297
|
-
AND UPPER(table_schema ) = UPPER(%s) AND UPPER(table_name) = UPPER(%s)
|
|
298
|
-
""", tuple(params)
|
|
299
|
-
else:
|
|
300
|
-
return """
|
|
301
|
-
SELECT COLUMN_NAME
|
|
302
|
-
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
|
|
303
|
-
WHERE OBJECTPROPERTY(OBJECT_ID(CONSTRAINT_SCHEMA + '.' + QUOTENAME(CONSTRAINT_NAME)), 'IsPrimaryKey') = 1
|
|
304
|
-
AND UPPER(table_name) = UPPER(%s)
|
|
305
|
-
""", tuple(params)
|
|
306
|
-
|
|
307
|
-
@classmethod
|
|
308
|
-
def xforeign_keys(cls, table):
|
|
309
|
-
params = table.split('.')
|
|
310
|
-
if '.' in table:
|
|
311
|
-
return """
|
|
312
|
-
SELECT COLUMN_NAME
|
|
313
|
-
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
|
|
314
|
-
WHERE OBJECTPROPERTY(OBJECT_ID(CONSTRAINT_SCHEMA + '.' + QUOTENAME(CONSTRAINT_NAME)), 'IsPrimaryKey') = 1
|
|
315
|
-
AND UPPER(table_schema ) = UPPER(%s) AND UPPER(table_name) = UPPER(%s)
|
|
316
|
-
""", tuple(params)
|
|
317
|
-
else:
|
|
318
|
-
return """
|
|
319
|
-
SELECT COLUMN_NAME
|
|
320
|
-
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
|
|
321
|
-
WHERE OBJECTPROPERTY(OBJECT_ID(CONSTRAINT_SCHEMA + '.' + QUOTENAME(CONSTRAINT_NAME)), 'IsPrimaryKey') = 1
|
|
322
|
-
AND UPPER(table_name) = UPPER(%s)
|
|
323
|
-
""", tuple(params)
|
|
324
|
-
|
|
325
|
-
@classmethod
|
|
326
|
-
def insert(cls, table, data={}):
|
|
327
|
-
keys = []
|
|
328
|
-
vals = []
|
|
329
|
-
args = []
|
|
330
|
-
for key,val in data.items():
|
|
331
|
-
keys.append(self.quote(key.lower()))
|
|
332
|
-
if isinstance(val,str) \
|
|
333
|
-
and len(val) > 2 \
|
|
334
|
-
and val[:2] == '@@':
|
|
335
|
-
vals.append(val[2:])
|
|
336
|
-
else:
|
|
337
|
-
vals.append('%s')
|
|
338
|
-
args.append(val)
|
|
339
|
-
|
|
340
|
-
sql = ['INSERT INTO']
|
|
341
|
-
sql.append(self.quote(table))
|
|
342
|
-
sql.append('(')
|
|
343
|
-
sql.append(','.join(keys))
|
|
344
|
-
sql.append(')')
|
|
345
|
-
sql.append('VALUES')
|
|
346
|
-
sql.append('(')
|
|
347
|
-
sql.append(','.join(vals))
|
|
348
|
-
sql.append(')')
|
|
349
|
-
sql = ' '.join(sql)
|
|
350
|
-
values = cls.massage_values(args)
|
|
351
|
-
return sql,values
|
|
352
|
-
|
|
353
|
-
@classmethod
|
|
354
|
-
def get_type(cls, v):
|
|
355
|
-
if isinstance(v, str):
|
|
356
|
-
if v[:2] == '@@':
|
|
357
|
-
return v[2:]
|
|
358
|
-
elif isinstance(v, str) \
|
|
359
|
-
or v is str:
|
|
360
|
-
return cls.TYPES.TEXT
|
|
361
|
-
elif isinstance(v, bool) \
|
|
362
|
-
or v is bool:
|
|
363
|
-
return cls.TYPES.BOOLEAN
|
|
364
|
-
elif isinstance(v, int) \
|
|
365
|
-
or v is int:
|
|
366
|
-
if v > 2147483647 or v < -2147483648:
|
|
367
|
-
return cls.TYPES.BIGINT
|
|
368
|
-
else:
|
|
369
|
-
return cls.TYPES.INTEGER
|
|
370
|
-
elif isinstance(v, float) \
|
|
371
|
-
or v is float:
|
|
372
|
-
return cls.TYPES.NUMERIC + '(19, 6)'
|
|
373
|
-
elif isinstance(v, decimal.Decimal) \
|
|
374
|
-
or v is decimal.Decimal:
|
|
375
|
-
return cls.TYPES.NUMERIC + '(19, 6)'
|
|
376
|
-
elif isinstance (v, datetime.datetime) \
|
|
377
|
-
or v is datetime.datetime:
|
|
378
|
-
return cls.TYPES.DATETIME
|
|
379
|
-
elif isinstance (v, datetime.date) \
|
|
380
|
-
or v is datetime.date:
|
|
381
|
-
return cls.TYPES.DATE
|
|
382
|
-
elif isinstance(v, datetime.time) \
|
|
383
|
-
or v is datetime.time:
|
|
384
|
-
return cls.TYPES.TIME
|
|
385
|
-
elif isinstance (v, bytes) \
|
|
386
|
-
or v is bytes:
|
|
387
|
-
return cls.TYPES.BINARY
|
|
388
|
-
# Everything else defaults to TEXT, incl. None
|
|
389
|
-
return cls.TYPES.TEXT
|
|
390
|
-
|
|
391
|
-
@classmethod
|
|
392
|
-
def py_type(cls, v):
|
|
393
|
-
v = str(v).upper()
|
|
394
|
-
if v == cls.TYPES.INTEGER:
|
|
395
|
-
return int
|
|
396
|
-
elif v in cls.TYPES.TEXT:
|
|
397
|
-
return str
|
|
398
|
-
elif v == cls.TYPES.BOOLEAN:
|
|
399
|
-
return bool
|
|
400
|
-
elif v == cls.TYPES.DATE:
|
|
401
|
-
return datetime.date
|
|
402
|
-
elif v == cls.TYPES.TIME:
|
|
403
|
-
return datetime.time
|
|
404
|
-
elif v == cls.TYPES.DATETIME:
|
|
405
|
-
return datetime.datetime
|
|
406
|
-
else:
|
|
407
|
-
raise Exception("unmapped type %s" % v)
|
|
408
|
-
|
|
409
|
-
@classmethod
|
|
410
|
-
def massage_data(cls,data):
|
|
411
|
-
"""
|
|
412
|
-
|
|
413
|
-
:param :
|
|
414
|
-
:param :
|
|
415
|
-
:param :
|
|
416
|
-
:returns:
|
|
417
|
-
"""
|
|
418
|
-
data = {key.lower():val for key,val in data.items()}
|
|
419
|
-
primaryKey = set(cls.GetPrimaryKeyColumnNames())
|
|
420
|
-
if not primaryKey:
|
|
421
|
-
if not cls.Exists():
|
|
422
|
-
raise exceptions.DbTableMissingError
|
|
423
|
-
dataKeys = set(data.keys()).intersection( primaryKey )
|
|
424
|
-
dataColumns = set(data.keys()).difference( primaryKey )
|
|
425
|
-
pk = {}
|
|
426
|
-
pk.update([(k,data[k]) for k in dataKeys])
|
|
427
|
-
d = {}
|
|
428
|
-
d.update([(k,data[k]) for k in dataColumns])
|
|
429
|
-
return d,pk
|
|
430
|
-
|
|
431
|
-
@classmethod
|
|
432
|
-
def massage_values(cls, values):
|
|
433
|
-
return tuple(values)
|
|
434
|
-
|
|
435
|
-
@classmethod
|
|
436
|
-
def alter_add(cls, table, columns, null_allowed=True):
|
|
437
|
-
sql = []
|
|
438
|
-
null = 'NOT NULL' if not null_allowed else ''
|
|
439
|
-
if isinstance(columns,dict):
|
|
440
|
-
for key,val in columns.items():
|
|
441
|
-
sql.append("ALTER TABLE {} ADD {} {} {};".format(self.quote(table), self.quote(key), cls.get_type(val), null))
|
|
442
|
-
return '\n\t'.join(sql)
|
|
443
|
-
|
|
444
|
-
@classmethod
|
|
445
|
-
def alter_drop(cls, table, columns):
|
|
446
|
-
sql = ["ALTER TABLE {} DROP COLUMN".format(self.quote(table))]
|
|
447
|
-
if isinstance(columns,dict):
|
|
448
|
-
for key,val in columns.items():
|
|
449
|
-
sql.append("{},".format(key))
|
|
450
|
-
if sql[-1][-1] == ',':
|
|
451
|
-
sql[-1] = sql[-1][:-1]
|
|
452
|
-
return '\n\t'.join(sql)
|
|
453
|
-
|
|
454
|
-
@classmethod
|
|
455
|
-
def alter_column_by_type(cls, table, column, value, null_allowed=True):
|
|
456
|
-
sql = ["ALTER TABLE {} ALTER COLUMN".format(self.quote(table))]
|
|
457
|
-
sql.append("{} {}".format(self.quote(column), cls.get_type(value)))
|
|
458
|
-
if not null_allowed:
|
|
459
|
-
sql.append('NOT NULL')
|
|
460
|
-
return '\n\t'.join(sql)
|
|
461
|
-
|
|
462
|
-
@classmethod
|
|
463
|
-
def alter_column_by_sql(cls, table, column, value):
|
|
464
|
-
sql = ["ALTER TABLE {} ALTER COLUMN".format(self.quote(table))]
|
|
465
|
-
sql.append("{} {}".format(self.quote(column), value))
|
|
466
|
-
return ' '.join(sql)
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
@classmethod
|
|
470
|
-
def rename_column(cls, table, name, new):
|
|
471
|
-
if '.' in table:
|
|
472
|
-
schema, table = table.split('.')
|
|
473
|
-
else:
|
|
474
|
-
schema = cls.default_schema
|
|
475
|
-
return "sp_rename '{}.{}.{}', '{}', 'COLUMN';".format(self.quote(schema), self.quote(table), self.quote(name), new)
|
|
476
|
-
|
|
477
|
-
@classmethod
|
|
478
|
-
def rename_table(cls, table, name, new):
|
|
479
|
-
if '.' in table:
|
|
480
|
-
schema, table = table.split('.')
|
|
481
|
-
else:
|
|
482
|
-
schema = cls.default_schema
|
|
483
|
-
return "sp_rename '{}.{}', '{}';".format(self.quote(schema), self.quote(name), new)
|
|
484
|
-
|
|
485
|
-
@classmethod
|
|
486
|
-
def create_savepoint(cls, sp):
|
|
487
|
-
return None #"SAVE TRANSACTION {}".format(sp)
|
|
488
|
-
|
|
489
|
-
@classmethod
|
|
490
|
-
def release_savepoint(cls, sp):
|
|
491
|
-
return None
|
|
492
|
-
|
|
493
|
-
@classmethod
|
|
494
|
-
def rollback_savepoint(cls, sp):
|
|
495
|
-
return None #"ROLLBACK TRANSACTION {}".format(sp)
|
|
496
|
-
|
|
497
|
-
@classmethod
|
|
498
|
-
def find_duplicates(cls, table, columns, key):
|
|
499
|
-
if isinstance(columns, str):
|
|
500
|
-
columns = [columns]
|
|
501
|
-
return """
|
|
502
|
-
SELECT {2}
|
|
503
|
-
FROM (SELECT {2},
|
|
504
|
-
ROW_NUMBER() OVER (partition BY {1} ORDER BY {2}) AS rnum
|
|
505
|
-
FROM {0}) t
|
|
506
|
-
WHERE t.rnum > 1;
|
|
507
|
-
""".format(table, ','.join(self.quote(columns)), key), tuple()
|
|
508
|
-
|
|
509
|
-
@classmethod
|
|
510
|
-
def delete_duplicates(cls, table, columns, key):
|
|
511
|
-
if isinstance(columns, str):
|
|
512
|
-
columns = [columns]
|
|
513
|
-
return """
|
|
514
|
-
DELETE FROM {0}
|
|
515
|
-
WHERE {2} IN (SELECT {2}
|
|
516
|
-
FROM (SELECT {2},
|
|
517
|
-
ROW_NUMBER() OVER (partition BY {1} ORDER BY {2}) AS rnum
|
|
518
|
-
FROM {0}) t
|
|
519
|
-
WHERE t.rnum > 1);
|
|
520
|
-
""".format(table, ','.join(self.quote(columns)), key), tuple()
|
|
521
|
-
|
|
522
|
-
@classmethod
|
|
523
|
-
def delete(cls, table, where):
|
|
524
|
-
sql = ['DELETE FROM {}'.format(table)]
|
|
525
|
-
sql.append('WHERE')
|
|
526
|
-
values = []
|
|
527
|
-
if isinstance(where,dict):
|
|
528
|
-
join = ''
|
|
529
|
-
for key in sorted(where.keys()):
|
|
530
|
-
if join: sql.append(join)
|
|
531
|
-
if where[key] == None:
|
|
532
|
-
sql.append('{} is NULL'.format(self.quote(key.lower())))
|
|
533
|
-
else:
|
|
534
|
-
sql.append('{} = %s'.format(self.quote(key.lower())))
|
|
535
|
-
values.append(where[key])
|
|
536
|
-
join = 'AND'
|
|
537
|
-
else:
|
|
538
|
-
sql.append(where)
|
|
539
|
-
return ' '.join(sql), tuple(values)
|
|
540
|
-
|
|
541
|
-
@classmethod
|
|
542
|
-
def truncate(cls, table):
|
|
543
|
-
return "truncate table {}".format(self.quote(table)), tuple()
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
class TYPES(object):
|
|
547
|
-
TEXT = 'VARCHAR(MAX)'
|
|
548
|
-
INTEGER = 'INT'
|
|
549
|
-
NUMERIC = 'NUMERIC'
|
|
550
|
-
DATETIME = 'DATETIME'
|
|
551
|
-
TIMESTAMP = 'DATETIME'
|
|
552
|
-
DATE = 'DATE'
|
|
553
|
-
TIME = 'TIME'
|
|
554
|
-
BIGINT = 'BIGINT'
|
|
555
|
-
BOOLEAN = 'BIT'
|
|
556
|
-
BINARY = 'VARBINARY(MAX)'
|
|
557
|
-
|
|
558
|
-
reserved_words = ['ABSOLUTE', 'ACTION', 'ADA', 'ADD', 'ALL', 'ALLOCATE', 'ALTER', 'AND', 'ANY', 'ARE', 'AS', 'ASC', 'ASSERTION', 'AT', 'AUTHORIZATION', 'AVG', 'BACKUP', 'BEGIN', 'BETWEEN', 'BIT', 'BIT_LENGTH', 'BOTH', 'BREAK', 'BROWSE', 'BULK', 'BY', 'CASCADE', 'CASCADED', 'CASE', 'CAST', 'CATALOG', 'CHAR', 'CHARACTER', 'CHARACTER_LENGTH', 'CHAR_LENGTH', 'CHECK', 'CHECKPOINT', 'CLOSE', 'CLUSTERED', 'COALESCE', 'COLLATE', 'COLLATION', 'COLUMN', 'COMMIT', 'COMPUTE', 'CONNECT', 'CONNECTION', 'CONSTRAINT', 'CONSTRAINTS', 'CONTAINS', 'CONTAINSTABLE', 'CONTINUE', 'CONVERT', 'CORRESPONDING', 'COUNT', 'CREATE', 'CROSS', 'CURRENT', 'CURRENT_DATE', 'CURRENT_TIME', 'CURRENT_TIMESTAMP', 'CURRENT_USER', 'CURSOR', 'DATABASE', 'DATE', 'DAY', 'DBCC', 'DEALLOCATE', 'DEC', 'DECIMAL', 'DECLARE', 'DEFAULT', 'DEFERRABLE', 'DEFERRED', 'DELETE', 'DENY', 'DESC', 'DESCRIBE', 'DESCRIPTOR', 'DIAGNOSTICS', 'DISCONNECT', 'DISK', 'DISTINCT', 'DISTRIBUTED', 'DOMAIN', 'DOUBLE', 'DROP', 'DUMP', 'ELSE', 'END', 'END-EXEC', 'ERRLVL', 'ESCAPE', 'EXCEPT', 'EXCEPTION', 'EXEC', 'EXECUTE', 'EXISTS', 'EXIT', 'EXTERNAL', 'EXTRACT', 'FALSE', 'FETCH', 'FILE', 'FILLFACTOR', 'FIRST', 'FLOAT', 'FOR', 'FOREIGN', 'FORTRAN', 'FOUND', 'FREETEXT', 'FREETEXTTABLE', 'FROM', 'FULL', 'FUNCTION', 'GET', 'GLOBAL', 'GO', 'GOTO', 'GRANT', 'GROUP', 'HAVING', 'HOLDLOCK', 'HOUR', 'IDENTITY', 'IDENTITYCOL', 'IDENTITY_INSERT', 'IF', 'IMMEDIATE', 'IN', 'INCLUDE', 'INDEX', 'INDICATOR', 'INITIALLY', 'INNER', 'INPUT', 'INSENSITIVE', 'INSERT', 'INT', 'INTEGER', 'INTERSECT', 'INTERVAL', 'INTO', 'IS', 'ISOLATION', 'JOIN', 'KEY', 'KILL', 'LANGUAGE', 'LAST', 'LEADING', 'LEFT', 'LEVEL', 'LIKE', 'LINENO', 'LOAD', 'LOCAL', 'LOWER', 'MATCH', 'MAX', 'MERGE', 'MIN', 'MINUTE', 'MODULE', 'MONTH', 'NAMES', 'NATIONAL', 'NATURAL', 'NCHAR', 'NEXT', 'NO', 'NOCHECK', 'NONCLUSTERED', 'NONE', 'NOT', 'NULL', 'NULLIF', 'NUMERIC', 'OCTET_LENGTH', 'OF', 'OFF', 'OFFSETS', 'ON', 'ONLY', 'OPEN', 'OPENDATASOURCE', 'OPENQUERY', 'OPENROWSET', 'OPENXML', 'OPTION', 'OR', 'ORDER', 'OUTER', 'OUTPUT', 'OVER', 'OVERLAPS', 'PAD', 'PARTIAL', 'PASCAL', 'PERCENT', 'PIVOT', 'PLAN', 'POSITION', 'PRECISION', 'PREPARE', 'PRESERVE', 'PRIMARY', 'PRINT', 'PRIOR', 'PRIVILEGES', 'PROC', 'PROCEDURE', 'PUBLIC', 'RAISERROR', 'READ', 'READTEXT', 'REAL', 'RECONFIGURE', 'REFERENCES', 'RELATIVE', 'REPLICATION', 'RESTORE', 'RESTRICT', 'RETURN', 'REVERT', 'REVOKE', 'RIGHT', 'ROLLBACK', 'ROWCOUNT', 'ROWGUIDCOL', 'ROWS', 'RULE', 'SAVE', 'SCHEMA', 'SCROLL', 'SECOND', 'SECTION', 'SECURITYAUDIT', 'SELECT', 'SEMANTICKEYPHRASETABLE', 'SEMANTICSIMILARITYDETAILSTABLE', 'SEMANTICSIMILARITYTABLE', 'SESSION', 'SESSION_USER', 'SET', 'SETUSER', 'SHUTDOWN', 'SIZE', 'SMALLINT', 'SOME', 'SPACE', 'SQL', 'SQLCA', 'SQLCODE', 'SQLERROR', 'SQLSTATE', 'SQLWARNING', 'STATISTICS', 'SUBSTRING', 'SUM', 'SYSTEM_USER', 'TABLE', 'TABLESAMPLE', 'TEMPORARY', 'TEXTSIZE', 'THEN', 'TIME', 'TIMESTAMP', 'TIMEZONE_HOUR', 'TIMEZONE_MINUTE', 'TO', 'TOP', 'TRAILING', 'TRAN', 'TRANSACTION', 'TRANSLATE', 'TRANSLATION', 'TRIGGER', 'TRIM', 'TRUE', 'TRUNCATE', 'TRY_CONVERT', 'TSEQUAL', 'UNION', 'UNIQUE', 'UNKNOWN', 'UNPIVOT', 'UPDATE', 'UPDATETEXT', 'UPPER', 'USAGE', 'USE', 'USER', 'USING', 'VALUE', 'VALUES', 'VARCHAR', 'VARYING', 'VIEW', 'WAITFOR', 'WHEN', 'WHENEVER', 'WHERE', 'WHILE', 'WITH', 'WITHIN GROUP', 'WORK', 'WRITE', 'WRITETEXT', 'YEAR', 'ZONE',]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|