velocity-python 0.0.1__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 +3 -0
- velocity/aws/__init__.py +24 -0
- velocity/aws/context.py +0 -0
- velocity/aws/handlers/__init__.py +2 -0
- velocity/aws/handlers/lambda_handler.py +123 -0
- velocity/aws/handlers/sqs_handler.py +48 -0
- velocity/db/__init__.py +5 -0
- velocity/db/core/__init__.py +0 -0
- velocity/db/core/column.py +202 -0
- velocity/db/core/database.py +65 -0
- velocity/db/core/decorators.py +81 -0
- velocity/db/core/engine.py +367 -0
- velocity/db/core/exceptions.py +31 -0
- velocity/db/core/result.py +137 -0
- velocity/db/core/row.py +191 -0
- velocity/db/core/sequence.py +33 -0
- velocity/db/core/table.py +448 -0
- velocity/db/core/transaction.py +178 -0
- velocity/db/servers/__init__.py +0 -0
- velocity/db/servers/mysql.py +575 -0
- velocity/db/servers/postgres.py +1275 -0
- velocity/db/servers/sql.py +558 -0
- velocity/db/servers/sqlite.py +899 -0
- velocity/db/servers/sqlserver.py +821 -0
- velocity/misc/__init__.py +0 -0
- velocity/misc/conv.py +420 -0
- velocity/misc/db.py +85 -0
- velocity/misc/export.py +147 -0
- velocity/misc/format.py +81 -0
- velocity/misc/mail.py +67 -0
- velocity/misc/timer.py +27 -0
- velocity_python-0.0.1.dist-info/LICENSE +19 -0
- velocity_python-0.0.1.dist-info/METADATA +181 -0
- velocity_python-0.0.1.dist-info/RECORD +36 -0
- velocity_python-0.0.1.dist-info/WHEEL +5 -0
- velocity_python-0.0.1.dist-info/top_level.txt +1 -0
velocity/db/core/row.py
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import pprint
|
|
2
|
+
|
|
3
|
+
class Row(object):
|
|
4
|
+
def __init__(self, table, key):
|
|
5
|
+
if isinstance(table, str):
|
|
6
|
+
raise Exception("table parameter of row class must `table` instance")
|
|
7
|
+
self.table = table
|
|
8
|
+
if isinstance(key,(dict,Row)):
|
|
9
|
+
pk = {}
|
|
10
|
+
try:
|
|
11
|
+
for k in self.key_cols:
|
|
12
|
+
pk[k] = key[k]
|
|
13
|
+
except KeyError:
|
|
14
|
+
pk = key
|
|
15
|
+
else:
|
|
16
|
+
pk = { self.key_cols[0]: key }
|
|
17
|
+
self.pk = pk
|
|
18
|
+
self.cache = key
|
|
19
|
+
|
|
20
|
+
def __repr__(self):
|
|
21
|
+
return repr(self.to_dict())
|
|
22
|
+
|
|
23
|
+
def __str__(self):
|
|
24
|
+
return pprint.pformat(self.to_dict())
|
|
25
|
+
|
|
26
|
+
def __len__(self):
|
|
27
|
+
return int(self.table.count(self.pk))
|
|
28
|
+
|
|
29
|
+
def __getitem__(self, key):
|
|
30
|
+
if key in self.pk:
|
|
31
|
+
return self.pk[key]
|
|
32
|
+
return self.table.get_value(key, self.pk)
|
|
33
|
+
|
|
34
|
+
def __setitem__(self, key, val):
|
|
35
|
+
if key in self.pk:
|
|
36
|
+
raise Exception("Can't update a primary key, idiot!")
|
|
37
|
+
self.table.upsert({key: val}, self.pk)
|
|
38
|
+
|
|
39
|
+
def __delitem__(self, key):
|
|
40
|
+
if key in self.pk:
|
|
41
|
+
raise Exception("Can't delete a primary key, idiot!")
|
|
42
|
+
if key not in self:
|
|
43
|
+
return
|
|
44
|
+
self[key] = None
|
|
45
|
+
|
|
46
|
+
def __contains__(self, key):
|
|
47
|
+
return key.lower() in [x.lower() for x in self.keys()]
|
|
48
|
+
|
|
49
|
+
def clear(self):
|
|
50
|
+
self.table.delete(where=self.pk)
|
|
51
|
+
return self
|
|
52
|
+
|
|
53
|
+
def keys(self):
|
|
54
|
+
return self.table.sys_columns
|
|
55
|
+
|
|
56
|
+
def values(self, *args):
|
|
57
|
+
d = self.table.select(where=self.pk).as_dict().one()
|
|
58
|
+
if args:
|
|
59
|
+
values = []
|
|
60
|
+
for arg in args:
|
|
61
|
+
values.append(d[arg])
|
|
62
|
+
return values
|
|
63
|
+
else:
|
|
64
|
+
return list(d.values())
|
|
65
|
+
|
|
66
|
+
def items(self):
|
|
67
|
+
d = self.table.select(where=self.pk).as_dict().one()
|
|
68
|
+
return list(d.items())
|
|
69
|
+
|
|
70
|
+
def get(self, key, failobj=None):
|
|
71
|
+
data = self[key]
|
|
72
|
+
if data == None:
|
|
73
|
+
return failobj
|
|
74
|
+
return data
|
|
75
|
+
|
|
76
|
+
def setdefault(self, key, default=None):
|
|
77
|
+
data = self[key]
|
|
78
|
+
if data == None:
|
|
79
|
+
self[key] = default
|
|
80
|
+
return default
|
|
81
|
+
return data
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def update(self, dict=None, **kwds):
|
|
85
|
+
data = {}
|
|
86
|
+
if dict:
|
|
87
|
+
data.update(dict)
|
|
88
|
+
if kwds:
|
|
89
|
+
data.update(kwds)
|
|
90
|
+
if data:
|
|
91
|
+
self.table.upsert(data, self.pk)
|
|
92
|
+
return self
|
|
93
|
+
|
|
94
|
+
def iterkeys(self):
|
|
95
|
+
return list(self.keys())
|
|
96
|
+
|
|
97
|
+
def itervalues(self):
|
|
98
|
+
return list(self.values())
|
|
99
|
+
|
|
100
|
+
def iteritems(self):
|
|
101
|
+
return list(self.items())
|
|
102
|
+
|
|
103
|
+
def __cmp__(self, other):
|
|
104
|
+
# zero == same (not less than or greater than other)
|
|
105
|
+
diff = -1
|
|
106
|
+
if hasattr(other,'keys'):
|
|
107
|
+
k1 = list(self.keys())
|
|
108
|
+
k2 = list(other.keys())
|
|
109
|
+
if k1 == k2:
|
|
110
|
+
diff = 0
|
|
111
|
+
for k in k1:
|
|
112
|
+
if self[k] != other[k]:
|
|
113
|
+
diff = -1
|
|
114
|
+
break
|
|
115
|
+
return diff
|
|
116
|
+
|
|
117
|
+
def __bool__(self):
|
|
118
|
+
return bool(self.__len__())
|
|
119
|
+
|
|
120
|
+
def copy(self):
|
|
121
|
+
old = self.to_dict()
|
|
122
|
+
for key in list(old.keys()):
|
|
123
|
+
if 'sys_' in key:
|
|
124
|
+
old.pop(key)
|
|
125
|
+
return self.table.new(old)
|
|
126
|
+
|
|
127
|
+
#================================================================
|
|
128
|
+
# This stuff is not implemented
|
|
129
|
+
|
|
130
|
+
def pop(self): raise NotImplementedError
|
|
131
|
+
def popitem(self): raise NotImplementedError
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def __lt__(self,other): raise NotImplementedError
|
|
135
|
+
def __gt__(self,other): raise NotImplementedError
|
|
136
|
+
def __le__(self,other): raise NotImplementedError
|
|
137
|
+
def __ge__(self,other): raise NotImplementedError
|
|
138
|
+
|
|
139
|
+
@classmethod
|
|
140
|
+
def fromkeys(cls, iterable, value=None): raise NotImplementedError
|
|
141
|
+
|
|
142
|
+
def to_dict(self):
|
|
143
|
+
return self.table.select(where=self.pk).as_dict().one()
|
|
144
|
+
|
|
145
|
+
def extract(self, *args):
|
|
146
|
+
data = {}
|
|
147
|
+
for key in args:
|
|
148
|
+
if isinstance(key,(tuple,list)):
|
|
149
|
+
data.update(self.extract(*key))
|
|
150
|
+
else:
|
|
151
|
+
data[key] = self[key]
|
|
152
|
+
return data
|
|
153
|
+
|
|
154
|
+
@property
|
|
155
|
+
def key_cols(self):
|
|
156
|
+
#result = self.execute(*self.sql.primary_keys(self.tablename))
|
|
157
|
+
#return [x[0] for x in result.as_tuple()]
|
|
158
|
+
return ['sys_id']
|
|
159
|
+
|
|
160
|
+
def split(self):
|
|
161
|
+
old = self.to_dict()
|
|
162
|
+
for key in old.keys():
|
|
163
|
+
if 'sys_' in key:
|
|
164
|
+
old.pop(key)
|
|
165
|
+
return old, self.pk
|
|
166
|
+
|
|
167
|
+
@property
|
|
168
|
+
def data(self):
|
|
169
|
+
return self.split()[0]
|
|
170
|
+
|
|
171
|
+
def row(self, key):
|
|
172
|
+
tx = self.table.tx
|
|
173
|
+
value = self[key]
|
|
174
|
+
if value is None:
|
|
175
|
+
return None
|
|
176
|
+
fk = self.table.foreign_key_info(key)
|
|
177
|
+
if not fk:
|
|
178
|
+
raise Exception("Column `{}` is not a foreign key in `{}`".format(key, self.table.name))
|
|
179
|
+
return tx.Row(fk['referenced_table_name'],value)
|
|
180
|
+
|
|
181
|
+
def match(self, other):
|
|
182
|
+
for key in other:
|
|
183
|
+
if self[key] != other[key]:
|
|
184
|
+
return False
|
|
185
|
+
return True
|
|
186
|
+
|
|
187
|
+
def touch(self):
|
|
188
|
+
self['sys_modified'] = '@@CURRENT_TIMESTAMP'
|
|
189
|
+
return self
|
|
190
|
+
|
|
191
|
+
delete = clear
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
class Sequence(object):
|
|
2
|
+
def __init__(self, tx, name, start=1000):
|
|
3
|
+
self.tx = tx
|
|
4
|
+
self.name = name.lower()
|
|
5
|
+
self.sql = tx.engine.sql
|
|
6
|
+
self.start = start
|
|
7
|
+
|
|
8
|
+
self.create()
|
|
9
|
+
|
|
10
|
+
def __str__(self):
|
|
11
|
+
return """
|
|
12
|
+
Sequence: %s
|
|
13
|
+
""" % ( self.name )
|
|
14
|
+
|
|
15
|
+
def create(self):
|
|
16
|
+
sql, vals = "CREATE SEQUENCE IF NOT EXISTS {} START {};".format(self.name, self.start), tuple()
|
|
17
|
+
return self.tx.execute(sql, vals)
|
|
18
|
+
|
|
19
|
+
def next(self):
|
|
20
|
+
sql, vals = "SELECT nextval('{}');".format(self.name), tuple()
|
|
21
|
+
return self.tx.execute(sql, vals).scalar()
|
|
22
|
+
|
|
23
|
+
def current(self):
|
|
24
|
+
sql, vals = "SELECT currval('{}');".format(self.name), tuple()
|
|
25
|
+
return self.tx.execute(sql, vals).scalar()
|
|
26
|
+
|
|
27
|
+
def reset(self, start=None):
|
|
28
|
+
sql, vals = "ALTER SEQUENCE {} RESTART WITH {};".format(self.name, start or self.start), tuple()
|
|
29
|
+
return self.tx.execute(sql, vals).scalar()
|
|
30
|
+
|
|
31
|
+
def drop(self):
|
|
32
|
+
sql, vals = "DROP SEQUENCE IF EXISTS {};".format(self.name), tuple()
|
|
33
|
+
return self.tx.execute(sql, vals)
|
|
@@ -0,0 +1,448 @@
|
|
|
1
|
+
from velocity.db import exceptions
|
|
2
|
+
from velocity.db.core.row import Row
|
|
3
|
+
from velocity.db.servers.sql import Query
|
|
4
|
+
from velocity.db.core.result import Result
|
|
5
|
+
from velocity.db.core.column import Column
|
|
6
|
+
from velocity.db.core.decorators import return_default, create_missing, retry_on_dup_key
|
|
7
|
+
from functools import wraps
|
|
8
|
+
|
|
9
|
+
class Table(object):
|
|
10
|
+
def __init__(self, tx, name):
|
|
11
|
+
self.tx = tx
|
|
12
|
+
assert(self.tx)
|
|
13
|
+
self.name = name.lower()
|
|
14
|
+
assert(self.name)
|
|
15
|
+
self.sql = tx.engine.sql
|
|
16
|
+
assert(self.sql)
|
|
17
|
+
|
|
18
|
+
def __str__(self):
|
|
19
|
+
return """
|
|
20
|
+
Table: %s
|
|
21
|
+
(table exists) %s
|
|
22
|
+
Columns: %s
|
|
23
|
+
Rows: %s
|
|
24
|
+
""" % (
|
|
25
|
+
self.name,
|
|
26
|
+
self.exists(),
|
|
27
|
+
len(self.columns),
|
|
28
|
+
len(self)
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
def __enter__(self):
|
|
32
|
+
return self
|
|
33
|
+
|
|
34
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
35
|
+
if not exc_type:
|
|
36
|
+
self.close()
|
|
37
|
+
|
|
38
|
+
def close(self):
|
|
39
|
+
try:
|
|
40
|
+
self._cursor.close()
|
|
41
|
+
except:
|
|
42
|
+
pass
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def cursor(self):
|
|
46
|
+
try:
|
|
47
|
+
return self._cursor
|
|
48
|
+
except:
|
|
49
|
+
self._cursor = self.tx.cursor()
|
|
50
|
+
return self._cursor
|
|
51
|
+
|
|
52
|
+
def __call__(self, where=None):
|
|
53
|
+
sql,val = self.sql.select(table=self.name,where=where)
|
|
54
|
+
for data in self.tx.execute(sql,val):
|
|
55
|
+
yield self.row(data)
|
|
56
|
+
|
|
57
|
+
def __iter__(self):
|
|
58
|
+
sql,val = self.sql.select(table=self.name, orderby="sys_id")
|
|
59
|
+
for data in self.tx.execute(sql,val):
|
|
60
|
+
yield self.row(data)
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def sys_columns(self):
|
|
64
|
+
sql, vals = self.sql.columns(self.name)
|
|
65
|
+
result = self.tx.execute(sql, vals, cursor=self.cursor)
|
|
66
|
+
return [x[0] for x in result.as_tuple()]
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def columns(self):
|
|
70
|
+
columns = []
|
|
71
|
+
for column in self.sys_columns:
|
|
72
|
+
if 'sys_' not in column:
|
|
73
|
+
columns.append(column)
|
|
74
|
+
return columns
|
|
75
|
+
|
|
76
|
+
@return_default(None)
|
|
77
|
+
def create_index(self, columns, unique=False, direction=None, where=None, **kwds):
|
|
78
|
+
sql, vals = self.sql.create_index(self.name, columns, unique, direction, where, tbl=self, **kwds)
|
|
79
|
+
self.tx.execute(sql, vals, cursor=self.cursor)
|
|
80
|
+
|
|
81
|
+
@return_default(None)
|
|
82
|
+
def drop_index(self, columns, **kwds):
|
|
83
|
+
sql, vals = self.sql.drop_index(self.name, columns, **kwds)
|
|
84
|
+
self.tx.execute(sql, vals, cursor=self.cursor)
|
|
85
|
+
|
|
86
|
+
@return_default(None)
|
|
87
|
+
def drop_column(self, column):
|
|
88
|
+
sql, vals = self.sql.drop_column(self.name, column)
|
|
89
|
+
self.tx.execute(sql, vals, cursor=self.cursor)
|
|
90
|
+
|
|
91
|
+
def create(self, columns={}, drop=False):
|
|
92
|
+
sql, vals = self.sql.create_table(self.name, columns, drop)
|
|
93
|
+
self.tx.execute(sql, vals, cursor=self.cursor)
|
|
94
|
+
|
|
95
|
+
def drop(self):
|
|
96
|
+
sql, vals = self.sql.drop_table(self.name)
|
|
97
|
+
self.tx.execute(sql, vals, cursor=self.cursor)
|
|
98
|
+
|
|
99
|
+
def exists(self):
|
|
100
|
+
sql, vals = self.sql.tables()
|
|
101
|
+
result = self.tx.execute(sql, vals, cursor=self.cursor)
|
|
102
|
+
if '.' in self.name:
|
|
103
|
+
return bool(self.name in ["%s.%s" % x for x in result.as_tuple()])
|
|
104
|
+
else:
|
|
105
|
+
return bool(self.name in ["%s" % x[1] for x in result.as_tuple()])
|
|
106
|
+
|
|
107
|
+
def column(self, name):
|
|
108
|
+
return Column(self, name)
|
|
109
|
+
|
|
110
|
+
def row(self, key=None):
|
|
111
|
+
if key == None:
|
|
112
|
+
return self.new()
|
|
113
|
+
return Row(self, key)
|
|
114
|
+
|
|
115
|
+
def dict(self, key):
|
|
116
|
+
row = self.find(key)
|
|
117
|
+
return row.to_dict() if row else {}
|
|
118
|
+
|
|
119
|
+
def rows(self, where=None, orderby=None, qty=None):
|
|
120
|
+
for key in self.ids(where=where, orderby=orderby, qty=qty):
|
|
121
|
+
yield Row(self, key)
|
|
122
|
+
|
|
123
|
+
def ids(self, where=None, orderby=None, groupby=None, having=None, start=None, qty=None):
|
|
124
|
+
for key in self.select('sys_id', where=where,orderby=orderby,groupby=groupby,having=having,start=start,qty=qty):
|
|
125
|
+
yield key['sys_id']
|
|
126
|
+
|
|
127
|
+
def set_id(self, start):
|
|
128
|
+
sql, vals = self.sql.set_id(self.name, start)
|
|
129
|
+
result = self.tx.execute(sql, vals, cursor=self.cursor)
|
|
130
|
+
|
|
131
|
+
def new(self, data={'sys_modified':'@@CURRENT_TIMESTAMP'}):
|
|
132
|
+
if len(data) == 1 and 'sys_id' in data:
|
|
133
|
+
return self.row(data).touch()
|
|
134
|
+
val = self.insert(data)
|
|
135
|
+
sql, vals = self.sql.last_id(self.name)
|
|
136
|
+
sys_id = self.tx.execute(sql, vals).scalar()
|
|
137
|
+
return self.row(sys_id)
|
|
138
|
+
|
|
139
|
+
def get(self, where):
|
|
140
|
+
if where is None:
|
|
141
|
+
raise Exception("None is not allowed as a primary key")
|
|
142
|
+
if isinstance(where, int):
|
|
143
|
+
where = {'sys_id': where}
|
|
144
|
+
result = self.select('sys_id', where=where).all()
|
|
145
|
+
if len(result) > 1:
|
|
146
|
+
sql = self.selectSQL('sys_id', where=where)
|
|
147
|
+
raise exceptions.DuplicateRowsFoundError("More than one entry found. {}".format(sql))
|
|
148
|
+
elif len(result) < 1:
|
|
149
|
+
where = where.copy()
|
|
150
|
+
keys = list(where.keys())
|
|
151
|
+
for key in keys:
|
|
152
|
+
chars = set('<>!=%')
|
|
153
|
+
if any((c in chars) for c in key):
|
|
154
|
+
where.pop(key)
|
|
155
|
+
return self.new(where)
|
|
156
|
+
return Row(self, result[0]['sys_id'])
|
|
157
|
+
|
|
158
|
+
@return_default(None)
|
|
159
|
+
def find(self, where):
|
|
160
|
+
if where is None:
|
|
161
|
+
raise Exception("None is not allowed as a primary key")
|
|
162
|
+
if isinstance(where, int):
|
|
163
|
+
where = {'sys_id': where}
|
|
164
|
+
result = self.select('sys_id', where=where).all()
|
|
165
|
+
if len(result) > 1:
|
|
166
|
+
sql = self.selectSQL('sys_id', where=where)
|
|
167
|
+
raise exceptions.DuplicateRowsFoundError("More than one entry found. {}".format(sql))
|
|
168
|
+
elif len(result) < 1:
|
|
169
|
+
return None
|
|
170
|
+
return Row(self, result[0]['sys_id'])
|
|
171
|
+
|
|
172
|
+
@return_default(None)
|
|
173
|
+
def first(self, where, orderby=None, create_new=False):
|
|
174
|
+
if where is None:
|
|
175
|
+
raise Exception("None is not allowed as a primary key")
|
|
176
|
+
if isinstance(where, int):
|
|
177
|
+
where = {'sys_id': where}
|
|
178
|
+
result = self.select('sys_id', where=where, orderby=orderby).all()
|
|
179
|
+
if len(result) < 1:
|
|
180
|
+
if create_new:
|
|
181
|
+
where = where.copy()
|
|
182
|
+
keys = list(where.keys())
|
|
183
|
+
for key in keys:
|
|
184
|
+
chars = set('<>!=%')
|
|
185
|
+
if any((c in chars) for c in key):
|
|
186
|
+
where.pop(key)
|
|
187
|
+
return self.new(where)
|
|
188
|
+
return None
|
|
189
|
+
return Row(self, result[0]['sys_id'])
|
|
190
|
+
|
|
191
|
+
@return_default(None)
|
|
192
|
+
def one(self, where=None, orderby=None):
|
|
193
|
+
if isinstance(where, int):
|
|
194
|
+
where = {'sys_id': where}
|
|
195
|
+
result = self.select('sys_id', where=where, orderby=orderby).all()
|
|
196
|
+
if len(result) < 1:
|
|
197
|
+
return None
|
|
198
|
+
return Row(self, result[0]['sys_id'])
|
|
199
|
+
|
|
200
|
+
@property
|
|
201
|
+
def primary_keys(self):
|
|
202
|
+
sql, vals = self.sql.primary_keys(self.name)
|
|
203
|
+
result = self.tx.execute(sql, vals, cursor=self.cursor)
|
|
204
|
+
return [x[0] for x in result.as_tuple()]
|
|
205
|
+
|
|
206
|
+
@property
|
|
207
|
+
def foreign_keys(self):
|
|
208
|
+
sql, vals = self.sql.primary_keys(self.name)
|
|
209
|
+
result = self.tx.execute(sql, vals, cursor=self.cursor)
|
|
210
|
+
return [x[0] for x in result.as_tuple()]
|
|
211
|
+
|
|
212
|
+
def foreign_key_info(self, column):
|
|
213
|
+
sql, vals = self.sql.foreign_key_info(table=self.name, column=column)
|
|
214
|
+
return self.tx.execute(sql, vals, cursor=self.cursor).one()
|
|
215
|
+
|
|
216
|
+
@return_default()
|
|
217
|
+
def create_foreign_key(self, columns, key_to_table, key_to_columns='sys_id'):
|
|
218
|
+
sql, vals = self.sql.create_foreign_key(self.name, columns, key_to_table, key_to_columns)
|
|
219
|
+
return self.tx.execute(sql, vals, cursor=self.cursor)
|
|
220
|
+
|
|
221
|
+
def drop_foreign_key(self, columns, key_to_table, key_to_columns='sys_id'):
|
|
222
|
+
sql, vals = self.sql.create_foreign_key(self.name, columns, key_to_table, key_to_columns)
|
|
223
|
+
return self.tx.execute(sql, vals, cursor=self.cursor)
|
|
224
|
+
|
|
225
|
+
def rename(self, name):
|
|
226
|
+
sql, vals = self.sql.rename_table(self.name, name)
|
|
227
|
+
self.tx.execute(sql, vals, cursor=self.cursor)
|
|
228
|
+
self.name = name
|
|
229
|
+
|
|
230
|
+
def lower_keys(self, arg):
|
|
231
|
+
new = {}
|
|
232
|
+
if isinstance(arg,dict):
|
|
233
|
+
for key in list(arg.keys()):
|
|
234
|
+
new[key.lower()] = arg[key]
|
|
235
|
+
return new
|
|
236
|
+
|
|
237
|
+
@create_missing
|
|
238
|
+
def alter(self, columns):
|
|
239
|
+
diff = []
|
|
240
|
+
if isinstance(columns, dict):
|
|
241
|
+
columns = self.lower_keys(columns)
|
|
242
|
+
# Need to maintain order of keys
|
|
243
|
+
for k in list(columns.keys()):
|
|
244
|
+
diff.append(k) if k not in self.columns else None
|
|
245
|
+
else:
|
|
246
|
+
raise Exception("I don't know how to handle columns data type in this context")
|
|
247
|
+
if diff:
|
|
248
|
+
new = dict([(key,columns[key]) for key in diff if 'sys_' not in key])
|
|
249
|
+
sql, vals = self.sql.alter_add(self.name, new)
|
|
250
|
+
self.tx.execute(sql, vals, cursor=self.cursor)
|
|
251
|
+
|
|
252
|
+
@create_missing
|
|
253
|
+
def alter_type(self, column, type_or_value, nullable=True):
|
|
254
|
+
sql, vals = self.sql.alter_column_by_type(self.name, column, type_or_value, nullable)
|
|
255
|
+
self.tx.execute(sql, vals, cursor=self.cursor)
|
|
256
|
+
|
|
257
|
+
@create_missing
|
|
258
|
+
def update(self, data, pk, left_join=None, inner_join =None, outer_join=None):
|
|
259
|
+
sql, vals = self.sql.update(self.name, data, pk, left_join, inner_join, outer_join)
|
|
260
|
+
result = self.tx.execute(sql, vals, cursor=self.cursor)
|
|
261
|
+
return result.cursor.rowcount
|
|
262
|
+
|
|
263
|
+
@retry_on_dup_key
|
|
264
|
+
@create_missing
|
|
265
|
+
def insert(self, data):
|
|
266
|
+
sql, vals = self.sql.insert(self.name, data)
|
|
267
|
+
result = self.tx.execute(sql, vals, cursor=self.cursor)
|
|
268
|
+
return result.cursor.rowcount
|
|
269
|
+
|
|
270
|
+
def upsert(self, data, pk):
|
|
271
|
+
if not self.update(data, pk):
|
|
272
|
+
new = {}
|
|
273
|
+
new.update(pk)
|
|
274
|
+
new.update(data)
|
|
275
|
+
self.insert(new)
|
|
276
|
+
|
|
277
|
+
def indate(self, data, pk):
|
|
278
|
+
new = {}
|
|
279
|
+
new.update(pk)
|
|
280
|
+
new.update(data)
|
|
281
|
+
try:
|
|
282
|
+
sp = self.tx.create_savepoint(cursor=self.cursor)
|
|
283
|
+
self.insert(new)
|
|
284
|
+
except exceptions.DbDuplicateKeyError:
|
|
285
|
+
self.tx.rollback_savepoint(sp, cursor=self.cursor)
|
|
286
|
+
self.update(data, pk)
|
|
287
|
+
|
|
288
|
+
def updateSQL(self, data, pk, left_join=None, inner_join =None, outer_join=None):
|
|
289
|
+
return self.sql.update(self.name, data, pk, left_join, inner_join, outer_join)
|
|
290
|
+
|
|
291
|
+
@return_default(0)
|
|
292
|
+
def count(self, where=None):
|
|
293
|
+
sql, vals = self.sql.select(columns='count(*)', table=self.name, where=where)
|
|
294
|
+
return self.tx.execute(sql, vals, cursor=self.cursor).scalar()
|
|
295
|
+
|
|
296
|
+
@return_default(0)
|
|
297
|
+
def sum(self, column, where=None):
|
|
298
|
+
sql, vals = self.sql.select(columns='sum({})'.format(column), table=self.name, where=where)
|
|
299
|
+
return self.tx.execute(sql, vals, cursor=self.cursor).scalar()
|
|
300
|
+
|
|
301
|
+
@return_default(0)
|
|
302
|
+
def __len__(self):
|
|
303
|
+
sql, vals = self.sql.select(columns='count(*)', table=self.name)
|
|
304
|
+
return self.tx.execute(sql, vals, cursor=self.cursor).scalar()
|
|
305
|
+
|
|
306
|
+
@return_default(None)
|
|
307
|
+
def oldest(self, where={}, field='sys_modified', columns='sys_id'):
|
|
308
|
+
sql,vals = self.sql.select(columns=columns,
|
|
309
|
+
table=self.name,
|
|
310
|
+
where=where,
|
|
311
|
+
orderby=field + ' asc',
|
|
312
|
+
qty=1)
|
|
313
|
+
return self.tx.execute(sql, vals, cursor=self.cursor).scalar()
|
|
314
|
+
|
|
315
|
+
@return_default(None)
|
|
316
|
+
def newest(self, where={}, field='sys_modified', columns='sys_id'):
|
|
317
|
+
sql,vals = self.sql.select(columns=columns,
|
|
318
|
+
table=self.name,
|
|
319
|
+
where=where,
|
|
320
|
+
orderby=field + ' desc',
|
|
321
|
+
qty=1)
|
|
322
|
+
return self.tx.execute(sql, vals, cursor=self.cursor).scalar()
|
|
323
|
+
|
|
324
|
+
@return_default(Result())
|
|
325
|
+
def select(self,columns=None,where=None,orderby=None,groupby=None,having=None,start=None,qty=None):
|
|
326
|
+
sql,vals = self.sql.select(columns=columns,
|
|
327
|
+
table=self.name,
|
|
328
|
+
where=where,
|
|
329
|
+
orderby=orderby,
|
|
330
|
+
groupby=groupby,
|
|
331
|
+
having=having,
|
|
332
|
+
start=start,
|
|
333
|
+
qty=qty,
|
|
334
|
+
tbl=self)
|
|
335
|
+
return self.tx.execute(sql, vals)
|
|
336
|
+
|
|
337
|
+
def list(self, *args, **kwds):
|
|
338
|
+
return self.select(*args, **kwds).all()
|
|
339
|
+
|
|
340
|
+
def selectSQL(self,columns=None,where=None,orderby=None,groupby=None,having=None,start=None,qty=None):
|
|
341
|
+
return self.sql.select(columns=columns,
|
|
342
|
+
table=self.name,
|
|
343
|
+
where=where,
|
|
344
|
+
orderby=orderby,
|
|
345
|
+
groupby=groupby,
|
|
346
|
+
having=having,
|
|
347
|
+
start=start,
|
|
348
|
+
qty=qty,
|
|
349
|
+
tbl=self)
|
|
350
|
+
|
|
351
|
+
def query(self,columns=None,where=None,orderby=None,groupby=None,having=None,start=None,qty=None):
|
|
352
|
+
sql,vals = self.sql.select(columns=columns,
|
|
353
|
+
table=self.name,
|
|
354
|
+
where=where,
|
|
355
|
+
orderby=orderby,
|
|
356
|
+
groupby=groupby,
|
|
357
|
+
having=having,
|
|
358
|
+
start=start,
|
|
359
|
+
qty=qty,
|
|
360
|
+
tbl=self)
|
|
361
|
+
if vals:
|
|
362
|
+
raise Exception("a query generator does not support dictionary type as where clause")
|
|
363
|
+
return Query(sql)
|
|
364
|
+
|
|
365
|
+
@return_default(Result())
|
|
366
|
+
def server_select(self,columns=None,where=None,orderby=None,groupby=None,having=None,start=None,qty=None):
|
|
367
|
+
sql,vals = self.sql.select(columns=columns,
|
|
368
|
+
table=self.name,
|
|
369
|
+
where=where,
|
|
370
|
+
orderby=orderby,
|
|
371
|
+
groupby=groupby,
|
|
372
|
+
having=having,
|
|
373
|
+
start=start,
|
|
374
|
+
qty=qty,
|
|
375
|
+
tbl=self)
|
|
376
|
+
return self.tx.server_execute(sql, vals)
|
|
377
|
+
|
|
378
|
+
@return_default(Result())
|
|
379
|
+
def batch(self, size=100, *args, **kwds):
|
|
380
|
+
current = 0
|
|
381
|
+
while True:
|
|
382
|
+
kwds['start'] = current
|
|
383
|
+
kwds['qty'] = size
|
|
384
|
+
results = self.select(*args, **kwds).all()
|
|
385
|
+
if results:
|
|
386
|
+
yield results
|
|
387
|
+
current += len(results)
|
|
388
|
+
else:
|
|
389
|
+
raise StopIteration
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
def get_value(self, key, pk):
|
|
394
|
+
return self.select(columns=key, where=pk).scalar()
|
|
395
|
+
|
|
396
|
+
@return_default({})
|
|
397
|
+
def get_row(self, where):
|
|
398
|
+
if not where:
|
|
399
|
+
raise Exception("Unique key for the row to be retrieved is required.")
|
|
400
|
+
sql, vals = self.sql.select(columns='*', table=self.name, where=where)
|
|
401
|
+
return self.tx.execute(sql, vals, cursor=self.cursor).one()
|
|
402
|
+
|
|
403
|
+
def delete(self, where):
|
|
404
|
+
if not where:
|
|
405
|
+
raise Exception("You just tried to delete an entire table. Use truncate instead.")
|
|
406
|
+
sql, vals = self.sql.delete(table=self.name, where=where)
|
|
407
|
+
result = self.tx.execute(sql, vals)
|
|
408
|
+
return result.cursor.rowcount
|
|
409
|
+
|
|
410
|
+
def truncate(self):
|
|
411
|
+
sql, vals = self.sql.truncate(table=self.name)
|
|
412
|
+
self.tx.execute(sql, vals)
|
|
413
|
+
|
|
414
|
+
def has_duplicates(self, columns=['sys_id'], key='sys_id'):
|
|
415
|
+
sql, vals = self.sql.find_duplicates(self.name, columns, key)
|
|
416
|
+
return bool([x for x in self.tx.execute(sql, vals)])
|
|
417
|
+
|
|
418
|
+
def find_duplicates(self, columns=['sys_id'], key='sys_id'):
|
|
419
|
+
sql, vals = self.sql.find_duplicates(self.name, columns, key)
|
|
420
|
+
return [x for x in self.tx.execute(sql, vals)]
|
|
421
|
+
|
|
422
|
+
def delete_duplicates(self, columns=['sys_id'], key='sys_id'):
|
|
423
|
+
sql, vals = self.sql.delete_duplicates(self.name, columns, key='sys_id')
|
|
424
|
+
self.tx.execute(sql, vals)
|
|
425
|
+
|
|
426
|
+
def create_view(self, name, query, temp=False, silent=True):
|
|
427
|
+
sql, vals = self.sql.create_view(name=name,query=query,temp=temp,silent=silent)
|
|
428
|
+
return self.tx.execute(sql, vals)
|
|
429
|
+
|
|
430
|
+
def drop_view(self, name, silent=True):
|
|
431
|
+
sql, vals = self.sql.drop_view(name=name,silent=silent)
|
|
432
|
+
return self.tx.execute(sql, vals)
|
|
433
|
+
|
|
434
|
+
def alter_trigger(self, name='USER', state='ENABLE'):
|
|
435
|
+
sql, vals = self.sql.alter_trigger(table=self.name, state=state, name=name)
|
|
436
|
+
return self.tx.execute(sql, vals)
|
|
437
|
+
|
|
438
|
+
def rename_column(self, orig, new):
|
|
439
|
+
sql, vals = self.sql.rename_column(table=self.name, orig=orig, new=new)
|
|
440
|
+
return self.tx.execute(sql, vals)
|
|
441
|
+
|
|
442
|
+
def set_sequence(self, next_value=1000):
|
|
443
|
+
sql, vals = self.sql.set_sequence(table=self.name, next_value=next_value)
|
|
444
|
+
return self.tx.execute(sql, vals).scalar()
|
|
445
|
+
|
|
446
|
+
def missing(self, list, column='sys_id', where=None):
|
|
447
|
+
sql, vals = self.sql.missing(table=self.name, list=list, column=column, where=where)
|
|
448
|
+
return self.tx.execute(sql, vals).as_simple_list().all()
|