sqlspec 0.17.0__py3-none-any.whl → 0.18.0__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.
Potentially problematic release.
This version of sqlspec might be problematic. Click here for more details.
- sqlspec/__init__.py +1 -1
- sqlspec/_sql.py +188 -234
- sqlspec/adapters/adbc/config.py +24 -30
- sqlspec/adapters/adbc/driver.py +42 -61
- sqlspec/adapters/aiosqlite/config.py +5 -10
- sqlspec/adapters/aiosqlite/driver.py +9 -25
- sqlspec/adapters/aiosqlite/pool.py +43 -35
- sqlspec/adapters/asyncmy/config.py +10 -7
- sqlspec/adapters/asyncmy/driver.py +18 -39
- sqlspec/adapters/asyncpg/config.py +4 -0
- sqlspec/adapters/asyncpg/driver.py +32 -79
- sqlspec/adapters/bigquery/config.py +12 -65
- sqlspec/adapters/bigquery/driver.py +39 -133
- sqlspec/adapters/duckdb/config.py +11 -15
- sqlspec/adapters/duckdb/driver.py +61 -85
- sqlspec/adapters/duckdb/pool.py +2 -5
- sqlspec/adapters/oracledb/_types.py +8 -1
- sqlspec/adapters/oracledb/config.py +55 -38
- sqlspec/adapters/oracledb/driver.py +35 -92
- sqlspec/adapters/oracledb/migrations.py +257 -0
- sqlspec/adapters/psqlpy/config.py +13 -9
- sqlspec/adapters/psqlpy/driver.py +28 -103
- sqlspec/adapters/psycopg/config.py +9 -5
- sqlspec/adapters/psycopg/driver.py +107 -175
- sqlspec/adapters/sqlite/config.py +7 -5
- sqlspec/adapters/sqlite/driver.py +37 -73
- sqlspec/adapters/sqlite/pool.py +3 -12
- sqlspec/base.py +1 -8
- sqlspec/builder/__init__.py +1 -1
- sqlspec/builder/_base.py +34 -20
- sqlspec/builder/_column.py +5 -1
- sqlspec/builder/_ddl.py +407 -183
- sqlspec/builder/_expression_wrappers.py +46 -0
- sqlspec/builder/_insert.py +2 -4
- sqlspec/builder/_update.py +5 -5
- sqlspec/builder/mixins/_insert_operations.py +26 -6
- sqlspec/builder/mixins/_merge_operations.py +1 -1
- sqlspec/builder/mixins/_order_limit_operations.py +16 -4
- sqlspec/builder/mixins/_select_operations.py +3 -7
- sqlspec/builder/mixins/_update_operations.py +4 -4
- sqlspec/config.py +32 -13
- sqlspec/core/__init__.py +89 -14
- sqlspec/core/cache.py +57 -104
- sqlspec/core/compiler.py +57 -112
- sqlspec/core/filters.py +1 -21
- sqlspec/core/hashing.py +13 -47
- sqlspec/core/parameters.py +272 -261
- sqlspec/core/result.py +12 -27
- sqlspec/core/splitter.py +17 -21
- sqlspec/core/statement.py +150 -159
- sqlspec/driver/_async.py +2 -15
- sqlspec/driver/_common.py +16 -95
- sqlspec/driver/_sync.py +2 -15
- sqlspec/driver/mixins/_result_tools.py +8 -29
- sqlspec/driver/mixins/_sql_translator.py +6 -8
- sqlspec/exceptions.py +1 -2
- sqlspec/loader.py +43 -115
- sqlspec/migrations/__init__.py +1 -1
- sqlspec/migrations/base.py +34 -45
- sqlspec/migrations/commands.py +34 -15
- sqlspec/migrations/loaders.py +1 -1
- sqlspec/migrations/runner.py +104 -19
- sqlspec/migrations/tracker.py +49 -2
- sqlspec/protocols.py +13 -6
- sqlspec/storage/__init__.py +4 -4
- sqlspec/storage/backends/fsspec.py +5 -6
- sqlspec/storage/backends/obstore.py +7 -8
- sqlspec/storage/registry.py +3 -3
- sqlspec/utils/__init__.py +2 -2
- sqlspec/utils/logging.py +6 -10
- sqlspec/utils/sync_tools.py +27 -4
- sqlspec/utils/text.py +6 -1
- {sqlspec-0.17.0.dist-info → sqlspec-0.18.0.dist-info}/METADATA +1 -1
- sqlspec-0.18.0.dist-info/RECORD +138 -0
- sqlspec/builder/_ddl_utils.py +0 -103
- sqlspec-0.17.0.dist-info/RECORD +0 -137
- {sqlspec-0.17.0.dist-info → sqlspec-0.18.0.dist-info}/WHEEL +0 -0
- {sqlspec-0.17.0.dist-info → sqlspec-0.18.0.dist-info}/entry_points.txt +0 -0
- {sqlspec-0.17.0.dist-info → sqlspec-0.18.0.dist-info}/licenses/LICENSE +0 -0
- {sqlspec-0.17.0.dist-info → sqlspec-0.18.0.dist-info}/licenses/NOTICE +0 -0
sqlspec/builder/_ddl.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"""DDL builders for SQLSpec: DROP, CREATE INDEX, TRUNCATE, etc."""
|
|
2
2
|
|
|
3
|
-
from dataclasses import dataclass, field
|
|
4
3
|
from typing import TYPE_CHECKING, Any, Optional, Union
|
|
5
4
|
|
|
6
5
|
from sqlglot import exp
|
|
@@ -8,7 +7,6 @@ from sqlglot.dialects.dialect import DialectType
|
|
|
8
7
|
from typing_extensions import Self
|
|
9
8
|
|
|
10
9
|
from sqlspec.builder._base import QueryBuilder, SafeQuery
|
|
11
|
-
from sqlspec.builder._ddl_utils import build_column_expression, build_constraint_expression
|
|
12
10
|
from sqlspec.core.result import SQLResult
|
|
13
11
|
|
|
14
12
|
if TYPE_CHECKING:
|
|
@@ -37,16 +35,109 @@ __all__ = (
|
|
|
37
35
|
)
|
|
38
36
|
|
|
39
37
|
|
|
40
|
-
|
|
38
|
+
def build_column_expression(col: "ColumnDefinition") -> "exp.Expression":
|
|
39
|
+
"""Build SQLGlot expression for a column definition."""
|
|
40
|
+
col_def = exp.ColumnDef(this=exp.to_identifier(col.name), kind=exp.DataType.build(col.dtype))
|
|
41
|
+
|
|
42
|
+
constraints: list[exp.ColumnConstraint] = []
|
|
43
|
+
|
|
44
|
+
if col.not_null:
|
|
45
|
+
constraints.append(exp.ColumnConstraint(kind=exp.NotNullColumnConstraint()))
|
|
46
|
+
|
|
47
|
+
if col.primary_key:
|
|
48
|
+
constraints.append(exp.ColumnConstraint(kind=exp.PrimaryKeyColumnConstraint()))
|
|
49
|
+
|
|
50
|
+
if col.unique:
|
|
51
|
+
constraints.append(exp.ColumnConstraint(kind=exp.UniqueColumnConstraint()))
|
|
52
|
+
|
|
53
|
+
if col.default is not None:
|
|
54
|
+
default_expr: Optional[exp.Expression] = None
|
|
55
|
+
if isinstance(col.default, str):
|
|
56
|
+
default_upper = col.default.upper()
|
|
57
|
+
if default_upper == "CURRENT_TIMESTAMP":
|
|
58
|
+
default_expr = exp.CurrentTimestamp()
|
|
59
|
+
elif default_upper == "CURRENT_DATE":
|
|
60
|
+
default_expr = exp.CurrentDate()
|
|
61
|
+
elif default_upper == "CURRENT_TIME":
|
|
62
|
+
default_expr = exp.CurrentTime()
|
|
63
|
+
elif "(" in col.default:
|
|
64
|
+
default_expr = exp.maybe_parse(col.default)
|
|
65
|
+
else:
|
|
66
|
+
default_expr = exp.convert(col.default)
|
|
67
|
+
else:
|
|
68
|
+
default_expr = exp.convert(col.default)
|
|
69
|
+
|
|
70
|
+
constraints.append(exp.ColumnConstraint(kind=exp.DefaultColumnConstraint(this=default_expr)))
|
|
71
|
+
|
|
72
|
+
if col.check:
|
|
73
|
+
constraints.append(exp.ColumnConstraint(kind=exp.Check(this=exp.maybe_parse(col.check))))
|
|
74
|
+
|
|
75
|
+
if col.comment:
|
|
76
|
+
constraints.append(exp.ColumnConstraint(kind=exp.CommentColumnConstraint(this=exp.convert(col.comment))))
|
|
77
|
+
|
|
78
|
+
if col.generated:
|
|
79
|
+
constraints.append(
|
|
80
|
+
exp.ColumnConstraint(kind=exp.GeneratedAsIdentityColumnConstraint(this=exp.maybe_parse(col.generated)))
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
if col.collate:
|
|
84
|
+
constraints.append(exp.ColumnConstraint(kind=exp.CollateColumnConstraint(this=exp.to_identifier(col.collate))))
|
|
85
|
+
|
|
86
|
+
if constraints:
|
|
87
|
+
col_def.set("constraints", constraints)
|
|
88
|
+
|
|
89
|
+
return col_def
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def build_constraint_expression(constraint: "ConstraintDefinition") -> "Optional[exp.Expression]":
|
|
93
|
+
"""Build SQLGlot expression for a table constraint."""
|
|
94
|
+
if constraint.constraint_type == "PRIMARY KEY":
|
|
95
|
+
pk_constraint = exp.PrimaryKey(expressions=[exp.to_identifier(col) for col in constraint.columns])
|
|
96
|
+
|
|
97
|
+
if constraint.name:
|
|
98
|
+
return exp.Constraint(this=exp.to_identifier(constraint.name), expression=pk_constraint)
|
|
99
|
+
return pk_constraint
|
|
100
|
+
|
|
101
|
+
if constraint.constraint_type == "FOREIGN KEY":
|
|
102
|
+
fk_constraint = exp.ForeignKey(
|
|
103
|
+
expressions=[exp.to_identifier(col) for col in constraint.columns],
|
|
104
|
+
reference=exp.Reference(
|
|
105
|
+
this=exp.to_table(constraint.references_table) if constraint.references_table else None,
|
|
106
|
+
expressions=[exp.to_identifier(col) for col in constraint.references_columns],
|
|
107
|
+
on_delete=constraint.on_delete,
|
|
108
|
+
on_update=constraint.on_update,
|
|
109
|
+
),
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
if constraint.name:
|
|
113
|
+
return exp.Constraint(this=exp.to_identifier(constraint.name), expression=fk_constraint)
|
|
114
|
+
return fk_constraint
|
|
115
|
+
|
|
116
|
+
if constraint.constraint_type == "UNIQUE":
|
|
117
|
+
unique_constraint = exp.UniqueKeyProperty(expressions=[exp.to_identifier(col) for col in constraint.columns])
|
|
118
|
+
|
|
119
|
+
if constraint.name:
|
|
120
|
+
return exp.Constraint(this=exp.to_identifier(constraint.name), expression=unique_constraint)
|
|
121
|
+
return unique_constraint
|
|
122
|
+
|
|
123
|
+
if constraint.constraint_type == "CHECK":
|
|
124
|
+
check_expr = exp.Check(this=exp.maybe_parse(constraint.condition) if constraint.condition else None)
|
|
125
|
+
|
|
126
|
+
if constraint.name:
|
|
127
|
+
return exp.Constraint(this=exp.to_identifier(constraint.name), expression=check_expr)
|
|
128
|
+
return check_expr
|
|
129
|
+
|
|
130
|
+
return None
|
|
131
|
+
|
|
132
|
+
|
|
41
133
|
class DDLBuilder(QueryBuilder):
|
|
42
134
|
"""Base class for DDL builders (CREATE, DROP, ALTER, etc)."""
|
|
43
135
|
|
|
44
|
-
|
|
45
|
-
_expression: Optional[exp.Expression] = field(default=None, init=False, repr=False, compare=False, hash=False)
|
|
136
|
+
__slots__ = ()
|
|
46
137
|
|
|
47
|
-
def
|
|
48
|
-
|
|
49
|
-
|
|
138
|
+
def __init__(self, dialect: DialectType = None) -> None:
|
|
139
|
+
super().__init__(dialect=dialect)
|
|
140
|
+
self._expression: Optional[exp.Expression] = None
|
|
50
141
|
|
|
51
142
|
def _create_base_expression(self) -> exp.Expression:
|
|
52
143
|
msg = "Subclasses must implement _create_base_expression."
|
|
@@ -65,40 +156,91 @@ class DDLBuilder(QueryBuilder):
|
|
|
65
156
|
return super().to_statement(config=config)
|
|
66
157
|
|
|
67
158
|
|
|
68
|
-
@dataclass
|
|
69
159
|
class ColumnDefinition:
|
|
70
160
|
"""Column definition for CREATE TABLE."""
|
|
71
161
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
162
|
+
__slots__ = (
|
|
163
|
+
"auto_increment",
|
|
164
|
+
"check",
|
|
165
|
+
"collate",
|
|
166
|
+
"comment",
|
|
167
|
+
"default",
|
|
168
|
+
"dtype",
|
|
169
|
+
"generated",
|
|
170
|
+
"name",
|
|
171
|
+
"not_null",
|
|
172
|
+
"primary_key",
|
|
173
|
+
"unique",
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
def __init__(
|
|
177
|
+
self,
|
|
178
|
+
name: str,
|
|
179
|
+
dtype: str,
|
|
180
|
+
default: "Optional[Any]" = None,
|
|
181
|
+
not_null: bool = False,
|
|
182
|
+
primary_key: bool = False,
|
|
183
|
+
unique: bool = False,
|
|
184
|
+
auto_increment: bool = False,
|
|
185
|
+
comment: "Optional[str]" = None,
|
|
186
|
+
check: "Optional[str]" = None,
|
|
187
|
+
generated: "Optional[str]" = None,
|
|
188
|
+
collate: "Optional[str]" = None,
|
|
189
|
+
) -> None:
|
|
190
|
+
self.name = name
|
|
191
|
+
self.dtype = dtype
|
|
192
|
+
self.default = default
|
|
193
|
+
self.not_null = not_null
|
|
194
|
+
self.primary_key = primary_key
|
|
195
|
+
self.unique = unique
|
|
196
|
+
self.auto_increment = auto_increment
|
|
197
|
+
self.comment = comment
|
|
198
|
+
self.check = check
|
|
199
|
+
self.generated = generated
|
|
200
|
+
self.collate = collate
|
|
83
201
|
|
|
84
202
|
|
|
85
|
-
@dataclass
|
|
86
203
|
class ConstraintDefinition:
|
|
87
204
|
"""Constraint definition for CREATE TABLE."""
|
|
88
205
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
206
|
+
__slots__ = (
|
|
207
|
+
"columns",
|
|
208
|
+
"condition",
|
|
209
|
+
"constraint_type",
|
|
210
|
+
"deferrable",
|
|
211
|
+
"initially_deferred",
|
|
212
|
+
"name",
|
|
213
|
+
"on_delete",
|
|
214
|
+
"on_update",
|
|
215
|
+
"references_columns",
|
|
216
|
+
"references_table",
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
def __init__(
|
|
220
|
+
self,
|
|
221
|
+
constraint_type: str,
|
|
222
|
+
name: "Optional[str]" = None,
|
|
223
|
+
columns: "Optional[list[str]]" = None,
|
|
224
|
+
references_table: "Optional[str]" = None,
|
|
225
|
+
references_columns: "Optional[list[str]]" = None,
|
|
226
|
+
condition: "Optional[str]" = None,
|
|
227
|
+
on_delete: "Optional[str]" = None,
|
|
228
|
+
on_update: "Optional[str]" = None,
|
|
229
|
+
deferrable: bool = False,
|
|
230
|
+
initially_deferred: bool = False,
|
|
231
|
+
) -> None:
|
|
232
|
+
self.constraint_type = constraint_type
|
|
233
|
+
self.name = name
|
|
234
|
+
self.columns = columns or []
|
|
235
|
+
self.references_table = references_table
|
|
236
|
+
self.references_columns = references_columns or []
|
|
237
|
+
self.condition = condition
|
|
238
|
+
self.on_delete = on_delete
|
|
239
|
+
self.on_update = on_update
|
|
240
|
+
self.deferrable = deferrable
|
|
241
|
+
self.initially_deferred = initially_deferred
|
|
99
242
|
|
|
100
243
|
|
|
101
|
-
@dataclass
|
|
102
244
|
class CreateTable(DDLBuilder):
|
|
103
245
|
"""Builder for CREATE TABLE statements with columns and constraints.
|
|
104
246
|
|
|
@@ -113,20 +255,31 @@ class CreateTable(DDLBuilder):
|
|
|
113
255
|
sql = builder.build().sql
|
|
114
256
|
"""
|
|
115
257
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
258
|
+
__slots__ = (
|
|
259
|
+
"_columns",
|
|
260
|
+
"_constraints",
|
|
261
|
+
"_if_not_exists",
|
|
262
|
+
"_like_table",
|
|
263
|
+
"_partition_by",
|
|
264
|
+
"_schema",
|
|
265
|
+
"_table_name",
|
|
266
|
+
"_table_options",
|
|
267
|
+
"_tablespace",
|
|
268
|
+
"_temporary",
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
def __init__(self, table_name: str, dialect: DialectType = None) -> None:
|
|
272
|
+
super().__init__(dialect=dialect)
|
|
129
273
|
self._table_name = table_name
|
|
274
|
+
self._if_not_exists = False
|
|
275
|
+
self._temporary = False
|
|
276
|
+
self._columns: list[ColumnDefinition] = []
|
|
277
|
+
self._constraints: list[ConstraintDefinition] = []
|
|
278
|
+
self._table_options: dict[str, Any] = {}
|
|
279
|
+
self._schema: Optional[str] = None
|
|
280
|
+
self._tablespace: Optional[str] = None
|
|
281
|
+
self._like_table: Optional[str] = None
|
|
282
|
+
self._partition_by: Optional[str] = None
|
|
130
283
|
|
|
131
284
|
def in_schema(self, schema_name: str) -> "Self":
|
|
132
285
|
"""Set the schema for the table."""
|
|
@@ -320,11 +473,6 @@ class CreateTable(DDLBuilder):
|
|
|
320
473
|
if not self._columns and not self._like_table:
|
|
321
474
|
self._raise_sql_builder_error("Table must have at least one column or use LIKE clause")
|
|
322
475
|
|
|
323
|
-
if self._schema:
|
|
324
|
-
table = exp.Table(this=exp.to_identifier(self._table_name), db=exp.to_identifier(self._schema))
|
|
325
|
-
else:
|
|
326
|
-
table = exp.to_table(self._table_name)
|
|
327
|
-
|
|
328
476
|
column_defs: list[exp.Expression] = []
|
|
329
477
|
for col in self._columns:
|
|
330
478
|
col_expr = build_column_expression(col)
|
|
@@ -358,7 +506,12 @@ class CreateTable(DDLBuilder):
|
|
|
358
506
|
|
|
359
507
|
properties_node = exp.Properties(expressions=props) if props else None
|
|
360
508
|
|
|
361
|
-
|
|
509
|
+
if self._schema:
|
|
510
|
+
table_identifier = exp.Table(this=exp.to_identifier(self._table_name), db=exp.to_identifier(self._schema))
|
|
511
|
+
else:
|
|
512
|
+
table_identifier = exp.Table(this=exp.to_identifier(self._table_name))
|
|
513
|
+
|
|
514
|
+
schema_expr = exp.Schema(this=table_identifier, expressions=column_defs)
|
|
362
515
|
|
|
363
516
|
like_expr = None
|
|
364
517
|
if self._like_table:
|
|
@@ -366,42 +519,30 @@ class CreateTable(DDLBuilder):
|
|
|
366
519
|
|
|
367
520
|
return exp.Create(
|
|
368
521
|
kind="TABLE",
|
|
369
|
-
this=
|
|
522
|
+
this=schema_expr,
|
|
370
523
|
exists=self._if_not_exists,
|
|
371
524
|
temporary=self._temporary,
|
|
372
|
-
expression=schema_expr,
|
|
373
525
|
properties=properties_node,
|
|
374
526
|
like=like_expr,
|
|
375
527
|
)
|
|
376
528
|
|
|
377
|
-
@staticmethod
|
|
378
|
-
def _build_column_expression(col: "ColumnDefinition") -> "exp.Expression":
|
|
379
|
-
"""Build SQLGlot expression for a column definition."""
|
|
380
|
-
return build_column_expression(col)
|
|
381
|
-
|
|
382
|
-
@staticmethod
|
|
383
|
-
def _build_constraint_expression(constraint: "ConstraintDefinition") -> "Optional[exp.Expression]":
|
|
384
|
-
"""Build SQLGlot expression for a table constraint."""
|
|
385
|
-
return build_constraint_expression(constraint)
|
|
386
|
-
|
|
387
529
|
|
|
388
|
-
@dataclass
|
|
389
530
|
class DropTable(DDLBuilder):
|
|
390
531
|
"""Builder for DROP TABLE [IF EXISTS] ... [CASCADE|RESTRICT]."""
|
|
391
532
|
|
|
392
|
-
|
|
393
|
-
_if_exists: bool = False
|
|
394
|
-
_cascade: Optional[bool] = None
|
|
533
|
+
__slots__ = ("_cascade", "_if_exists", "_table_name")
|
|
395
534
|
|
|
396
|
-
def __init__(self, table_name: str,
|
|
535
|
+
def __init__(self, table_name: str, dialect: DialectType = None) -> None:
|
|
397
536
|
"""Initialize DROP TABLE with table name.
|
|
398
537
|
|
|
399
538
|
Args:
|
|
400
539
|
table_name: Name of the table to drop
|
|
401
|
-
|
|
540
|
+
dialect: SQL dialect to use
|
|
402
541
|
"""
|
|
403
|
-
super().__init__(
|
|
542
|
+
super().__init__(dialect=dialect)
|
|
404
543
|
self._table_name = table_name
|
|
544
|
+
self._if_exists = False
|
|
545
|
+
self._cascade: Optional[bool] = None
|
|
405
546
|
|
|
406
547
|
def table(self, name: str) -> Self:
|
|
407
548
|
self._table_name = name
|
|
@@ -427,24 +568,23 @@ class DropTable(DDLBuilder):
|
|
|
427
568
|
)
|
|
428
569
|
|
|
429
570
|
|
|
430
|
-
@dataclass
|
|
431
571
|
class DropIndex(DDLBuilder):
|
|
432
572
|
"""Builder for DROP INDEX [IF EXISTS] ... [ON table] [CASCADE|RESTRICT]."""
|
|
433
573
|
|
|
434
|
-
|
|
435
|
-
_table_name: Optional[str] = None
|
|
436
|
-
_if_exists: bool = False
|
|
437
|
-
_cascade: Optional[bool] = None
|
|
574
|
+
__slots__ = ("_cascade", "_if_exists", "_index_name", "_table_name")
|
|
438
575
|
|
|
439
|
-
def __init__(self, index_name: str,
|
|
576
|
+
def __init__(self, index_name: str, dialect: DialectType = None) -> None:
|
|
440
577
|
"""Initialize DROP INDEX with index name.
|
|
441
578
|
|
|
442
579
|
Args:
|
|
443
580
|
index_name: Name of the index to drop
|
|
444
|
-
|
|
581
|
+
dialect: SQL dialect to use
|
|
445
582
|
"""
|
|
446
|
-
super().__init__(
|
|
583
|
+
super().__init__(dialect=dialect)
|
|
447
584
|
self._index_name = index_name
|
|
585
|
+
self._table_name: Optional[str] = None
|
|
586
|
+
self._if_exists = False
|
|
587
|
+
self._cascade: Optional[bool] = None
|
|
448
588
|
|
|
449
589
|
def name(self, index_name: str) -> Self:
|
|
450
590
|
self._index_name = index_name
|
|
@@ -478,13 +618,22 @@ class DropIndex(DDLBuilder):
|
|
|
478
618
|
)
|
|
479
619
|
|
|
480
620
|
|
|
481
|
-
@dataclass
|
|
482
621
|
class DropView(DDLBuilder):
|
|
483
622
|
"""Builder for DROP VIEW [IF EXISTS] ... [CASCADE|RESTRICT]."""
|
|
484
623
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
624
|
+
__slots__ = ("_cascade", "_if_exists", "_view_name")
|
|
625
|
+
|
|
626
|
+
def __init__(self, view_name: str, dialect: DialectType = None) -> None:
|
|
627
|
+
"""Initialize DROP VIEW with view name.
|
|
628
|
+
|
|
629
|
+
Args:
|
|
630
|
+
view_name: Name of the view to drop
|
|
631
|
+
dialect: SQL dialect to use
|
|
632
|
+
"""
|
|
633
|
+
super().__init__(dialect=dialect)
|
|
634
|
+
self._view_name = view_name
|
|
635
|
+
self._if_exists = False
|
|
636
|
+
self._cascade: Optional[bool] = None
|
|
488
637
|
|
|
489
638
|
def name(self, view_name: str) -> Self:
|
|
490
639
|
self._view_name = view_name
|
|
@@ -510,13 +659,22 @@ class DropView(DDLBuilder):
|
|
|
510
659
|
)
|
|
511
660
|
|
|
512
661
|
|
|
513
|
-
@dataclass
|
|
514
662
|
class DropSchema(DDLBuilder):
|
|
515
663
|
"""Builder for DROP SCHEMA [IF EXISTS] ... [CASCADE|RESTRICT]."""
|
|
516
664
|
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
665
|
+
__slots__ = ("_cascade", "_if_exists", "_schema_name")
|
|
666
|
+
|
|
667
|
+
def __init__(self, schema_name: str, dialect: DialectType = None) -> None:
|
|
668
|
+
"""Initialize DROP SCHEMA with schema name.
|
|
669
|
+
|
|
670
|
+
Args:
|
|
671
|
+
schema_name: Name of the schema to drop
|
|
672
|
+
dialect: SQL dialect to use
|
|
673
|
+
"""
|
|
674
|
+
super().__init__(dialect=dialect)
|
|
675
|
+
self._schema_name = schema_name
|
|
676
|
+
self._if_exists = False
|
|
677
|
+
self._cascade: Optional[bool] = None
|
|
520
678
|
|
|
521
679
|
def name(self, schema_name: str) -> Self:
|
|
522
680
|
self._schema_name = schema_name
|
|
@@ -542,32 +700,26 @@ class DropSchema(DDLBuilder):
|
|
|
542
700
|
)
|
|
543
701
|
|
|
544
702
|
|
|
545
|
-
@dataclass
|
|
546
703
|
class CreateIndex(DDLBuilder):
|
|
547
|
-
"""Builder for CREATE [UNIQUE] INDEX [IF NOT EXISTS] ... ON ... (...).
|
|
704
|
+
"""Builder for CREATE [UNIQUE] INDEX [IF NOT EXISTS] ... ON ... (...)."""
|
|
548
705
|
|
|
549
|
-
|
|
550
|
-
"""
|
|
551
|
-
|
|
552
|
-
_index_name: Optional[str] = None
|
|
553
|
-
_table_name: Optional[str] = None
|
|
554
|
-
_columns: list[Union[str, exp.Ordered, exp.Expression]] = field(default_factory=list)
|
|
555
|
-
_unique: bool = False
|
|
556
|
-
_if_not_exists: bool = False
|
|
557
|
-
_using: Optional[str] = None
|
|
558
|
-
_where: Optional[Union[str, exp.Expression]] = None
|
|
706
|
+
__slots__ = ("_columns", "_if_not_exists", "_index_name", "_table_name", "_unique", "_using", "_where")
|
|
559
707
|
|
|
560
|
-
def __init__(self, index_name: str,
|
|
708
|
+
def __init__(self, index_name: str, dialect: DialectType = None) -> None:
|
|
561
709
|
"""Initialize CREATE INDEX with index name.
|
|
562
710
|
|
|
563
711
|
Args:
|
|
564
712
|
index_name: Name of the index to create
|
|
565
|
-
|
|
713
|
+
dialect: SQL dialect to use
|
|
566
714
|
"""
|
|
567
|
-
super().__init__(
|
|
715
|
+
super().__init__(dialect=dialect)
|
|
568
716
|
self._index_name = index_name
|
|
569
|
-
|
|
570
|
-
|
|
717
|
+
self._table_name: Optional[str] = None
|
|
718
|
+
self._columns: list[Union[str, exp.Ordered, exp.Expression]] = []
|
|
719
|
+
self._unique = False
|
|
720
|
+
self._if_not_exists = False
|
|
721
|
+
self._using: Optional[str] = None
|
|
722
|
+
self._where: Optional[Union[str, exp.Expression]] = None
|
|
571
723
|
|
|
572
724
|
def name(self, index_name: str) -> Self:
|
|
573
725
|
self._index_name = index_name
|
|
@@ -625,13 +777,22 @@ class CreateIndex(DDLBuilder):
|
|
|
625
777
|
)
|
|
626
778
|
|
|
627
779
|
|
|
628
|
-
@dataclass
|
|
629
780
|
class Truncate(DDLBuilder):
|
|
630
781
|
"""Builder for TRUNCATE TABLE ... [CASCADE|RESTRICT] [RESTART IDENTITY|CONTINUE IDENTITY]."""
|
|
631
782
|
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
783
|
+
__slots__ = ("_cascade", "_identity", "_table_name")
|
|
784
|
+
|
|
785
|
+
def __init__(self, table_name: str, dialect: DialectType = None) -> None:
|
|
786
|
+
"""Initialize TRUNCATE with table name.
|
|
787
|
+
|
|
788
|
+
Args:
|
|
789
|
+
table_name: Name of the table to truncate
|
|
790
|
+
dialect: SQL dialect to use
|
|
791
|
+
"""
|
|
792
|
+
super().__init__(dialect=dialect)
|
|
793
|
+
self._table_name = table_name
|
|
794
|
+
self._cascade: Optional[bool] = None
|
|
795
|
+
self._identity: Optional[str] = None
|
|
635
796
|
|
|
636
797
|
def table(self, name: str) -> Self:
|
|
637
798
|
self._table_name = name
|
|
@@ -660,29 +821,63 @@ class Truncate(DDLBuilder):
|
|
|
660
821
|
return exp.TruncateTable(this=exp.to_table(self._table_name), cascade=self._cascade, identity=identity_expr)
|
|
661
822
|
|
|
662
823
|
|
|
663
|
-
@dataclass
|
|
664
824
|
class AlterOperation:
|
|
665
825
|
"""Represents a single ALTER TABLE operation."""
|
|
666
826
|
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
827
|
+
__slots__ = (
|
|
828
|
+
"after_column",
|
|
829
|
+
"column_definition",
|
|
830
|
+
"column_name",
|
|
831
|
+
"constraint_definition",
|
|
832
|
+
"constraint_name",
|
|
833
|
+
"first",
|
|
834
|
+
"new_name",
|
|
835
|
+
"new_type",
|
|
836
|
+
"operation_type",
|
|
837
|
+
"using_expression",
|
|
838
|
+
)
|
|
839
|
+
|
|
840
|
+
def __init__(
|
|
841
|
+
self,
|
|
842
|
+
operation_type: str,
|
|
843
|
+
column_name: "Optional[str]" = None,
|
|
844
|
+
column_definition: "Optional[ColumnDefinition]" = None,
|
|
845
|
+
constraint_name: "Optional[str]" = None,
|
|
846
|
+
constraint_definition: "Optional[ConstraintDefinition]" = None,
|
|
847
|
+
new_type: "Optional[str]" = None,
|
|
848
|
+
new_name: "Optional[str]" = None,
|
|
849
|
+
after_column: "Optional[str]" = None,
|
|
850
|
+
first: bool = False,
|
|
851
|
+
using_expression: "Optional[str]" = None,
|
|
852
|
+
) -> None:
|
|
853
|
+
self.operation_type = operation_type
|
|
854
|
+
self.column_name = column_name
|
|
855
|
+
self.column_definition = column_definition
|
|
856
|
+
self.constraint_name = constraint_name
|
|
857
|
+
self.constraint_definition = constraint_definition
|
|
858
|
+
self.new_type = new_type
|
|
859
|
+
self.new_name = new_name
|
|
860
|
+
self.after_column = after_column
|
|
861
|
+
self.first = first
|
|
862
|
+
self.using_expression = using_expression
|
|
677
863
|
|
|
678
864
|
|
|
679
|
-
@dataclass
|
|
680
865
|
class CreateSchema(DDLBuilder):
|
|
681
866
|
"""Builder for CREATE SCHEMA [IF NOT EXISTS] schema_name [AUTHORIZATION user_name]."""
|
|
682
867
|
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
868
|
+
__slots__ = ("_authorization", "_if_not_exists", "_schema_name")
|
|
869
|
+
|
|
870
|
+
def __init__(self, schema_name: str, dialect: DialectType = None) -> None:
|
|
871
|
+
"""Initialize CREATE SCHEMA with schema name.
|
|
872
|
+
|
|
873
|
+
Args:
|
|
874
|
+
schema_name: Name of the schema to create
|
|
875
|
+
dialect: SQL dialect to use
|
|
876
|
+
"""
|
|
877
|
+
super().__init__(dialect=dialect)
|
|
878
|
+
self._schema_name = schema_name
|
|
879
|
+
self._if_not_exists = False
|
|
880
|
+
self._authorization: Optional[str] = None
|
|
686
881
|
|
|
687
882
|
def name(self, schema_name: str) -> Self:
|
|
688
883
|
self._schema_name = schema_name
|
|
@@ -713,12 +908,9 @@ class CreateSchema(DDLBuilder):
|
|
|
713
908
|
)
|
|
714
909
|
|
|
715
910
|
|
|
716
|
-
@dataclass
|
|
717
911
|
class CreateTableAsSelect(DDLBuilder):
|
|
718
912
|
"""Builder for CREATE TABLE [IF NOT EXISTS] ... AS SELECT ... (CTAS).
|
|
719
913
|
|
|
720
|
-
Supports optional column list and parameterized SELECT sources.
|
|
721
|
-
|
|
722
914
|
Example:
|
|
723
915
|
builder = (
|
|
724
916
|
CreateTableAsSelectBuilder()
|
|
@@ -736,10 +928,14 @@ class CreateTableAsSelect(DDLBuilder):
|
|
|
736
928
|
- as_select(select_query): Set the SELECT source (SQL, SelectBuilder, or str).
|
|
737
929
|
"""
|
|
738
930
|
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
931
|
+
__slots__ = ("_columns", "_if_not_exists", "_select_query", "_table_name")
|
|
932
|
+
|
|
933
|
+
def __init__(self, dialect: DialectType = None) -> None:
|
|
934
|
+
super().__init__(dialect=dialect)
|
|
935
|
+
self._table_name: Optional[str] = None
|
|
936
|
+
self._if_not_exists = False
|
|
937
|
+
self._columns: list[str] = []
|
|
938
|
+
self._select_query: Optional[object] = None
|
|
743
939
|
|
|
744
940
|
def name(self, table_name: str) -> Self:
|
|
745
941
|
self._table_name = table_name
|
|
@@ -753,7 +949,7 @@ class CreateTableAsSelect(DDLBuilder):
|
|
|
753
949
|
self._columns = list(cols)
|
|
754
950
|
return self
|
|
755
951
|
|
|
756
|
-
def as_select(self, select_query:
|
|
952
|
+
def as_select(self, select_query: "Union[str, exp.Expression]") -> Self:
|
|
757
953
|
self._select_query = select_query
|
|
758
954
|
return self
|
|
759
955
|
|
|
@@ -805,23 +1001,40 @@ class CreateTableAsSelect(DDLBuilder):
|
|
|
805
1001
|
)
|
|
806
1002
|
|
|
807
1003
|
|
|
808
|
-
@dataclass
|
|
809
1004
|
class CreateMaterializedView(DDLBuilder):
|
|
810
|
-
"""Builder for CREATE MATERIALIZED VIEW [IF NOT EXISTS] ... AS SELECT ...
|
|
1005
|
+
"""Builder for CREATE MATERIALIZED VIEW [IF NOT EXISTS] ... AS SELECT ..."""
|
|
1006
|
+
|
|
1007
|
+
__slots__ = (
|
|
1008
|
+
"_columns",
|
|
1009
|
+
"_hints",
|
|
1010
|
+
"_if_not_exists",
|
|
1011
|
+
"_refresh_mode",
|
|
1012
|
+
"_select_query",
|
|
1013
|
+
"_storage_parameters",
|
|
1014
|
+
"_tablespace",
|
|
1015
|
+
"_using_index",
|
|
1016
|
+
"_view_name",
|
|
1017
|
+
"_with_data",
|
|
1018
|
+
)
|
|
1019
|
+
|
|
1020
|
+
def __init__(self, view_name: str, dialect: DialectType = None) -> None:
|
|
1021
|
+
"""Initialize CREATE MATERIALIZED VIEW with view name.
|
|
811
1022
|
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
1023
|
+
Args:
|
|
1024
|
+
view_name: Name of the materialized view to create
|
|
1025
|
+
dialect: SQL dialect to use
|
|
1026
|
+
"""
|
|
1027
|
+
super().__init__(dialect=dialect)
|
|
1028
|
+
self._view_name = view_name
|
|
1029
|
+
self._if_not_exists = False
|
|
1030
|
+
self._columns: list[str] = []
|
|
1031
|
+
self._select_query: Optional[Union[str, exp.Expression]] = None
|
|
1032
|
+
self._with_data: Optional[bool] = None
|
|
1033
|
+
self._refresh_mode: Optional[str] = None
|
|
1034
|
+
self._storage_parameters: dict[str, Any] = {}
|
|
1035
|
+
self._tablespace: Optional[str] = None
|
|
1036
|
+
self._using_index: Optional[str] = None
|
|
1037
|
+
self._hints: list[str] = []
|
|
825
1038
|
|
|
826
1039
|
def name(self, view_name: str) -> Self:
|
|
827
1040
|
self._view_name = view_name
|
|
@@ -835,7 +1048,7 @@ class CreateMaterializedView(DDLBuilder):
|
|
|
835
1048
|
self._columns = list(cols)
|
|
836
1049
|
return self
|
|
837
1050
|
|
|
838
|
-
def as_select(self, select_query:
|
|
1051
|
+
def as_select(self, select_query: "Union[str, exp.Expression]") -> Self:
|
|
839
1052
|
self._select_query = select_query
|
|
840
1053
|
return self
|
|
841
1054
|
|
|
@@ -926,18 +1139,24 @@ class CreateMaterializedView(DDLBuilder):
|
|
|
926
1139
|
)
|
|
927
1140
|
|
|
928
1141
|
|
|
929
|
-
@dataclass
|
|
930
1142
|
class CreateView(DDLBuilder):
|
|
931
|
-
"""Builder for CREATE VIEW [IF NOT EXISTS] ... AS SELECT ...
|
|
1143
|
+
"""Builder for CREATE VIEW [IF NOT EXISTS] ... AS SELECT ..."""
|
|
932
1144
|
|
|
933
|
-
|
|
934
|
-
"""
|
|
1145
|
+
__slots__ = ("_columns", "_hints", "_if_not_exists", "_select_query", "_view_name")
|
|
935
1146
|
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
1147
|
+
def __init__(self, view_name: str, dialect: DialectType = None) -> None:
|
|
1148
|
+
"""Initialize CREATE VIEW with view name.
|
|
1149
|
+
|
|
1150
|
+
Args:
|
|
1151
|
+
view_name: Name of the view to create
|
|
1152
|
+
dialect: SQL dialect to use
|
|
1153
|
+
"""
|
|
1154
|
+
super().__init__(dialect=dialect)
|
|
1155
|
+
self._view_name = view_name
|
|
1156
|
+
self._if_not_exists = False
|
|
1157
|
+
self._columns: list[str] = []
|
|
1158
|
+
self._select_query: Optional[Union[str, exp.Expression]] = None
|
|
1159
|
+
self._hints: list[str] = []
|
|
941
1160
|
|
|
942
1161
|
def name(self, view_name: str) -> Self:
|
|
943
1162
|
self._view_name = view_name
|
|
@@ -951,7 +1170,7 @@ class CreateView(DDLBuilder):
|
|
|
951
1170
|
self._columns = list(cols)
|
|
952
1171
|
return self
|
|
953
1172
|
|
|
954
|
-
def as_select(self, select_query:
|
|
1173
|
+
def as_select(self, select_query: "Union[str, exp.Expression]") -> Self:
|
|
955
1174
|
self._select_query = select_query
|
|
956
1175
|
return self
|
|
957
1176
|
|
|
@@ -1007,31 +1226,25 @@ class CreateView(DDLBuilder):
|
|
|
1007
1226
|
)
|
|
1008
1227
|
|
|
1009
1228
|
|
|
1010
|
-
@dataclass
|
|
1011
1229
|
class AlterTable(DDLBuilder):
|
|
1012
|
-
"""Builder for ALTER TABLE
|
|
1013
|
-
|
|
1014
|
-
Supports column operations (add, drop, alter type, rename) and constraint operations.
|
|
1230
|
+
"""Builder for ALTER TABLE operations.
|
|
1015
1231
|
|
|
1016
1232
|
Example:
|
|
1017
1233
|
builder = (
|
|
1018
|
-
|
|
1234
|
+
AlterTable("users")
|
|
1019
1235
|
.add_column("email", "VARCHAR(255)", not_null=True)
|
|
1020
1236
|
.drop_column("old_field")
|
|
1021
1237
|
.add_constraint("check_age", "CHECK (age >= 18)")
|
|
1022
1238
|
)
|
|
1023
1239
|
"""
|
|
1024
1240
|
|
|
1025
|
-
|
|
1026
|
-
_operations: "list[AlterOperation]" = field(default_factory=list)
|
|
1027
|
-
_schema: "Optional[str]" = None
|
|
1028
|
-
_if_exists: bool = False
|
|
1241
|
+
__slots__ = ("_if_exists", "_operations", "_schema", "_table_name")
|
|
1029
1242
|
|
|
1030
|
-
def __init__(self, table_name: str) -> None:
|
|
1031
|
-
super().__init__()
|
|
1243
|
+
def __init__(self, table_name: str, dialect: DialectType = None) -> None:
|
|
1244
|
+
super().__init__(dialect=dialect)
|
|
1032
1245
|
self._table_name = table_name
|
|
1033
|
-
self._operations = []
|
|
1034
|
-
self._schema = None
|
|
1246
|
+
self._operations: list[AlterOperation] = []
|
|
1247
|
+
self._schema: Optional[str] = None
|
|
1035
1248
|
self._if_exists = False
|
|
1036
1249
|
|
|
1037
1250
|
def if_exists(self) -> "Self":
|
|
@@ -1277,17 +1490,22 @@ class AlterTable(DDLBuilder):
|
|
|
1277
1490
|
raise AssertionError
|
|
1278
1491
|
|
|
1279
1492
|
|
|
1280
|
-
@dataclass
|
|
1281
1493
|
class CommentOn(DDLBuilder):
|
|
1282
|
-
"""Builder for COMMENT ON ... IS ... statements.
|
|
1494
|
+
"""Builder for COMMENT ON ... IS ... statements."""
|
|
1283
1495
|
|
|
1284
|
-
|
|
1285
|
-
"""
|
|
1496
|
+
__slots__ = ("_column", "_comment", "_table", "_target_type")
|
|
1286
1497
|
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1498
|
+
def __init__(self, dialect: DialectType = None) -> None:
|
|
1499
|
+
"""Initialize COMMENT ON builder.
|
|
1500
|
+
|
|
1501
|
+
Args:
|
|
1502
|
+
dialect: SQL dialect to use
|
|
1503
|
+
"""
|
|
1504
|
+
super().__init__(dialect=dialect)
|
|
1505
|
+
self._target_type: Optional[str] = None
|
|
1506
|
+
self._table: Optional[str] = None
|
|
1507
|
+
self._column: Optional[str] = None
|
|
1508
|
+
self._comment: Optional[str] = None
|
|
1291
1509
|
|
|
1292
1510
|
def on_table(self, table: str) -> Self:
|
|
1293
1511
|
self._target_type = "TABLE"
|
|
@@ -1318,15 +1536,21 @@ class CommentOn(DDLBuilder):
|
|
|
1318
1536
|
raise AssertionError
|
|
1319
1537
|
|
|
1320
1538
|
|
|
1321
|
-
@dataclass
|
|
1322
1539
|
class RenameTable(DDLBuilder):
|
|
1323
|
-
"""Builder for ALTER TABLE ... RENAME TO ... statements.
|
|
1540
|
+
"""Builder for ALTER TABLE ... RENAME TO ... statements."""
|
|
1324
1541
|
|
|
1325
|
-
|
|
1326
|
-
|
|
1542
|
+
__slots__ = ("_new_name", "_old_name")
|
|
1543
|
+
|
|
1544
|
+
def __init__(self, old_name: str, dialect: DialectType = None) -> None:
|
|
1545
|
+
"""Initialize RENAME TABLE with old name.
|
|
1327
1546
|
|
|
1328
|
-
|
|
1329
|
-
|
|
1547
|
+
Args:
|
|
1548
|
+
old_name: Current name of the table
|
|
1549
|
+
dialect: SQL dialect to use
|
|
1550
|
+
"""
|
|
1551
|
+
super().__init__(dialect=dialect)
|
|
1552
|
+
self._old_name = old_name
|
|
1553
|
+
self._new_name: Optional[str] = None
|
|
1330
1554
|
|
|
1331
1555
|
def table(self, old_name: str) -> Self:
|
|
1332
1556
|
self._old_name = old_name
|