|
32 | 32 | from .base import Executable
|
33 | 33 | from .base import SchemaVisitor
|
34 | 34 | from .elements import ClauseElement
|
| 35 | +from .schema import Table |
| 36 | +from .selectable import Selectable |
| 37 | +from .selectable import TableClause |
35 | 38 | from .. import exc
|
36 | 39 | from .. import util
|
37 | 40 | from ..util import topological
|
|
47 | 50 | from .schema import Index
|
48 | 51 | from .schema import SchemaItem
|
49 | 52 | from .schema import Sequence as Sequence # noqa: F401
|
50 |
| - from .schema import Table |
51 |
| - from .selectable import TableClause |
52 | 53 | from ..engine.base import Connection
|
53 | 54 | from ..engine.interfaces import CacheStats
|
54 | 55 | from ..engine.interfaces import CompiledCacheType
|
@@ -544,6 +545,93 @@ def __init__(
|
544 | 545 | self.include_foreign_key_constraints = include_foreign_key_constraints
|
545 | 546 |
|
546 | 547 |
|
| 548 | +class CreateTableAs(ExecutableDDLElement): |
| 549 | + """Represent a CREATE TABLE ... AS (CTAS) statement. |
| 550 | +
|
| 551 | + This creates a new table directly from the output of a SELECT. |
| 552 | + The set of columns in the new table is derived from the |
| 553 | + SELECT list; constraints, indexes, and defaults are not copied. |
| 554 | +
|
| 555 | + :param selectable: :class:`_sql.Selectable` |
| 556 | + The SELECT (or other selectable) providing the columns and rows. |
| 557 | +
|
| 558 | + :param target: str | :class:`_sql.TableClause` |
| 559 | + Table name or object. If passed as a string, it must be |
| 560 | + unqualified; use the ``schema`` argument for qualification. |
| 561 | +
|
| 562 | + :param schema: str, optional |
| 563 | + Schema or owner name. If both ``schema`` and the target object |
| 564 | + specify a schema, they must match. |
| 565 | +
|
| 566 | + :param temporary: bool, default False. |
| 567 | + If True, render ``TEMPORARY`` (PostgreSQL, MySQL, SQLite), or |
| 568 | + a ``#<name>`` temporary table on SQL Server. Dialects that do |
| 569 | + not support this option will raise :class:`.CompileError`. |
| 570 | +
|
| 571 | + :param if_not_exists: bool, default False. |
| 572 | + If True, render ``IF NOT EXISTS`` where supported |
| 573 | + (PostgreSQL, MySQL, SQLite). Dialects that do not support this |
| 574 | + option will raise :class:`.CompileError`. |
| 575 | + """ |
| 576 | + |
| 577 | + __visit_name__ = "create_table_as" |
| 578 | + inherit_cache = False |
| 579 | + |
| 580 | + def __init__( |
| 581 | + self, |
| 582 | + selectable: Selectable, |
| 583 | + target: Union[str, TableClause], |
| 584 | + *, |
| 585 | + schema: Optional[str] = None, |
| 586 | + temporary: bool = False, |
| 587 | + if_not_exists: bool = False, |
| 588 | + ): |
| 589 | + if isinstance(target, TableClause): |
| 590 | + t_name = target.name |
| 591 | + t_schema = target.schema |
| 592 | + |
| 593 | + if not t_name or not str(t_name).strip(): |
| 594 | + raise exc.ArgumentError("Table name must be non-empty") |
| 595 | + |
| 596 | + if ( |
| 597 | + schema is not None |
| 598 | + and t_schema is not None |
| 599 | + and schema != t_schema |
| 600 | + ): |
| 601 | + raise exc.ArgumentError( |
| 602 | + f"Conflicting schema: target={t_schema!r}, " |
| 603 | + f"schema={schema!r}" |
| 604 | + ) |
| 605 | + final_schema = ( |
| 606 | + schema |
| 607 | + if (schema is not None and t_schema is None) |
| 608 | + else t_schema |
| 609 | + ) |
| 610 | + elif isinstance(target, str): |
| 611 | + if not target.strip(): |
| 612 | + raise exc.ArgumentError("Table name must be non-empty") |
| 613 | + if "." in target: |
| 614 | + raise exc.ArgumentError( |
| 615 | + "Target string must be unqualified (use schema=)." |
| 616 | + ) |
| 617 | + t_name = target |
| 618 | + final_schema = schema |
| 619 | + else: |
| 620 | + raise exc.ArgumentError("target must be a string, TableClause") |
| 621 | + |
| 622 | + self.table = TableClause(t_name, schema=final_schema) |
| 623 | + |
| 624 | + self.target = target |
| 625 | + self.schema = final_schema |
| 626 | + self.selectable = selectable |
| 627 | + self.temporary = bool(temporary) |
| 628 | + self.if_not_exists = bool(if_not_exists) |
| 629 | + |
| 630 | + @property |
| 631 | + def generated_table(self) -> TableClause: |
| 632 | + return self.table |
| 633 | + |
| 634 | + |
547 | 635 | class _DropView(_DropBase["Table"]):
|
548 | 636 | """Semi-public 'DROP VIEW' construct.
|
549 | 637 |
|
|
0 commit comments