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.
Files changed (116) hide show
  1. masonite_framework_orm-3.0.1.dist-info/METADATA +87 -0
  2. masonite_framework_orm-3.0.1.dist-info/RECORD +116 -0
  3. masonite_framework_orm-3.0.1.dist-info/WHEEL +5 -0
  4. masonite_framework_orm-3.0.1.dist-info/entry_points.txt +3 -0
  5. masonite_framework_orm-3.0.1.dist-info/licenses/LICENSE +21 -0
  6. masonite_framework_orm-3.0.1.dist-info/top_level.txt +1 -0
  7. masoniteorm/__init__.py +1 -0
  8. masoniteorm/collection/Collection.py +605 -0
  9. masoniteorm/collection/__init__.py +1 -0
  10. masoniteorm/commands/CanOverrideConfig.py +16 -0
  11. masoniteorm/commands/CanOverrideOptionsDefault.py +22 -0
  12. masoniteorm/commands/Command.py +6 -0
  13. masoniteorm/commands/Entry.py +43 -0
  14. masoniteorm/commands/MakeMigrationCommand.py +57 -0
  15. masoniteorm/commands/MakeModelCommand.py +78 -0
  16. masoniteorm/commands/MakeModelDocstringCommand.py +37 -0
  17. masoniteorm/commands/MakeObserverCommand.py +54 -0
  18. masoniteorm/commands/MakeSeedCommand.py +54 -0
  19. masoniteorm/commands/MigrateCommand.py +46 -0
  20. masoniteorm/commands/MigrateFreshCommand.py +41 -0
  21. masoniteorm/commands/MigrateRefreshCommand.py +41 -0
  22. masoniteorm/commands/MigrateResetCommand.py +25 -0
  23. masoniteorm/commands/MigrateRollbackCommand.py +26 -0
  24. masoniteorm/commands/MigrateStatusCommand.py +51 -0
  25. masoniteorm/commands/SeedRunCommand.py +35 -0
  26. masoniteorm/commands/ShellCommand.py +205 -0
  27. masoniteorm/commands/__init__.py +18 -0
  28. masoniteorm/commands/stubs/create_migration.stub +20 -0
  29. masoniteorm/commands/stubs/create_seed.stub +9 -0
  30. masoniteorm/commands/stubs/model.stub +9 -0
  31. masoniteorm/commands/stubs/observer.stub +101 -0
  32. masoniteorm/commands/stubs/table_migration.stub +19 -0
  33. masoniteorm/config.py +123 -0
  34. masoniteorm/connections/BaseConnection.py +101 -0
  35. masoniteorm/connections/ConnectionFactory.py +59 -0
  36. masoniteorm/connections/ConnectionResolver.py +132 -0
  37. masoniteorm/connections/MSSQLConnection.py +176 -0
  38. masoniteorm/connections/MySQLConnection.py +232 -0
  39. masoniteorm/connections/PostgresConnection.py +225 -0
  40. masoniteorm/connections/SQLiteConnection.py +179 -0
  41. masoniteorm/connections/__init__.py +6 -0
  42. masoniteorm/exceptions.py +38 -0
  43. masoniteorm/expressions/__init__.py +1 -0
  44. masoniteorm/expressions/expressions.py +288 -0
  45. masoniteorm/factories/Factory.py +112 -0
  46. masoniteorm/factories/__init__.py +1 -0
  47. masoniteorm/helpers/__init__.py +0 -0
  48. masoniteorm/helpers/misc.py +22 -0
  49. masoniteorm/migrations/Migration.py +330 -0
  50. masoniteorm/migrations/__init__.py +1 -0
  51. masoniteorm/models/MigrationModel.py +9 -0
  52. masoniteorm/models/Model.py +1209 -0
  53. masoniteorm/models/Model.pyi +1366 -0
  54. masoniteorm/models/Pivot.py +5 -0
  55. masoniteorm/models/__init__.py +1 -0
  56. masoniteorm/observers/ObservesEvents.py +27 -0
  57. masoniteorm/observers/__init__.py +1 -0
  58. masoniteorm/pagination/BasePaginator.py +10 -0
  59. masoniteorm/pagination/LengthAwarePaginator.py +34 -0
  60. masoniteorm/pagination/SimplePaginator.py +28 -0
  61. masoniteorm/pagination/__init__.py +2 -0
  62. masoniteorm/providers/ORMProvider.py +39 -0
  63. masoniteorm/providers/__init__.py +1 -0
  64. masoniteorm/query/EagerRelation.py +42 -0
  65. masoniteorm/query/QueryBuilder.py +2486 -0
  66. masoniteorm/query/__init__.py +1 -0
  67. masoniteorm/query/grammars/BaseGrammar.py +1027 -0
  68. masoniteorm/query/grammars/MSSQLGrammar.py +194 -0
  69. masoniteorm/query/grammars/MySQLGrammar.py +238 -0
  70. masoniteorm/query/grammars/PostgresGrammar.py +213 -0
  71. masoniteorm/query/grammars/SQLiteGrammar.py +228 -0
  72. masoniteorm/query/grammars/__init__.py +4 -0
  73. masoniteorm/query/processors/MSSQLPostProcessor.py +58 -0
  74. masoniteorm/query/processors/MySQLPostProcessor.py +48 -0
  75. masoniteorm/query/processors/PostgresPostProcessor.py +49 -0
  76. masoniteorm/query/processors/SQLitePostProcessor.py +49 -0
  77. masoniteorm/query/processors/__init__.py +4 -0
  78. masoniteorm/relationships/BaseRelationship.py +161 -0
  79. masoniteorm/relationships/BelongsTo.py +124 -0
  80. masoniteorm/relationships/BelongsToMany.py +604 -0
  81. masoniteorm/relationships/HasMany.py +66 -0
  82. masoniteorm/relationships/HasManyThrough.py +269 -0
  83. masoniteorm/relationships/HasOne.py +111 -0
  84. masoniteorm/relationships/HasOneThrough.py +275 -0
  85. masoniteorm/relationships/MorphMany.py +152 -0
  86. masoniteorm/relationships/MorphOne.py +156 -0
  87. masoniteorm/relationships/MorphTo.py +111 -0
  88. masoniteorm/relationships/MorphToMany.py +108 -0
  89. masoniteorm/relationships/__init__.py +10 -0
  90. masoniteorm/schema/Blueprint.py +1161 -0
  91. masoniteorm/schema/Column.py +144 -0
  92. masoniteorm/schema/ColumnDiff.py +0 -0
  93. masoniteorm/schema/Constraint.py +5 -0
  94. masoniteorm/schema/ForeignKeyConstraint.py +28 -0
  95. masoniteorm/schema/Index.py +5 -0
  96. masoniteorm/schema/Schema.py +359 -0
  97. masoniteorm/schema/Table.py +94 -0
  98. masoniteorm/schema/TableDiff.py +86 -0
  99. masoniteorm/schema/__init__.py +3 -0
  100. masoniteorm/schema/platforms/MSSQLPlatform.py +367 -0
  101. masoniteorm/schema/platforms/MySQLPlatform.py +513 -0
  102. masoniteorm/schema/platforms/Platform.py +97 -0
  103. masoniteorm/schema/platforms/PostgresPlatform.py +551 -0
  104. masoniteorm/schema/platforms/SQLitePlatform.py +481 -0
  105. masoniteorm/schema/platforms/__init__.py +4 -0
  106. masoniteorm/scopes/BaseScope.py +6 -0
  107. masoniteorm/scopes/SoftDeleteScope.py +56 -0
  108. masoniteorm/scopes/SoftDeletesMixin.py +13 -0
  109. masoniteorm/scopes/TimeStampsMixin.py +12 -0
  110. masoniteorm/scopes/TimeStampsScope.py +47 -0
  111. masoniteorm/scopes/UUIDPrimaryKeyMixin.py +8 -0
  112. masoniteorm/scopes/UUIDPrimaryKeyScope.py +51 -0
  113. masoniteorm/scopes/__init__.py +8 -0
  114. masoniteorm/scopes/scope.py +15 -0
  115. masoniteorm/seeds/Seeder.py +42 -0
  116. 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)