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,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 ""
|