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,513 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
3
|
+
from ...schema import Schema
|
|
4
|
+
from ..Table import Table
|
|
5
|
+
from .Platform import Platform
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class MySQLPlatform(Platform):
|
|
9
|
+
types_without_lengths = ["enum"]
|
|
10
|
+
|
|
11
|
+
type_map = {
|
|
12
|
+
"string": "VARCHAR",
|
|
13
|
+
"char": "CHAR",
|
|
14
|
+
"integer": "INT",
|
|
15
|
+
"big_integer": "BIGINT",
|
|
16
|
+
"tiny_integer": "TINYINT",
|
|
17
|
+
"small_integer": "SMALLINT",
|
|
18
|
+
"medium_integer": "MEDIUMINT",
|
|
19
|
+
"integer_unsigned": "INT UNSIGNED",
|
|
20
|
+
"big_integer_unsigned": "BIGINT UNSIGNED",
|
|
21
|
+
"tiny_integer_unsigned": "TINYINT UNSIGNED",
|
|
22
|
+
"small_integer_unsigned": "SMALLINT UNSIGNED",
|
|
23
|
+
"medium_integer_unsigned": "MEDIUMINT UNSIGNED",
|
|
24
|
+
"big_increments": "BIGINT UNSIGNED AUTO_INCREMENT",
|
|
25
|
+
"increments": "INT UNSIGNED AUTO_INCREMENT",
|
|
26
|
+
"uuid": "CHAR",
|
|
27
|
+
"binary": "LONGBLOB",
|
|
28
|
+
"boolean": "BOOLEAN",
|
|
29
|
+
"decimal": "DECIMAL",
|
|
30
|
+
"double": "DOUBLE",
|
|
31
|
+
"enum": "ENUM",
|
|
32
|
+
"text": "TEXT",
|
|
33
|
+
"tiny_text": "TINYTEXT",
|
|
34
|
+
"float": "FLOAT",
|
|
35
|
+
"geometry": "GEOMETRY",
|
|
36
|
+
"json": "JSON",
|
|
37
|
+
"jsonb": "LONGBLOB",
|
|
38
|
+
"inet": "VARCHAR",
|
|
39
|
+
"cidr": "VARCHAR",
|
|
40
|
+
"macaddr": "VARCHAR",
|
|
41
|
+
"long_text": "LONGTEXT",
|
|
42
|
+
"point": "POINT",
|
|
43
|
+
"time": "TIME",
|
|
44
|
+
"timestamp": "TIMESTAMP",
|
|
45
|
+
"date": "DATE",
|
|
46
|
+
"year": "YEAR",
|
|
47
|
+
"datetime": "DATETIME",
|
|
48
|
+
"tiny_increments": "TINYINT AUTO_INCREMENT",
|
|
49
|
+
"unsigned": "INT UNSIGNED",
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
premapped_nulls = {True: "NULL", False: "NOT NULL"}
|
|
53
|
+
|
|
54
|
+
premapped_defaults = {
|
|
55
|
+
"current": " DEFAULT CURRENT_TIMESTAMP",
|
|
56
|
+
"now": " DEFAULT NOW()",
|
|
57
|
+
"null": " DEFAULT NULL",
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
signed = {"unsigned": "UNSIGNED", "signed": "SIGNED"}
|
|
61
|
+
|
|
62
|
+
def columnize(self, columns):
|
|
63
|
+
sql = []
|
|
64
|
+
for name, column in columns.items():
|
|
65
|
+
if column.length:
|
|
66
|
+
length = self.create_column_length(column.column_type).format(
|
|
67
|
+
length=column.length
|
|
68
|
+
)
|
|
69
|
+
else:
|
|
70
|
+
length = ""
|
|
71
|
+
|
|
72
|
+
if column.default == "":
|
|
73
|
+
default = " DEFAULT ''"
|
|
74
|
+
elif column.default in (0,):
|
|
75
|
+
default = f" DEFAULT {column.default}"
|
|
76
|
+
elif column.default in self.premapped_defaults.keys():
|
|
77
|
+
default = self.premapped_defaults.get(column.default)
|
|
78
|
+
elif column.default:
|
|
79
|
+
if (
|
|
80
|
+
isinstance(column.default, (str,))
|
|
81
|
+
and not column.default_is_raw
|
|
82
|
+
):
|
|
83
|
+
default = f" DEFAULT '{column.default}'"
|
|
84
|
+
else:
|
|
85
|
+
default = f" DEFAULT {column.default}"
|
|
86
|
+
else:
|
|
87
|
+
default = ""
|
|
88
|
+
|
|
89
|
+
constraint = ""
|
|
90
|
+
column_constraint = ""
|
|
91
|
+
if column.primary:
|
|
92
|
+
constraint = "PRIMARY KEY"
|
|
93
|
+
|
|
94
|
+
if column.column_type == "enum":
|
|
95
|
+
values = ", ".join(f"'{x}'" for x in column.values)
|
|
96
|
+
column_constraint = f"({values})"
|
|
97
|
+
sql.append(
|
|
98
|
+
self.columnize_string()
|
|
99
|
+
.format(
|
|
100
|
+
name=self.get_column_string().format(column=column.name),
|
|
101
|
+
data_type=self.type_map.get(column.column_type, ""),
|
|
102
|
+
column_constraint=column_constraint,
|
|
103
|
+
length=length,
|
|
104
|
+
constraint=constraint,
|
|
105
|
+
nullable=self.premapped_nulls.get(column.is_null) or "",
|
|
106
|
+
default=default,
|
|
107
|
+
signed=(
|
|
108
|
+
" " + self.signed.get(column._signed)
|
|
109
|
+
if column._signed
|
|
110
|
+
else ""
|
|
111
|
+
),
|
|
112
|
+
comment=(
|
|
113
|
+
"COMMENT '" + column.comment + "'"
|
|
114
|
+
if column.comment
|
|
115
|
+
else ""
|
|
116
|
+
),
|
|
117
|
+
)
|
|
118
|
+
.strip()
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
return sql
|
|
122
|
+
|
|
123
|
+
def compile_create_sql(self, table, if_not_exists=False):
|
|
124
|
+
sql = []
|
|
125
|
+
table_create_format = (
|
|
126
|
+
self.create_if_not_exists_format()
|
|
127
|
+
if if_not_exists
|
|
128
|
+
else self.create_format()
|
|
129
|
+
)
|
|
130
|
+
sql.append(
|
|
131
|
+
table_create_format.format(
|
|
132
|
+
table=self.get_table_string().format(table=table.name),
|
|
133
|
+
columns=", ".join(
|
|
134
|
+
self.columnize(table.get_added_columns())
|
|
135
|
+
).strip(),
|
|
136
|
+
constraints=(
|
|
137
|
+
", "
|
|
138
|
+
+ ", ".join(
|
|
139
|
+
self.constraintize(
|
|
140
|
+
table.get_added_constraints(), table
|
|
141
|
+
)
|
|
142
|
+
)
|
|
143
|
+
if table.get_added_constraints()
|
|
144
|
+
else ""
|
|
145
|
+
),
|
|
146
|
+
foreign_keys=(
|
|
147
|
+
", "
|
|
148
|
+
+ ", ".join(
|
|
149
|
+
self.foreign_key_constraintize(
|
|
150
|
+
table.name, table.added_foreign_keys
|
|
151
|
+
)
|
|
152
|
+
)
|
|
153
|
+
if table.added_foreign_keys
|
|
154
|
+
else ""
|
|
155
|
+
),
|
|
156
|
+
comment=f" COMMENT '{table.comment}'" if table.comment else "",
|
|
157
|
+
)
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
if table.added_indexes:
|
|
161
|
+
for name, index in table.added_indexes.items():
|
|
162
|
+
sql.append(
|
|
163
|
+
"CREATE INDEX {name} ON {table}({column})".format(
|
|
164
|
+
name=index.name,
|
|
165
|
+
table=self.wrap_table(table.name),
|
|
166
|
+
column=",".join(index.column),
|
|
167
|
+
)
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
return sql
|
|
171
|
+
|
|
172
|
+
def compile_alter_sql(self, table):
|
|
173
|
+
sql = []
|
|
174
|
+
|
|
175
|
+
if table.added_columns:
|
|
176
|
+
add_columns = []
|
|
177
|
+
|
|
178
|
+
for name, column in table.get_added_columns().items():
|
|
179
|
+
if column.length:
|
|
180
|
+
length = self.create_column_length(
|
|
181
|
+
column.column_type
|
|
182
|
+
).format(length=column.length)
|
|
183
|
+
else:
|
|
184
|
+
length = ""
|
|
185
|
+
|
|
186
|
+
default = ""
|
|
187
|
+
if column.default in (0,):
|
|
188
|
+
default = f" DEFAULT {column.default}"
|
|
189
|
+
elif column.default in self.premapped_defaults.keys():
|
|
190
|
+
default = self.premapped_defaults.get(column.default)
|
|
191
|
+
elif column.default:
|
|
192
|
+
if isinstance(column.default, (str,)):
|
|
193
|
+
default = f" DEFAULT '{column.default}'"
|
|
194
|
+
else:
|
|
195
|
+
default = f" DEFAULT {column.default}"
|
|
196
|
+
else:
|
|
197
|
+
default = ""
|
|
198
|
+
|
|
199
|
+
column_constraint = ""
|
|
200
|
+
if column.column_type == "enum":
|
|
201
|
+
values = ", ".join(f"'{x}'" for x in column.values)
|
|
202
|
+
column_constraint = f"({values})"
|
|
203
|
+
add_columns.append(
|
|
204
|
+
self.add_column_string()
|
|
205
|
+
.format(
|
|
206
|
+
name=self.get_column_string().format(
|
|
207
|
+
column=column.name
|
|
208
|
+
),
|
|
209
|
+
data_type=self.type_map.get(column.column_type, ""),
|
|
210
|
+
column_constraint=column_constraint,
|
|
211
|
+
length=length,
|
|
212
|
+
constraint="PRIMARY KEY" if column.primary else "",
|
|
213
|
+
nullable="NULL" if column.is_null else "NOT NULL",
|
|
214
|
+
default=default,
|
|
215
|
+
signed=(
|
|
216
|
+
" " + self.signed.get(column._signed)
|
|
217
|
+
if column._signed
|
|
218
|
+
else ""
|
|
219
|
+
),
|
|
220
|
+
after=(
|
|
221
|
+
(" AFTER " + self.wrap_column(column._after))
|
|
222
|
+
if column._after
|
|
223
|
+
else ""
|
|
224
|
+
),
|
|
225
|
+
comment=(
|
|
226
|
+
" COMMENT '" + column.comment + "'"
|
|
227
|
+
if column.comment
|
|
228
|
+
else ""
|
|
229
|
+
),
|
|
230
|
+
)
|
|
231
|
+
.strip()
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
sql.append(
|
|
235
|
+
self.alter_format().format(
|
|
236
|
+
table=self.wrap_table(table.name),
|
|
237
|
+
columns=", ".join(add_columns).strip(),
|
|
238
|
+
comment=(
|
|
239
|
+
f" COMMENT '{table.comment}'" if table.comment else ""
|
|
240
|
+
),
|
|
241
|
+
)
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
if table.renamed_columns:
|
|
245
|
+
renamed_sql = []
|
|
246
|
+
|
|
247
|
+
for name, column in table.get_renamed_columns().items():
|
|
248
|
+
if column.length:
|
|
249
|
+
length = self.create_column_length(
|
|
250
|
+
column.column_type
|
|
251
|
+
).format(length=column.length)
|
|
252
|
+
else:
|
|
253
|
+
length = ""
|
|
254
|
+
|
|
255
|
+
renamed_sql.append(
|
|
256
|
+
self.rename_column_string()
|
|
257
|
+
.format(
|
|
258
|
+
to=self.columnize({column.name: column})[0],
|
|
259
|
+
old=self.get_column_string().format(column=name),
|
|
260
|
+
)
|
|
261
|
+
.strip()
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
sql.append(
|
|
265
|
+
self.alter_format().format(
|
|
266
|
+
table=self.wrap_table(table.name),
|
|
267
|
+
columns=", ".join(renamed_sql).strip(),
|
|
268
|
+
)
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
if table.changed_columns:
|
|
272
|
+
sql.append(
|
|
273
|
+
self.alter_format().format(
|
|
274
|
+
table=self.wrap_table(table.name),
|
|
275
|
+
columns=", ".join(
|
|
276
|
+
f"MODIFY {x}"
|
|
277
|
+
for x in self.columnize(table.changed_columns)
|
|
278
|
+
),
|
|
279
|
+
)
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
if table.dropped_columns:
|
|
283
|
+
dropped_sql = []
|
|
284
|
+
|
|
285
|
+
for name in table.get_dropped_columns():
|
|
286
|
+
dropped_sql.append(
|
|
287
|
+
self.drop_column_string()
|
|
288
|
+
.format(name=self.get_column_string().format(column=name))
|
|
289
|
+
.strip()
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
sql.append(
|
|
293
|
+
self.alter_format().format(
|
|
294
|
+
table=self.wrap_table(table.name),
|
|
295
|
+
columns=", ".join(dropped_sql),
|
|
296
|
+
)
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
if table.added_foreign_keys:
|
|
300
|
+
for (
|
|
301
|
+
column,
|
|
302
|
+
foreign_key_constraint,
|
|
303
|
+
) in table.get_added_foreign_keys().items():
|
|
304
|
+
cascade = ""
|
|
305
|
+
if foreign_key_constraint.delete_action:
|
|
306
|
+
cascade += f" ON DELETE {self.foreign_key_actions.get(foreign_key_constraint.delete_action.lower())}"
|
|
307
|
+
if foreign_key_constraint.update_action:
|
|
308
|
+
cascade += f" ON UPDATE {self.foreign_key_actions.get(foreign_key_constraint.update_action.lower())}"
|
|
309
|
+
sql.append(
|
|
310
|
+
f"ALTER TABLE {self.wrap_table(table.name)} ADD "
|
|
311
|
+
+ self.get_foreign_key_constraint_string().format(
|
|
312
|
+
column=column,
|
|
313
|
+
constraint_name=foreign_key_constraint.constraint_name,
|
|
314
|
+
table=table.name,
|
|
315
|
+
foreign_table=foreign_key_constraint.foreign_table,
|
|
316
|
+
foreign_column=foreign_key_constraint.foreign_column,
|
|
317
|
+
cascade=cascade,
|
|
318
|
+
)
|
|
319
|
+
)
|
|
320
|
+
|
|
321
|
+
if table.dropped_foreign_keys:
|
|
322
|
+
constraints = table.dropped_foreign_keys
|
|
323
|
+
for constraint in constraints:
|
|
324
|
+
sql.append(
|
|
325
|
+
f"ALTER TABLE {self.wrap_table(table.name)} DROP FOREIGN KEY {constraint}"
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
if table.added_indexes:
|
|
329
|
+
for name, index in table.added_indexes.items():
|
|
330
|
+
sql.append(
|
|
331
|
+
"CREATE INDEX {name} ON {table}({column})".format(
|
|
332
|
+
name=index.name,
|
|
333
|
+
table=self.wrap_table(table.name),
|
|
334
|
+
column=",".join(index.column),
|
|
335
|
+
)
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
if table.added_constraints:
|
|
339
|
+
for name, constraint in table.added_constraints.items():
|
|
340
|
+
if constraint.constraint_type == "unique":
|
|
341
|
+
sql.append(
|
|
342
|
+
f"ALTER TABLE {self.wrap_table(table.name)} ADD CONSTRAINT UNIQUE INDEX {constraint.name}({','.join(constraint.columns)})"
|
|
343
|
+
)
|
|
344
|
+
elif constraint.constraint_type == "fulltext":
|
|
345
|
+
sql.append(
|
|
346
|
+
f"ALTER TABLE {self.wrap_table(table.name)} ADD FULLTEXT {constraint.name}({','.join(constraint.columns)})"
|
|
347
|
+
)
|
|
348
|
+
elif constraint.constraint_type == "primary_key":
|
|
349
|
+
sql.append(
|
|
350
|
+
f"ALTER TABLE {self.wrap_table(table.name)} ADD CONSTRAINT {constraint.name} PRIMARY KEY ({','.join(constraint.columns)})"
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
if (
|
|
354
|
+
table.removed_indexes
|
|
355
|
+
or table.removed_unique_indexes
|
|
356
|
+
or table.dropped_primary_keys
|
|
357
|
+
):
|
|
358
|
+
constraints = table.removed_indexes
|
|
359
|
+
constraints += table.removed_unique_indexes
|
|
360
|
+
constraints += table.dropped_primary_keys
|
|
361
|
+
for constraint in constraints:
|
|
362
|
+
sql.append(
|
|
363
|
+
f"ALTER TABLE {self.wrap_table(table.name)} DROP INDEX {constraint}"
|
|
364
|
+
)
|
|
365
|
+
if table.comment:
|
|
366
|
+
sql.append(
|
|
367
|
+
f"ALTER TABLE {self.wrap_table(table.name)} COMMENT '{table.comment}'"
|
|
368
|
+
)
|
|
369
|
+
return sql
|
|
370
|
+
|
|
371
|
+
def add_column_string(self):
|
|
372
|
+
return "ADD {name} {data_type}{length}{column_constraint}{signed} {nullable}{default}{after}{comment}"
|
|
373
|
+
|
|
374
|
+
def drop_column_string(self):
|
|
375
|
+
return "DROP COLUMN {name}"
|
|
376
|
+
|
|
377
|
+
def change_column_string(self):
|
|
378
|
+
return "MODIFY {name}{data_type}{length}{column_constraint} {nullable}{default} {constraint}"
|
|
379
|
+
|
|
380
|
+
def rename_column_string(self):
|
|
381
|
+
return "CHANGE {old} {to}"
|
|
382
|
+
|
|
383
|
+
def columnize_string(self):
|
|
384
|
+
return "{name} {data_type}{length}{column_constraint}{signed} {nullable}{default} {constraint}{comment}"
|
|
385
|
+
|
|
386
|
+
def constraintize(self, constraints, table):
|
|
387
|
+
sql = []
|
|
388
|
+
for name, constraint in constraints.items():
|
|
389
|
+
sql.append(
|
|
390
|
+
getattr(
|
|
391
|
+
self, f"get_{constraint.constraint_type}_constraint_string"
|
|
392
|
+
)().format(
|
|
393
|
+
columns=", ".join(constraint.columns),
|
|
394
|
+
name_columns="_".join(constraint.columns),
|
|
395
|
+
table=table.name,
|
|
396
|
+
constraint_name=constraint.name,
|
|
397
|
+
)
|
|
398
|
+
)
|
|
399
|
+
|
|
400
|
+
return sql
|
|
401
|
+
|
|
402
|
+
def get_table_string(self):
|
|
403
|
+
return "`{table}`"
|
|
404
|
+
|
|
405
|
+
def get_column_string(self):
|
|
406
|
+
return "`{column}`"
|
|
407
|
+
|
|
408
|
+
def create_format(self):
|
|
409
|
+
return "CREATE TABLE {table} ({columns}{constraints}{foreign_keys}){comment}"
|
|
410
|
+
|
|
411
|
+
def create_if_not_exists_format(self):
|
|
412
|
+
return "CREATE TABLE IF NOT EXISTS {table} ({columns}{constraints}{foreign_keys}){comment}"
|
|
413
|
+
|
|
414
|
+
def alter_format(self):
|
|
415
|
+
return "ALTER TABLE {table} {columns}"
|
|
416
|
+
|
|
417
|
+
def get_foreign_key_constraint_string(self):
|
|
418
|
+
return "CONSTRAINT {constraint_name} FOREIGN KEY ({column}) REFERENCES {foreign_table}({foreign_column}){cascade}"
|
|
419
|
+
|
|
420
|
+
def get_primary_key_constraint_string(self):
|
|
421
|
+
return "CONSTRAINT {constraint_name} PRIMARY KEY ({columns})"
|
|
422
|
+
|
|
423
|
+
def get_unique_constraint_string(self):
|
|
424
|
+
return "CONSTRAINT {constraint_name} UNIQUE ({columns})"
|
|
425
|
+
|
|
426
|
+
def compile_table_exists(self, table, database=None, schema=None):
|
|
427
|
+
return f"SELECT * from information_schema.tables where table_name='{table}' AND table_schema = '{database}'"
|
|
428
|
+
|
|
429
|
+
def compile_truncate(self, table, foreign_keys=False):
|
|
430
|
+
if not foreign_keys:
|
|
431
|
+
return f"TRUNCATE {self.wrap_table(table)}"
|
|
432
|
+
|
|
433
|
+
return [
|
|
434
|
+
self.disable_foreign_key_constraints(),
|
|
435
|
+
f"TRUNCATE {self.wrap_table(table)}",
|
|
436
|
+
self.enable_foreign_key_constraints(),
|
|
437
|
+
]
|
|
438
|
+
|
|
439
|
+
def compile_rename_table(self, current_name, new_name):
|
|
440
|
+
return f"ALTER TABLE {self.wrap_table(current_name)} RENAME TO {self.wrap_table(new_name)}"
|
|
441
|
+
|
|
442
|
+
def compile_drop_table_if_exists(self, table):
|
|
443
|
+
return f"DROP TABLE IF EXISTS {self.wrap_table(table)}"
|
|
444
|
+
|
|
445
|
+
def compile_drop_table(self, table):
|
|
446
|
+
return f"DROP TABLE {self.wrap_table(table)}"
|
|
447
|
+
|
|
448
|
+
def compile_column_exists(self, table, column):
|
|
449
|
+
return f"SELECT column_name FROM information_schema.columns WHERE table_name='{table}' and column_name='{column}'"
|
|
450
|
+
|
|
451
|
+
def compile_get_all_tables(self, database, schema=None):
|
|
452
|
+
return f"SELECT table_name FROM information_schema.tables WHERE table_schema = '{database}'"
|
|
453
|
+
|
|
454
|
+
def get_current_schema(self, connection, table_name, schema=None):
|
|
455
|
+
table = Table(table_name)
|
|
456
|
+
sql = f"DESCRIBE {table_name}"
|
|
457
|
+
result = connection.query(sql, ())
|
|
458
|
+
reversed_type_map = {v: k for k, v in self.type_map.items()}
|
|
459
|
+
|
|
460
|
+
for column in result:
|
|
461
|
+
column_type = self.get_column_type(
|
|
462
|
+
reversed_type_map, column["Type"].upper()
|
|
463
|
+
)
|
|
464
|
+
length = self.get_column_length(column["Type"])
|
|
465
|
+
default = column.get("Default")
|
|
466
|
+
|
|
467
|
+
table.add_column(
|
|
468
|
+
column["Field"],
|
|
469
|
+
column_type,
|
|
470
|
+
column_python_type=Schema._type_hints_map.get(
|
|
471
|
+
column_type, str
|
|
472
|
+
),
|
|
473
|
+
default=default,
|
|
474
|
+
length=length,
|
|
475
|
+
)
|
|
476
|
+
return table
|
|
477
|
+
|
|
478
|
+
def get_column_type(self, reversed_type_map, column_type):
|
|
479
|
+
if "(" in column_type:
|
|
480
|
+
parenthesis_index = column_type.find("(")
|
|
481
|
+
column_type = column_type[:parenthesis_index]
|
|
482
|
+
length = self.get_column_length(column_type)
|
|
483
|
+
if column_type == "CHAR":
|
|
484
|
+
if length == "1":
|
|
485
|
+
return "char"
|
|
486
|
+
elif length == "36":
|
|
487
|
+
return "uuid"
|
|
488
|
+
else:
|
|
489
|
+
return "char"
|
|
490
|
+
elif column_type == "VARCHAR":
|
|
491
|
+
if length == "4":
|
|
492
|
+
return "year"
|
|
493
|
+
else:
|
|
494
|
+
return "string"
|
|
495
|
+
return reversed_type_map.get(column_type)
|
|
496
|
+
|
|
497
|
+
def get_column_length(self, raw_column_type):
|
|
498
|
+
regex = re.compile(r"^\w+\((\d+)\)")
|
|
499
|
+
match = regex.match(raw_column_type)
|
|
500
|
+
if match:
|
|
501
|
+
return match.groups()[0]
|
|
502
|
+
|
|
503
|
+
if "(" in raw_column_type:
|
|
504
|
+
parenthesis_index = raw_column_type.find("(")
|
|
505
|
+
return raw_column_type[parenthesis_index + 1 : -1]
|
|
506
|
+
else:
|
|
507
|
+
return None
|
|
508
|
+
|
|
509
|
+
def enable_foreign_key_constraints(self):
|
|
510
|
+
return "SET FOREIGN_KEY_CHECKS=1"
|
|
511
|
+
|
|
512
|
+
def disable_foreign_key_constraints(self):
|
|
513
|
+
return "SET FOREIGN_KEY_CHECKS=0"
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
class Platform:
|
|
2
|
+
foreign_key_actions = {
|
|
3
|
+
"cascade": "CASCADE",
|
|
4
|
+
"set null": "SET NULL",
|
|
5
|
+
"cascade": "CASCADE",
|
|
6
|
+
"restrict": "RESTRICT",
|
|
7
|
+
"no action": "NO ACTION",
|
|
8
|
+
"default": "SET DEFAULT",
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
signed = {"signed": "SIGNED", "unsigned": "UNSIGNED"}
|
|
12
|
+
|
|
13
|
+
def columnize(self, columns):
|
|
14
|
+
sql = []
|
|
15
|
+
for name, column in columns.items():
|
|
16
|
+
if column.length:
|
|
17
|
+
length = self.create_column_length(column.column_type).format(
|
|
18
|
+
length=column.length
|
|
19
|
+
)
|
|
20
|
+
else:
|
|
21
|
+
length = ""
|
|
22
|
+
|
|
23
|
+
if column.default in (0,):
|
|
24
|
+
default = f" DEFAULT {column.default}"
|
|
25
|
+
elif column.default in self.premapped_defaults.keys():
|
|
26
|
+
default = self.premapped_defaults.get(column.default)
|
|
27
|
+
elif column.default:
|
|
28
|
+
if (
|
|
29
|
+
isinstance(column.default, (str,))
|
|
30
|
+
and not column.default_is_raw
|
|
31
|
+
):
|
|
32
|
+
default = f" DEFAULT '{column.default}'"
|
|
33
|
+
else:
|
|
34
|
+
default = f" DEFAULT {column.default}"
|
|
35
|
+
else:
|
|
36
|
+
default = ""
|
|
37
|
+
|
|
38
|
+
sql.append(
|
|
39
|
+
self.columnize_string()
|
|
40
|
+
.format(
|
|
41
|
+
name=column.name,
|
|
42
|
+
data_type=self.type_map.get(column.column_type, ""),
|
|
43
|
+
length=length,
|
|
44
|
+
constraint="PRIMARY KEY" if column.primary else "",
|
|
45
|
+
nullable=self.premapped_nulls.get(column.is_null) or "",
|
|
46
|
+
default=default,
|
|
47
|
+
)
|
|
48
|
+
.strip()
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
return sql
|
|
52
|
+
|
|
53
|
+
def columnize_string(self):
|
|
54
|
+
raise NotImplementedError
|
|
55
|
+
|
|
56
|
+
def create_column_length(self, column_type):
|
|
57
|
+
if column_type in self.types_without_lengths:
|
|
58
|
+
return ""
|
|
59
|
+
return "({length})"
|
|
60
|
+
|
|
61
|
+
def foreign_key_constraintize(self, table, foreign_keys):
|
|
62
|
+
sql = []
|
|
63
|
+
for name, foreign_key in foreign_keys.items():
|
|
64
|
+
cascade = ""
|
|
65
|
+
if foreign_key.delete_action:
|
|
66
|
+
cascade += f" ON DELETE {self.foreign_key_actions.get(foreign_key.delete_action.lower())}"
|
|
67
|
+
if foreign_key.update_action:
|
|
68
|
+
cascade += f" ON UPDATE {self.foreign_key_actions.get(foreign_key.update_action.lower())}"
|
|
69
|
+
sql.append(
|
|
70
|
+
self.get_foreign_key_constraint_string().format(
|
|
71
|
+
column=self.wrap_column(foreign_key.column),
|
|
72
|
+
constraint_name=foreign_key.constraint_name,
|
|
73
|
+
table=self.wrap_table(table),
|
|
74
|
+
foreign_table=self.wrap_table(foreign_key.foreign_table),
|
|
75
|
+
foreign_column=self.wrap_column(
|
|
76
|
+
foreign_key.foreign_column
|
|
77
|
+
),
|
|
78
|
+
cascade=cascade,
|
|
79
|
+
)
|
|
80
|
+
)
|
|
81
|
+
return sql
|
|
82
|
+
|
|
83
|
+
def constraintize(self, constraints):
|
|
84
|
+
sql = []
|
|
85
|
+
for name, constraint in constraints.items():
|
|
86
|
+
sql.append(
|
|
87
|
+
getattr(
|
|
88
|
+
self, f"get_{constraint.constraint_type}_constraint_string"
|
|
89
|
+
)().format(columns=", ".join(constraint.columns))
|
|
90
|
+
)
|
|
91
|
+
return sql
|
|
92
|
+
|
|
93
|
+
def wrap_table(self, table_name):
|
|
94
|
+
return self.get_table_string().format(table=table_name)
|
|
95
|
+
|
|
96
|
+
def wrap_column(self, column_name):
|
|
97
|
+
return self.get_column_string().format(column=column_name)
|