masonite-framework-orm 3.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.
- masonite_framework_orm-3.0.1.dist-info/METADATA +87 -0
- masonite_framework_orm-3.0.1.dist-info/RECORD +116 -0
- masonite_framework_orm-3.0.1.dist-info/WHEEL +5 -0
- masonite_framework_orm-3.0.1.dist-info/entry_points.txt +3 -0
- masonite_framework_orm-3.0.1.dist-info/licenses/LICENSE +21 -0
- masonite_framework_orm-3.0.1.dist-info/top_level.txt +1 -0
- masoniteorm/__init__.py +1 -0
- masoniteorm/collection/Collection.py +605 -0
- masoniteorm/collection/__init__.py +1 -0
- masoniteorm/commands/CanOverrideConfig.py +16 -0
- masoniteorm/commands/CanOverrideOptionsDefault.py +22 -0
- masoniteorm/commands/Command.py +6 -0
- masoniteorm/commands/Entry.py +43 -0
- masoniteorm/commands/MakeMigrationCommand.py +57 -0
- masoniteorm/commands/MakeModelCommand.py +78 -0
- masoniteorm/commands/MakeModelDocstringCommand.py +37 -0
- masoniteorm/commands/MakeObserverCommand.py +54 -0
- masoniteorm/commands/MakeSeedCommand.py +54 -0
- masoniteorm/commands/MigrateCommand.py +46 -0
- masoniteorm/commands/MigrateFreshCommand.py +41 -0
- masoniteorm/commands/MigrateRefreshCommand.py +41 -0
- masoniteorm/commands/MigrateResetCommand.py +25 -0
- masoniteorm/commands/MigrateRollbackCommand.py +26 -0
- masoniteorm/commands/MigrateStatusCommand.py +51 -0
- masoniteorm/commands/SeedRunCommand.py +35 -0
- masoniteorm/commands/ShellCommand.py +205 -0
- masoniteorm/commands/__init__.py +18 -0
- masoniteorm/commands/stubs/create_migration.stub +20 -0
- masoniteorm/commands/stubs/create_seed.stub +9 -0
- masoniteorm/commands/stubs/model.stub +9 -0
- masoniteorm/commands/stubs/observer.stub +101 -0
- masoniteorm/commands/stubs/table_migration.stub +19 -0
- masoniteorm/config.py +123 -0
- masoniteorm/connections/BaseConnection.py +101 -0
- masoniteorm/connections/ConnectionFactory.py +59 -0
- masoniteorm/connections/ConnectionResolver.py +132 -0
- masoniteorm/connections/MSSQLConnection.py +176 -0
- masoniteorm/connections/MySQLConnection.py +232 -0
- masoniteorm/connections/PostgresConnection.py +225 -0
- masoniteorm/connections/SQLiteConnection.py +179 -0
- masoniteorm/connections/__init__.py +6 -0
- masoniteorm/exceptions.py +38 -0
- masoniteorm/expressions/__init__.py +1 -0
- masoniteorm/expressions/expressions.py +288 -0
- masoniteorm/factories/Factory.py +112 -0
- masoniteorm/factories/__init__.py +1 -0
- masoniteorm/helpers/__init__.py +0 -0
- masoniteorm/helpers/misc.py +22 -0
- masoniteorm/migrations/Migration.py +330 -0
- masoniteorm/migrations/__init__.py +1 -0
- masoniteorm/models/MigrationModel.py +9 -0
- masoniteorm/models/Model.py +1209 -0
- masoniteorm/models/Model.pyi +1366 -0
- masoniteorm/models/Pivot.py +5 -0
- masoniteorm/models/__init__.py +1 -0
- masoniteorm/observers/ObservesEvents.py +27 -0
- masoniteorm/observers/__init__.py +1 -0
- masoniteorm/pagination/BasePaginator.py +10 -0
- masoniteorm/pagination/LengthAwarePaginator.py +34 -0
- masoniteorm/pagination/SimplePaginator.py +28 -0
- masoniteorm/pagination/__init__.py +2 -0
- masoniteorm/providers/ORMProvider.py +39 -0
- masoniteorm/providers/__init__.py +1 -0
- masoniteorm/query/EagerRelation.py +42 -0
- masoniteorm/query/QueryBuilder.py +2486 -0
- masoniteorm/query/__init__.py +1 -0
- masoniteorm/query/grammars/BaseGrammar.py +1027 -0
- masoniteorm/query/grammars/MSSQLGrammar.py +194 -0
- masoniteorm/query/grammars/MySQLGrammar.py +238 -0
- masoniteorm/query/grammars/PostgresGrammar.py +213 -0
- masoniteorm/query/grammars/SQLiteGrammar.py +228 -0
- masoniteorm/query/grammars/__init__.py +4 -0
- masoniteorm/query/processors/MSSQLPostProcessor.py +58 -0
- masoniteorm/query/processors/MySQLPostProcessor.py +48 -0
- masoniteorm/query/processors/PostgresPostProcessor.py +49 -0
- masoniteorm/query/processors/SQLitePostProcessor.py +49 -0
- masoniteorm/query/processors/__init__.py +4 -0
- masoniteorm/relationships/BaseRelationship.py +161 -0
- masoniteorm/relationships/BelongsTo.py +124 -0
- masoniteorm/relationships/BelongsToMany.py +604 -0
- masoniteorm/relationships/HasMany.py +66 -0
- masoniteorm/relationships/HasManyThrough.py +269 -0
- masoniteorm/relationships/HasOne.py +111 -0
- masoniteorm/relationships/HasOneThrough.py +275 -0
- masoniteorm/relationships/MorphMany.py +152 -0
- masoniteorm/relationships/MorphOne.py +156 -0
- masoniteorm/relationships/MorphTo.py +111 -0
- masoniteorm/relationships/MorphToMany.py +108 -0
- masoniteorm/relationships/__init__.py +10 -0
- masoniteorm/schema/Blueprint.py +1161 -0
- masoniteorm/schema/Column.py +144 -0
- masoniteorm/schema/ColumnDiff.py +0 -0
- masoniteorm/schema/Constraint.py +5 -0
- masoniteorm/schema/ForeignKeyConstraint.py +28 -0
- masoniteorm/schema/Index.py +5 -0
- masoniteorm/schema/Schema.py +359 -0
- masoniteorm/schema/Table.py +94 -0
- masoniteorm/schema/TableDiff.py +86 -0
- masoniteorm/schema/__init__.py +3 -0
- masoniteorm/schema/platforms/MSSQLPlatform.py +367 -0
- masoniteorm/schema/platforms/MySQLPlatform.py +513 -0
- masoniteorm/schema/platforms/Platform.py +97 -0
- masoniteorm/schema/platforms/PostgresPlatform.py +551 -0
- masoniteorm/schema/platforms/SQLitePlatform.py +481 -0
- masoniteorm/schema/platforms/__init__.py +4 -0
- masoniteorm/scopes/BaseScope.py +6 -0
- masoniteorm/scopes/SoftDeleteScope.py +56 -0
- masoniteorm/scopes/SoftDeletesMixin.py +13 -0
- masoniteorm/scopes/TimeStampsMixin.py +12 -0
- masoniteorm/scopes/TimeStampsScope.py +47 -0
- masoniteorm/scopes/UUIDPrimaryKeyMixin.py +8 -0
- masoniteorm/scopes/UUIDPrimaryKeyScope.py +51 -0
- masoniteorm/scopes/__init__.py +8 -0
- masoniteorm/scopes/scope.py +15 -0
- masoniteorm/seeds/Seeder.py +42 -0
- masoniteorm/seeds/__init__.py +1 -0
|
@@ -0,0 +1,1027 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
3
|
+
from ...expressions.expressions import (
|
|
4
|
+
JoinClause,
|
|
5
|
+
OnClause,
|
|
6
|
+
SelectExpression,
|
|
7
|
+
SubGroupExpression,
|
|
8
|
+
SubSelectExpression,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class BaseGrammar:
|
|
13
|
+
"""The keys in this dictionary is how the ORM will reference these aggregates
|
|
14
|
+
|
|
15
|
+
The values on the right are the matching functions for the grammar
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
[type] -- [description]
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
table = "users"
|
|
22
|
+
|
|
23
|
+
def __init__(
|
|
24
|
+
self,
|
|
25
|
+
columns=(),
|
|
26
|
+
table="users",
|
|
27
|
+
database=None,
|
|
28
|
+
wheres=(),
|
|
29
|
+
limit=False,
|
|
30
|
+
offset=False,
|
|
31
|
+
updates=None,
|
|
32
|
+
aggregates=(),
|
|
33
|
+
order_by=(),
|
|
34
|
+
distinct=False,
|
|
35
|
+
group_by=(),
|
|
36
|
+
joins=(),
|
|
37
|
+
lock=False,
|
|
38
|
+
having=(),
|
|
39
|
+
connection_details=None,
|
|
40
|
+
):
|
|
41
|
+
self._columns = columns
|
|
42
|
+
self.table = table
|
|
43
|
+
self.database = database
|
|
44
|
+
self._wheres = wheres
|
|
45
|
+
self._limit = limit
|
|
46
|
+
self._offset = offset
|
|
47
|
+
self._updates = updates or {}
|
|
48
|
+
self._aggregates = aggregates
|
|
49
|
+
self._order_by = order_by
|
|
50
|
+
self._group_by = group_by
|
|
51
|
+
self._distinct = distinct
|
|
52
|
+
self._joins = joins
|
|
53
|
+
self._having = having
|
|
54
|
+
self.lock = lock
|
|
55
|
+
self._connection_details = connection_details or {}
|
|
56
|
+
self._column = None
|
|
57
|
+
|
|
58
|
+
self._bindings = []
|
|
59
|
+
|
|
60
|
+
self._sql = ""
|
|
61
|
+
|
|
62
|
+
self._sql_qmark = ""
|
|
63
|
+
self._action = "select"
|
|
64
|
+
self.queries = []
|
|
65
|
+
|
|
66
|
+
def compile(self, action, qmark=False):
|
|
67
|
+
self._action = action
|
|
68
|
+
return getattr(self, "_compile_" + action)(qmark=qmark)
|
|
69
|
+
|
|
70
|
+
def _compile_select(self, qmark=False):
|
|
71
|
+
"""Compile a select query statement.
|
|
72
|
+
|
|
73
|
+
Keyword Arguments:
|
|
74
|
+
qmark {bool} -- [description] (default: {False})
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
[type] -- [description]
|
|
78
|
+
"""
|
|
79
|
+
if not self.table:
|
|
80
|
+
self._sql = (
|
|
81
|
+
self.select_no_table()
|
|
82
|
+
.format(
|
|
83
|
+
columns=self.process_columns(separator=", ", qmark=qmark),
|
|
84
|
+
table=self.process_table(self.table),
|
|
85
|
+
joins=self.process_joins(qmark=qmark),
|
|
86
|
+
wheres=self.process_wheres(qmark=qmark),
|
|
87
|
+
limit=self.process_limit(),
|
|
88
|
+
offset=self.process_offset(),
|
|
89
|
+
aggregates=self.process_aggregates(),
|
|
90
|
+
order_by=self.process_order_by(),
|
|
91
|
+
group_by=self.process_group_by(),
|
|
92
|
+
having=self.process_having(),
|
|
93
|
+
lock=self.process_locks(),
|
|
94
|
+
)
|
|
95
|
+
.strip()
|
|
96
|
+
)
|
|
97
|
+
else:
|
|
98
|
+
self._sql = (
|
|
99
|
+
self.select_format()
|
|
100
|
+
.format(
|
|
101
|
+
columns=self.process_columns(separator=", ", qmark=qmark),
|
|
102
|
+
keyword="DISTINCT" if self._distinct else "",
|
|
103
|
+
table=self.process_table(self.table),
|
|
104
|
+
joins=self.process_joins(qmark=qmark),
|
|
105
|
+
wheres=self.process_wheres(qmark=qmark),
|
|
106
|
+
limit=self.process_limit(),
|
|
107
|
+
offset=self.process_offset(),
|
|
108
|
+
aggregates=self.process_aggregates(),
|
|
109
|
+
order_by=self.process_order_by(),
|
|
110
|
+
group_by=self.process_group_by(),
|
|
111
|
+
having=self.process_having(),
|
|
112
|
+
lock=self.process_locks(),
|
|
113
|
+
)
|
|
114
|
+
.strip()
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
return self
|
|
118
|
+
|
|
119
|
+
def _compile_update(self, qmark=False):
|
|
120
|
+
"""Compiles an update query statement.
|
|
121
|
+
|
|
122
|
+
Keyword Arguments:
|
|
123
|
+
qmark {bool} -- Whether the query should use qmark. (default: {False})
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
self
|
|
127
|
+
"""
|
|
128
|
+
self._sql = self.update_format().format(
|
|
129
|
+
key_equals=self._compile_key_value_equals(qmark=qmark),
|
|
130
|
+
table=self.process_table(self.table),
|
|
131
|
+
wheres=self.process_wheres(qmark=qmark),
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
return self
|
|
135
|
+
|
|
136
|
+
def _compile_insert(self, qmark=False):
|
|
137
|
+
"""Compiles an insert expression.
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
self
|
|
141
|
+
"""
|
|
142
|
+
self._sql = self.insert_format().format(
|
|
143
|
+
key_equals=self._compile_key_value_equals(qmark=qmark),
|
|
144
|
+
table=self.process_table(self.table),
|
|
145
|
+
columns=self.process_columns(
|
|
146
|
+
separator=", ", action="insert", qmark=qmark
|
|
147
|
+
),
|
|
148
|
+
values=self.process_values(separator=", ", qmark=qmark),
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
return self
|
|
152
|
+
|
|
153
|
+
def _compile_bulk_create(self, qmark=False):
|
|
154
|
+
"""Compiles an insert expression.
|
|
155
|
+
|
|
156
|
+
Returns:
|
|
157
|
+
self
|
|
158
|
+
"""
|
|
159
|
+
all_values = [list(x.values()) for x in self._columns]
|
|
160
|
+
|
|
161
|
+
self._sql = self.bulk_insert_format().format(
|
|
162
|
+
key_equals=self._compile_key_value_equals(qmark=qmark),
|
|
163
|
+
table=self.process_table(self.table),
|
|
164
|
+
columns=self.columnize_bulk_columns(list(self._columns[0].keys())),
|
|
165
|
+
values=self.columnize_bulk_values(all_values, qmark=qmark),
|
|
166
|
+
)
|
|
167
|
+
return self
|
|
168
|
+
|
|
169
|
+
def columnize_bulk_columns(self, columns=[]):
|
|
170
|
+
return ", ".join(
|
|
171
|
+
self.column_string().format(column=x, separator="")
|
|
172
|
+
for x in columns
|
|
173
|
+
).rstrip(",")
|
|
174
|
+
|
|
175
|
+
def columnize_bulk_values(self, columns=[], qmark=False):
|
|
176
|
+
sql = ""
|
|
177
|
+
for x in columns:
|
|
178
|
+
inner = ""
|
|
179
|
+
if isinstance(x, list):
|
|
180
|
+
for y in x:
|
|
181
|
+
if qmark:
|
|
182
|
+
self.add_binding(y)
|
|
183
|
+
inner += (
|
|
184
|
+
"?, "
|
|
185
|
+
if qmark
|
|
186
|
+
else self.value_string().format(
|
|
187
|
+
value=y, separator=", "
|
|
188
|
+
)
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
inner = inner.rstrip(", ")
|
|
192
|
+
sql += self.process_value_string().format(
|
|
193
|
+
value=inner, separator=", "
|
|
194
|
+
)
|
|
195
|
+
else:
|
|
196
|
+
if qmark:
|
|
197
|
+
self.add_binding(x)
|
|
198
|
+
sql += (
|
|
199
|
+
"?, "
|
|
200
|
+
if qmark
|
|
201
|
+
else self.process_value_string().format(
|
|
202
|
+
value="?" if qmark else x, separator=", "
|
|
203
|
+
)
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
return sql.rstrip(", ")
|
|
207
|
+
|
|
208
|
+
def process_value_string(self):
|
|
209
|
+
return "({value}){separator}"
|
|
210
|
+
|
|
211
|
+
def _compile_delete(self, qmark=False):
|
|
212
|
+
"""Compiles a delete expression.
|
|
213
|
+
|
|
214
|
+
Returns:
|
|
215
|
+
self
|
|
216
|
+
"""
|
|
217
|
+
self._sql = self.delete_format().format(
|
|
218
|
+
key_equals=self._compile_key_value_equals(qmark=qmark),
|
|
219
|
+
table=self.process_table(self.table),
|
|
220
|
+
wheres=self.process_wheres(qmark=qmark),
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
return self
|
|
224
|
+
|
|
225
|
+
# TODO: Columnize?
|
|
226
|
+
def _get_multiple_columns(self, columns):
|
|
227
|
+
"""Compiles a string or a list of strings into the grammars column syntax.
|
|
228
|
+
|
|
229
|
+
Arguments:
|
|
230
|
+
columns {string|list} -- A column or list of columns
|
|
231
|
+
|
|
232
|
+
Returns:
|
|
233
|
+
self
|
|
234
|
+
"""
|
|
235
|
+
if isinstance(columns, list):
|
|
236
|
+
column_string = ""
|
|
237
|
+
for col in columns:
|
|
238
|
+
column_string += self.process_column(col) + ", "
|
|
239
|
+
return column_string.rstrip(", ")
|
|
240
|
+
|
|
241
|
+
return self.process_column(columns)
|
|
242
|
+
|
|
243
|
+
def process_joins(self, qmark=False):
|
|
244
|
+
"""Compiles a join expression.
|
|
245
|
+
|
|
246
|
+
Returns:
|
|
247
|
+
self
|
|
248
|
+
"""
|
|
249
|
+
sql = ""
|
|
250
|
+
for join in self._joins:
|
|
251
|
+
if isinstance(join, JoinClause):
|
|
252
|
+
on_string = ""
|
|
253
|
+
for clause_idx, clause in enumerate(join.get_on_clauses()):
|
|
254
|
+
keyword = clause.operator.upper() if clause_idx else "ON"
|
|
255
|
+
|
|
256
|
+
if isinstance(clause, OnClause):
|
|
257
|
+
on_string += f"{keyword} {self._table_column_string(clause.column1)} {clause.equality} {self._table_column_string(clause.column2)} "
|
|
258
|
+
else:
|
|
259
|
+
if clause.value_type == "NULL":
|
|
260
|
+
sql_string = f"{self.where_null_string()} "
|
|
261
|
+
on_string += sql_string.format(
|
|
262
|
+
keyword=keyword,
|
|
263
|
+
column=self.process_column(clause.column),
|
|
264
|
+
)
|
|
265
|
+
elif clause.value_type == "NOT NULL":
|
|
266
|
+
sql_string = f"{self.where_not_null_string()} "
|
|
267
|
+
on_string += sql_string.format(
|
|
268
|
+
keyword=keyword,
|
|
269
|
+
column=self.process_column(clause.column),
|
|
270
|
+
)
|
|
271
|
+
else:
|
|
272
|
+
if qmark:
|
|
273
|
+
value = "?"
|
|
274
|
+
self.add_binding(clause.value)
|
|
275
|
+
else:
|
|
276
|
+
value = self._compile_value(clause.value)
|
|
277
|
+
on_string += f"{keyword} {self._table_column_string(clause.column)} {clause.equality} {value} "
|
|
278
|
+
|
|
279
|
+
sql += self.join_string().format(
|
|
280
|
+
foreign_table=self.process_table(join.table),
|
|
281
|
+
alias=(
|
|
282
|
+
f" AS {self.process_table(join.alias)}"
|
|
283
|
+
if join.alias
|
|
284
|
+
else ""
|
|
285
|
+
),
|
|
286
|
+
on=on_string,
|
|
287
|
+
keyword=self.join_keywords[join.clause],
|
|
288
|
+
)
|
|
289
|
+
sql += " "
|
|
290
|
+
|
|
291
|
+
return sql
|
|
292
|
+
|
|
293
|
+
# TODO: Clean
|
|
294
|
+
def _compile_key_value_equals(self, qmark=False):
|
|
295
|
+
"""Compiles key value pairs.
|
|
296
|
+
|
|
297
|
+
Keyword Arguments:
|
|
298
|
+
qmark {bool} -- Whether the query should use qmark. (default: {False})
|
|
299
|
+
|
|
300
|
+
Returns:
|
|
301
|
+
self
|
|
302
|
+
"""
|
|
303
|
+
sql = ""
|
|
304
|
+
for update in self._updates:
|
|
305
|
+
if update.update_type == "increment":
|
|
306
|
+
sql_string = self.increment_string()
|
|
307
|
+
elif update.update_type == "decrement":
|
|
308
|
+
sql_string = self.decrement_string()
|
|
309
|
+
else:
|
|
310
|
+
sql_string = self.key_value_string()
|
|
311
|
+
|
|
312
|
+
column = update.column
|
|
313
|
+
value = update.value
|
|
314
|
+
if isinstance(column, dict):
|
|
315
|
+
for key, value in column.items():
|
|
316
|
+
if hasattr(value, "expression"):
|
|
317
|
+
sql += self.column_value_string().format(
|
|
318
|
+
column=self._table_column_string(key),
|
|
319
|
+
value=value.expression,
|
|
320
|
+
separator=", ",
|
|
321
|
+
)
|
|
322
|
+
else:
|
|
323
|
+
sql += sql_string.format(
|
|
324
|
+
column=self._table_column_string(key),
|
|
325
|
+
value=(
|
|
326
|
+
self.value_string().format(
|
|
327
|
+
value=value, separator=""
|
|
328
|
+
)
|
|
329
|
+
if not qmark
|
|
330
|
+
else "?"
|
|
331
|
+
),
|
|
332
|
+
separator=", ",
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
if qmark:
|
|
336
|
+
self._bindings += (value,)
|
|
337
|
+
else:
|
|
338
|
+
sql += sql_string.format(
|
|
339
|
+
column=self._table_column_string(column),
|
|
340
|
+
value=(
|
|
341
|
+
self.value_string().format(value=value, separator=", ")
|
|
342
|
+
if not qmark
|
|
343
|
+
else "?"
|
|
344
|
+
),
|
|
345
|
+
separator=", ",
|
|
346
|
+
)
|
|
347
|
+
if qmark:
|
|
348
|
+
self._bindings += (value,)
|
|
349
|
+
|
|
350
|
+
sql = sql.rstrip(", ")
|
|
351
|
+
return sql
|
|
352
|
+
|
|
353
|
+
def process_aggregates(self):
|
|
354
|
+
"""Compiles aggregates to be used in a query expression.
|
|
355
|
+
|
|
356
|
+
Returns:
|
|
357
|
+
self
|
|
358
|
+
"""
|
|
359
|
+
sql = ""
|
|
360
|
+
for aggregates in self._aggregates:
|
|
361
|
+
aggregate = aggregates.aggregate
|
|
362
|
+
column = aggregates.column
|
|
363
|
+
aggregate_function = self.aggregate_options.get(aggregate, "")
|
|
364
|
+
if not aggregates.alias and column == "*":
|
|
365
|
+
aggregate_string = self.aggregate_string_without_alias()
|
|
366
|
+
else:
|
|
367
|
+
aggregate_string = self.aggregate_string_with_alias()
|
|
368
|
+
|
|
369
|
+
sql += (
|
|
370
|
+
aggregate_string.format(
|
|
371
|
+
aggregate_function=aggregate_function,
|
|
372
|
+
column=(
|
|
373
|
+
"*"
|
|
374
|
+
if column == "*"
|
|
375
|
+
else self._table_column_string(column)
|
|
376
|
+
),
|
|
377
|
+
alias=self.process_alias(aggregates.alias or column),
|
|
378
|
+
)
|
|
379
|
+
+ ", "
|
|
380
|
+
)
|
|
381
|
+
|
|
382
|
+
return sql
|
|
383
|
+
|
|
384
|
+
def process_order_by(self):
|
|
385
|
+
"""Compiles an order by for a query expression.
|
|
386
|
+
|
|
387
|
+
Returns:
|
|
388
|
+
self
|
|
389
|
+
"""
|
|
390
|
+
sql = ""
|
|
391
|
+
if self._order_by:
|
|
392
|
+
order_crit = ""
|
|
393
|
+
for order_bys in self._order_by:
|
|
394
|
+
if order_bys.raw:
|
|
395
|
+
order_crit += order_bys.column
|
|
396
|
+
if not isinstance(order_bys.bindings, (list, tuple)):
|
|
397
|
+
raise ValueError(
|
|
398
|
+
f"Bindings must be tuple or list. Received {type(order_bys.bindings)}"
|
|
399
|
+
)
|
|
400
|
+
|
|
401
|
+
if order_bys.bindings:
|
|
402
|
+
self.add_binding(*order_bys.bindings)
|
|
403
|
+
|
|
404
|
+
continue
|
|
405
|
+
|
|
406
|
+
if len(order_crit):
|
|
407
|
+
order_crit += ", "
|
|
408
|
+
column = order_bys.column
|
|
409
|
+
direction = order_bys.direction
|
|
410
|
+
if "." in column:
|
|
411
|
+
column_string = self._table_column_string(column)
|
|
412
|
+
else:
|
|
413
|
+
column_string = self.column_string().format(
|
|
414
|
+
column=column, separator=""
|
|
415
|
+
)
|
|
416
|
+
order_crit += self.order_by_format().format(
|
|
417
|
+
column=column_string, direction=direction.upper()
|
|
418
|
+
)
|
|
419
|
+
|
|
420
|
+
sql += self.order_by_string().format(order_columns=order_crit)
|
|
421
|
+
return sql
|
|
422
|
+
|
|
423
|
+
def process_group_by(self):
|
|
424
|
+
"""Compiles a group by for a query expression.
|
|
425
|
+
|
|
426
|
+
Returns:
|
|
427
|
+
self
|
|
428
|
+
"""
|
|
429
|
+
sql = ""
|
|
430
|
+
columns = []
|
|
431
|
+
for group_by in self._group_by:
|
|
432
|
+
if group_by.raw:
|
|
433
|
+
if group_by.bindings:
|
|
434
|
+
self.add_binding(*group_by.bindings)
|
|
435
|
+
|
|
436
|
+
sql += "GROUP BY " + group_by.column
|
|
437
|
+
return sql
|
|
438
|
+
|
|
439
|
+
else:
|
|
440
|
+
columns.append(self._table_column_string(group_by.column))
|
|
441
|
+
|
|
442
|
+
if columns:
|
|
443
|
+
sql += " GROUP BY {column}".format(column=", ".join(columns))
|
|
444
|
+
|
|
445
|
+
return sql
|
|
446
|
+
|
|
447
|
+
def process_alias(self, column):
|
|
448
|
+
"""Compiles an alias for a column.
|
|
449
|
+
|
|
450
|
+
Arguments:
|
|
451
|
+
column {string} -- The name of the column.
|
|
452
|
+
|
|
453
|
+
Returns:
|
|
454
|
+
self
|
|
455
|
+
"""
|
|
456
|
+
return column
|
|
457
|
+
|
|
458
|
+
def process_table(self, table):
|
|
459
|
+
"""Compiles a given table name.
|
|
460
|
+
|
|
461
|
+
Arguments:
|
|
462
|
+
table {string} -- The table name to compile.
|
|
463
|
+
|
|
464
|
+
Returns:
|
|
465
|
+
self
|
|
466
|
+
"""
|
|
467
|
+
if not table:
|
|
468
|
+
return ""
|
|
469
|
+
|
|
470
|
+
if isinstance(table, str):
|
|
471
|
+
return ".".join(
|
|
472
|
+
self.table_string().format(
|
|
473
|
+
table=t,
|
|
474
|
+
database=self._connection_details.get("database", ""),
|
|
475
|
+
prefix=self._connection_details.get("prefix", ""),
|
|
476
|
+
)
|
|
477
|
+
for t in table.split(".")
|
|
478
|
+
)
|
|
479
|
+
|
|
480
|
+
if table.raw:
|
|
481
|
+
return table.name
|
|
482
|
+
|
|
483
|
+
return ".".join(
|
|
484
|
+
self.table_string().format(
|
|
485
|
+
table=t,
|
|
486
|
+
database=self._connection_details.get("database", ""),
|
|
487
|
+
prefix=self._connection_details.get("prefix", ""),
|
|
488
|
+
)
|
|
489
|
+
for t in table.name.split(".")
|
|
490
|
+
)
|
|
491
|
+
|
|
492
|
+
def process_limit(self):
|
|
493
|
+
"""Compiles the limit expression.
|
|
494
|
+
|
|
495
|
+
Returns:
|
|
496
|
+
self
|
|
497
|
+
"""
|
|
498
|
+
if not self._limit:
|
|
499
|
+
return ""
|
|
500
|
+
|
|
501
|
+
return self.limit_string(offset=self._offset).format(limit=self._limit)
|
|
502
|
+
|
|
503
|
+
def process_offset(self):
|
|
504
|
+
"""Compiles the offset expression.
|
|
505
|
+
|
|
506
|
+
Returns:
|
|
507
|
+
self
|
|
508
|
+
"""
|
|
509
|
+
if not self._offset:
|
|
510
|
+
return ""
|
|
511
|
+
|
|
512
|
+
return self.offset_string().format(
|
|
513
|
+
offset=self._offset, limit=self._limit or 1
|
|
514
|
+
)
|
|
515
|
+
|
|
516
|
+
def process_locks(self):
|
|
517
|
+
return self.locks.get(self.lock, "")
|
|
518
|
+
|
|
519
|
+
def process_having(self, qmark=False):
|
|
520
|
+
"""Compiles having expression.
|
|
521
|
+
|
|
522
|
+
Keyword Arguments:
|
|
523
|
+
qmark {bool} -- Whether or not to use Qmark (default: {False})
|
|
524
|
+
|
|
525
|
+
Returns:
|
|
526
|
+
self
|
|
527
|
+
"""
|
|
528
|
+
sql = ""
|
|
529
|
+
for having in self._having:
|
|
530
|
+
column = having.column
|
|
531
|
+
equality = having.equality
|
|
532
|
+
value = having.value
|
|
533
|
+
raw = having.raw
|
|
534
|
+
|
|
535
|
+
if not equality and not value:
|
|
536
|
+
sql_string = self.having_string()
|
|
537
|
+
else:
|
|
538
|
+
sql_string = self.having_equality_string()
|
|
539
|
+
|
|
540
|
+
sql += sql_string.format(
|
|
541
|
+
column=(
|
|
542
|
+
self._table_column_string(column)
|
|
543
|
+
if raw is False
|
|
544
|
+
else column
|
|
545
|
+
),
|
|
546
|
+
equality=equality,
|
|
547
|
+
value=self._compile_value(value),
|
|
548
|
+
)
|
|
549
|
+
|
|
550
|
+
return sql
|
|
551
|
+
|
|
552
|
+
def process_wheres(self, qmark=False, strip_first_where=False):
|
|
553
|
+
"""Compiles the where expression.
|
|
554
|
+
|
|
555
|
+
Keyword Arguments:
|
|
556
|
+
qmark {bool} -- Whether or not to use Qmark. (default: {False})
|
|
557
|
+
strip_first_where {bool} -- Whether or not to strip out the first where keyword.
|
|
558
|
+
This is useful when using subselects (default: {False})
|
|
559
|
+
|
|
560
|
+
Returns:
|
|
561
|
+
self
|
|
562
|
+
"""
|
|
563
|
+
sql = ""
|
|
564
|
+
loop_count = 0
|
|
565
|
+
for where in self._wheres:
|
|
566
|
+
column = where.column
|
|
567
|
+
equality = where.equality
|
|
568
|
+
value = where.value
|
|
569
|
+
value_type = where.value_type
|
|
570
|
+
|
|
571
|
+
"""Need to get a specific keyword here. This keyword either needs to be
|
|
572
|
+
something like WHERE, AND, OR.
|
|
573
|
+
|
|
574
|
+
Depending on the loop depends on the placement of the AND
|
|
575
|
+
"""
|
|
576
|
+
if loop_count == 0:
|
|
577
|
+
if strip_first_where:
|
|
578
|
+
keyword = ""
|
|
579
|
+
else:
|
|
580
|
+
keyword = " " + self.first_where_string()
|
|
581
|
+
elif hasattr(where, "keyword") and where.keyword == "or":
|
|
582
|
+
keyword = " " + self.or_where_string()
|
|
583
|
+
else:
|
|
584
|
+
keyword = " " + self.additional_where_string()
|
|
585
|
+
|
|
586
|
+
if where.raw:
|
|
587
|
+
"""If we have a raw query we just want to use the query supplied
|
|
588
|
+
and don't need to compile anything.
|
|
589
|
+
"""
|
|
590
|
+
sql += self.raw_query_string().format(
|
|
591
|
+
keyword=keyword, query=where.column
|
|
592
|
+
)
|
|
593
|
+
|
|
594
|
+
if not isinstance(where.bindings, (list, tuple)):
|
|
595
|
+
raise ValueError(
|
|
596
|
+
f"Bindings must be tuple or list. Received {type(where.bindings)}"
|
|
597
|
+
)
|
|
598
|
+
|
|
599
|
+
if where.bindings:
|
|
600
|
+
self.add_binding(*where.bindings)
|
|
601
|
+
|
|
602
|
+
loop_count += 1
|
|
603
|
+
|
|
604
|
+
continue
|
|
605
|
+
|
|
606
|
+
"""The column is an easy compile
|
|
607
|
+
"""
|
|
608
|
+
column = self._table_column_string(column)
|
|
609
|
+
|
|
610
|
+
"""Need to find which type of where string it is.
|
|
611
|
+
If it is a WHERE NULL, WHERE EXISTS, WHERE `col` = 'val' etc
|
|
612
|
+
"""
|
|
613
|
+
equality = equality.upper()
|
|
614
|
+
|
|
615
|
+
if equality == "BETWEEN":
|
|
616
|
+
low = where.low
|
|
617
|
+
high = where.high
|
|
618
|
+
if qmark:
|
|
619
|
+
self.add_binding(low)
|
|
620
|
+
self.add_binding(high)
|
|
621
|
+
|
|
622
|
+
sql_string = self.between_string().format(
|
|
623
|
+
low=self._compile_value(low) if not qmark else "?",
|
|
624
|
+
high=self._compile_value(high) if not qmark else "?",
|
|
625
|
+
column=self._table_column_string(where.column),
|
|
626
|
+
keyword=keyword,
|
|
627
|
+
)
|
|
628
|
+
elif equality == "NOT BETWEEN":
|
|
629
|
+
low = where.low
|
|
630
|
+
high = where.high
|
|
631
|
+
if qmark:
|
|
632
|
+
self.add_binding(low)
|
|
633
|
+
self.add_binding(high)
|
|
634
|
+
|
|
635
|
+
sql_string = self.not_between_string().format(
|
|
636
|
+
low=self._compile_value(low) if not qmark else "?",
|
|
637
|
+
high=self._compile_value(high) if not qmark else "?",
|
|
638
|
+
column=self._table_column_string(where.column),
|
|
639
|
+
keyword=keyword,
|
|
640
|
+
)
|
|
641
|
+
elif value_type == "value_equals":
|
|
642
|
+
sql_string = self.value_equal_string().format(
|
|
643
|
+
value1=where.column, value2=where.value, keyword=keyword
|
|
644
|
+
)
|
|
645
|
+
elif value_type == "NULL":
|
|
646
|
+
sql_string = self.where_null_string()
|
|
647
|
+
elif value_type == "DATE":
|
|
648
|
+
sql_string = self.where_date_string()
|
|
649
|
+
elif value_type == "NOT NULL":
|
|
650
|
+
sql_string = self.where_not_null_string()
|
|
651
|
+
elif equality == "EXISTS":
|
|
652
|
+
sql_string = self.where_exists_string()
|
|
653
|
+
elif equality == "NOT EXISTS":
|
|
654
|
+
sql_string = self.where_not_exists_string()
|
|
655
|
+
elif equality == "LIKE":
|
|
656
|
+
sql_string = self.where_like_string()
|
|
657
|
+
elif equality == "REGEXP":
|
|
658
|
+
sql_string = self.where_regexp_string()
|
|
659
|
+
elif equality == "NOT REGEXP":
|
|
660
|
+
sql_string = self.where_not_regexp_string()
|
|
661
|
+
elif equality == "NOT LIKE":
|
|
662
|
+
sql_string = self.where_not_like_string()
|
|
663
|
+
else:
|
|
664
|
+
sql_string = self.where_string()
|
|
665
|
+
|
|
666
|
+
"""If the value should actually be a sub query then we need to wrap it in a query here
|
|
667
|
+
"""
|
|
668
|
+
if isinstance(value, SubGroupExpression):
|
|
669
|
+
grammar = value.builder.get_grammar()
|
|
670
|
+
query_value = (
|
|
671
|
+
self.subquery_string()
|
|
672
|
+
.format(
|
|
673
|
+
query=grammar.process_wheres(
|
|
674
|
+
qmark=qmark, strip_first_where=True
|
|
675
|
+
)
|
|
676
|
+
)
|
|
677
|
+
.replace("( ", "(")
|
|
678
|
+
)
|
|
679
|
+
if grammar._bindings:
|
|
680
|
+
self.add_binding(*grammar._bindings)
|
|
681
|
+
sql_string = self.where_group_string()
|
|
682
|
+
elif isinstance(value, SubSelectExpression):
|
|
683
|
+
if qmark:
|
|
684
|
+
query_from_builder = value.builder.to_qmark()
|
|
685
|
+
if value.builder._bindings:
|
|
686
|
+
self.add_binding(*value.builder._bindings)
|
|
687
|
+
else:
|
|
688
|
+
query_from_builder = value.builder.to_sql()
|
|
689
|
+
query_value = self.subquery_string().format(
|
|
690
|
+
query=query_from_builder
|
|
691
|
+
)
|
|
692
|
+
elif isinstance(value, list):
|
|
693
|
+
query_value = "("
|
|
694
|
+
for val in value:
|
|
695
|
+
if qmark:
|
|
696
|
+
query_value += "?, "
|
|
697
|
+
self.add_binding(val)
|
|
698
|
+
else:
|
|
699
|
+
query_value += self.value_string().format(
|
|
700
|
+
value=val, separator=","
|
|
701
|
+
)
|
|
702
|
+
query_value = query_value.rstrip(",").rstrip(", ") + ")"
|
|
703
|
+
elif value is True and value_type != "NOT NULL":
|
|
704
|
+
sql_string = self.get_true_column_string()
|
|
705
|
+
query_value = 1
|
|
706
|
+
elif value is False and value_type != "NOT NULL":
|
|
707
|
+
sql_string = self.get_false_column_string()
|
|
708
|
+
query_value = 0
|
|
709
|
+
elif qmark and value_type != "column":
|
|
710
|
+
query_value = "?"
|
|
711
|
+
if (
|
|
712
|
+
value is not True
|
|
713
|
+
and value_type != "value_equals"
|
|
714
|
+
and value_type != "NULL"
|
|
715
|
+
and value_type != "BETWEEN"
|
|
716
|
+
):
|
|
717
|
+
self.add_binding(value)
|
|
718
|
+
elif value_type == "value":
|
|
719
|
+
if qmark:
|
|
720
|
+
query_value = "?"
|
|
721
|
+
else:
|
|
722
|
+
query_value = self.value_string().format(
|
|
723
|
+
value=value, separator=""
|
|
724
|
+
)
|
|
725
|
+
|
|
726
|
+
self.add_binding(value)
|
|
727
|
+
elif value_type == "column":
|
|
728
|
+
query_value = self._table_column_string(
|
|
729
|
+
column=value, separator=""
|
|
730
|
+
)
|
|
731
|
+
elif value_type == "DATE":
|
|
732
|
+
query_value = self.value_string().format(
|
|
733
|
+
value=value, separator=""
|
|
734
|
+
)
|
|
735
|
+
elif value_type == "having":
|
|
736
|
+
query_value = self._table_column_string(
|
|
737
|
+
column=value, separator=""
|
|
738
|
+
)
|
|
739
|
+
else:
|
|
740
|
+
query_value = ""
|
|
741
|
+
|
|
742
|
+
sql += sql_string.format(
|
|
743
|
+
keyword=keyword,
|
|
744
|
+
column=column,
|
|
745
|
+
equality=equality,
|
|
746
|
+
value=query_value,
|
|
747
|
+
)
|
|
748
|
+
|
|
749
|
+
loop_count += 1
|
|
750
|
+
|
|
751
|
+
return sql
|
|
752
|
+
|
|
753
|
+
def get_true_column_string(self):
|
|
754
|
+
return "{keyword} {column} = '1'"
|
|
755
|
+
|
|
756
|
+
def get_false_column_string(self):
|
|
757
|
+
return "{keyword} {column} = '0'"
|
|
758
|
+
|
|
759
|
+
def add_binding(self, *bindings):
|
|
760
|
+
"""Adds one or more bindings to the bindings tuple.
|
|
761
|
+
|
|
762
|
+
Arguments:
|
|
763
|
+
binding {string} -- A value to bind.
|
|
764
|
+
"""
|
|
765
|
+
self._bindings += bindings
|
|
766
|
+
|
|
767
|
+
def column_exists(self, column):
|
|
768
|
+
"""Check if a column exists
|
|
769
|
+
|
|
770
|
+
Arguments:
|
|
771
|
+
column {string} -- The name of the column to check for existence.
|
|
772
|
+
|
|
773
|
+
Returns:
|
|
774
|
+
self
|
|
775
|
+
"""
|
|
776
|
+
self._column = column
|
|
777
|
+
self._sql = self.process_exists()
|
|
778
|
+
return self
|
|
779
|
+
|
|
780
|
+
def table_exists(self):
|
|
781
|
+
"""Checks if a table exists.
|
|
782
|
+
|
|
783
|
+
Returns:
|
|
784
|
+
self
|
|
785
|
+
"""
|
|
786
|
+
self._sql = self.table_exists_string().format(
|
|
787
|
+
table=self.process_table(self.table),
|
|
788
|
+
database=self.database,
|
|
789
|
+
clean_table=self.table,
|
|
790
|
+
)
|
|
791
|
+
return self
|
|
792
|
+
|
|
793
|
+
def wrap_table(self, table_name):
|
|
794
|
+
return self.table_string().format(table=table_name)
|
|
795
|
+
|
|
796
|
+
def process_exists(self):
|
|
797
|
+
"""Specifies the column exists expression.
|
|
798
|
+
|
|
799
|
+
Returns:
|
|
800
|
+
self
|
|
801
|
+
"""
|
|
802
|
+
return self.column_exists_string().format(
|
|
803
|
+
table=self.process_table(self.table),
|
|
804
|
+
clean_table=self.table,
|
|
805
|
+
value=self._compile_value(self._column),
|
|
806
|
+
)
|
|
807
|
+
|
|
808
|
+
def to_sql(self):
|
|
809
|
+
"""Cleans up the SQL string and returns the SQL
|
|
810
|
+
|
|
811
|
+
Returns:
|
|
812
|
+
string
|
|
813
|
+
"""
|
|
814
|
+
return re.sub(" +", " ", self._sql.strip())
|
|
815
|
+
|
|
816
|
+
def to_qmark(self):
|
|
817
|
+
"""Cleans up the SQL string and returns the SQL
|
|
818
|
+
|
|
819
|
+
Returns:
|
|
820
|
+
string
|
|
821
|
+
"""
|
|
822
|
+
return re.sub(" +", " ", self._sql.strip())
|
|
823
|
+
|
|
824
|
+
# TODO: Inspect this can't just be used by another method. seems duplicative
|
|
825
|
+
def process_columns(self, separator="", action="select", qmark=False):
|
|
826
|
+
"""Specifies the columns in a selection expression.
|
|
827
|
+
|
|
828
|
+
Keyword Arguments:
|
|
829
|
+
separator {str} -- The separator used between columns (default: {""})
|
|
830
|
+
|
|
831
|
+
Returns:
|
|
832
|
+
self
|
|
833
|
+
"""
|
|
834
|
+
sql = ""
|
|
835
|
+
for column in self._columns:
|
|
836
|
+
alias = None
|
|
837
|
+
if isinstance(column, SelectExpression):
|
|
838
|
+
alias = column.alias
|
|
839
|
+
if column.raw:
|
|
840
|
+
sql += column.column + ", "
|
|
841
|
+
continue
|
|
842
|
+
|
|
843
|
+
column = column.column
|
|
844
|
+
|
|
845
|
+
if isinstance(column, SubGroupExpression):
|
|
846
|
+
if qmark:
|
|
847
|
+
builder_sql = column.builder.to_qmark()
|
|
848
|
+
if column.builder._bindings:
|
|
849
|
+
self.add_binding(*column.builder._bindings)
|
|
850
|
+
else:
|
|
851
|
+
builder_sql = column.builder.to_sql()
|
|
852
|
+
sql += f"({builder_sql}) AS {column.alias}, "
|
|
853
|
+
continue
|
|
854
|
+
|
|
855
|
+
sql += self._table_column_string(
|
|
856
|
+
column, alias=alias, separator=separator
|
|
857
|
+
)
|
|
858
|
+
|
|
859
|
+
if self._aggregates:
|
|
860
|
+
sql += self.process_aggregates()
|
|
861
|
+
|
|
862
|
+
if sql == "":
|
|
863
|
+
return "*"
|
|
864
|
+
|
|
865
|
+
return sql.rstrip(",").rstrip(", ")
|
|
866
|
+
|
|
867
|
+
# TODO: Duplicative?
|
|
868
|
+
def process_values(self, separator="", qmark=False):
|
|
869
|
+
"""Compiles column values for insert expressions.
|
|
870
|
+
|
|
871
|
+
Keyword Arguments:
|
|
872
|
+
separator {str} -- The separator used between columns (default: {""})
|
|
873
|
+
|
|
874
|
+
Returns:
|
|
875
|
+
self
|
|
876
|
+
"""
|
|
877
|
+
sql = ""
|
|
878
|
+
if self._columns == "*":
|
|
879
|
+
return self._columns
|
|
880
|
+
elif isinstance(self._columns, list):
|
|
881
|
+
for c in self._columns:
|
|
882
|
+
for column, value in dict(c).items():
|
|
883
|
+
if qmark:
|
|
884
|
+
self.add_binding(value)
|
|
885
|
+
sql += f"?{separator}".strip()
|
|
886
|
+
else:
|
|
887
|
+
sql += self._compile_value(value, separator=separator)
|
|
888
|
+
else:
|
|
889
|
+
for column, value in dict(self._columns).items():
|
|
890
|
+
if qmark:
|
|
891
|
+
self.add_binding(value)
|
|
892
|
+
sql += f"?{separator}".strip()
|
|
893
|
+
else:
|
|
894
|
+
sql += self._compile_value(value, separator=separator)
|
|
895
|
+
|
|
896
|
+
if not qmark:
|
|
897
|
+
return sql[:-2]
|
|
898
|
+
|
|
899
|
+
return sql.rstrip(separator.strip())
|
|
900
|
+
|
|
901
|
+
def process_column(self, column, separator=""):
|
|
902
|
+
"""Compiles a column into the column syntax.
|
|
903
|
+
|
|
904
|
+
Arguments:
|
|
905
|
+
column {string} -- The name of the column.
|
|
906
|
+
|
|
907
|
+
Keyword Arguments:
|
|
908
|
+
separator {string} -- The separator used between columns (default: {""})
|
|
909
|
+
|
|
910
|
+
Returns:
|
|
911
|
+
self
|
|
912
|
+
"""
|
|
913
|
+
table = None
|
|
914
|
+
if column and "." in column:
|
|
915
|
+
table, column = column.split(".")
|
|
916
|
+
return self.column_string().format(
|
|
917
|
+
column=column, separator=separator, table=table or self.table
|
|
918
|
+
)
|
|
919
|
+
|
|
920
|
+
def _table_column_string(self, column, alias=None, separator=""):
|
|
921
|
+
"""Compiles a column into the column syntax.
|
|
922
|
+
|
|
923
|
+
Arguments:
|
|
924
|
+
column {string} -- The name of the column.
|
|
925
|
+
|
|
926
|
+
Keyword Arguments:
|
|
927
|
+
separator {string} -- The separator used between columns (default: {""})
|
|
928
|
+
|
|
929
|
+
Returns:
|
|
930
|
+
self
|
|
931
|
+
"""
|
|
932
|
+
table = None
|
|
933
|
+
if column and "." in column:
|
|
934
|
+
table, column = column.split(".")
|
|
935
|
+
|
|
936
|
+
if column == "*":
|
|
937
|
+
return self.column_strings.get("select_all").format(
|
|
938
|
+
column=column,
|
|
939
|
+
separator=separator,
|
|
940
|
+
table=self.process_table(table or self.table),
|
|
941
|
+
)
|
|
942
|
+
|
|
943
|
+
if alias:
|
|
944
|
+
alias_string = self.subquery_alias_string().format(alias=alias)
|
|
945
|
+
return self.column_strings.get(self._action).format(
|
|
946
|
+
column=column,
|
|
947
|
+
separator=separator,
|
|
948
|
+
alias=" " + alias_string if alias else "",
|
|
949
|
+
table=self.process_table(table or self.table),
|
|
950
|
+
)
|
|
951
|
+
|
|
952
|
+
def _compile_value(self, value, separator=""):
|
|
953
|
+
"""Compiles a value using the value syntax.
|
|
954
|
+
|
|
955
|
+
Arguments:
|
|
956
|
+
value {string} -- The value to compile.
|
|
957
|
+
|
|
958
|
+
Keyword Arguments:
|
|
959
|
+
separator {string} -- The separator used between columns (default: {""})
|
|
960
|
+
|
|
961
|
+
Returns:
|
|
962
|
+
self
|
|
963
|
+
"""
|
|
964
|
+
return self.value_string().format(value=value, separator=separator)
|
|
965
|
+
|
|
966
|
+
def drop_table(self, table):
|
|
967
|
+
"""Specifies a drop table expression.
|
|
968
|
+
|
|
969
|
+
Arguments:
|
|
970
|
+
table {string} -- The table to drop.
|
|
971
|
+
|
|
972
|
+
Returns:
|
|
973
|
+
self
|
|
974
|
+
"""
|
|
975
|
+
self._sql = self.drop_table_string().format(
|
|
976
|
+
table=self.process_column(table)
|
|
977
|
+
)
|
|
978
|
+
return self
|
|
979
|
+
|
|
980
|
+
def drop_table_if_exists(self, table):
|
|
981
|
+
"""Specifies a drop table if exists expression.
|
|
982
|
+
|
|
983
|
+
Arguments:
|
|
984
|
+
table {string} -- The name of the table to drop.
|
|
985
|
+
|
|
986
|
+
Returns:
|
|
987
|
+
self
|
|
988
|
+
"""
|
|
989
|
+
self._sql = self.drop_table_if_exists_string().format(
|
|
990
|
+
table=self.process_column(table)
|
|
991
|
+
)
|
|
992
|
+
return self
|
|
993
|
+
|
|
994
|
+
def rename_table(self, current_table_name, new_table_name):
|
|
995
|
+
"""Specifies a rename table expression.
|
|
996
|
+
|
|
997
|
+
Arguments:
|
|
998
|
+
current_table_name {string} -- The name of the table currently.
|
|
999
|
+
new_table_name {string} -- The name you want to use now for the table.
|
|
1000
|
+
|
|
1001
|
+
Returns:
|
|
1002
|
+
self
|
|
1003
|
+
"""
|
|
1004
|
+
self._sql = self.rename_table_string().format(
|
|
1005
|
+
current_table_name=self.process_column(current_table_name),
|
|
1006
|
+
new_table_name=self.process_column(new_table_name),
|
|
1007
|
+
)
|
|
1008
|
+
return self
|
|
1009
|
+
|
|
1010
|
+
def truncate_table(self, table, foreign_keys=False):
|
|
1011
|
+
"""Specifies a truncate table expression.
|
|
1012
|
+
|
|
1013
|
+
Arguments;
|
|
1014
|
+
table {string} -- The name of the table to truncate.
|
|
1015
|
+
|
|
1016
|
+
Returns:
|
|
1017
|
+
self
|
|
1018
|
+
"""
|
|
1019
|
+
raise NotImplementedError(
|
|
1020
|
+
f"'{self.__class__.__name__}' does not support truncating"
|
|
1021
|
+
)
|
|
1022
|
+
|
|
1023
|
+
def where_regexp_string(self):
|
|
1024
|
+
return "{keyword} {column} REGEXP {value}"
|
|
1025
|
+
|
|
1026
|
+
def where_not_regexp_string(self):
|
|
1027
|
+
return "{keyword} {column} NOT REGEXP {value}"
|