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