Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

gjarzab
Copy link

@gjarzab gjarzab commented Sep 12, 2025

This PR adds support for the Create Table AS construct, along with a new .into() constructor on Select.

Description

Introduces CreateTableAs element which can then be used to render CREATE TABLE ... AS ... statements.
A CreateTableAs can either be constructed directly or from a Select / Selectable by using the new .into constructor method added to the Select class.

Compilation with the default dialect does not render any flags like TEMPORARY or IF NOT EXISTS. Support for these can be added in the dialect specific compilers. Compilation of CreateTableAs for SQLite supports TEMPORARY and IF NOT EXISTS.

#Basic CreateTableAs usage
CreateTableAs(select(users.c.id, users.c.name).select_from(users), "active_users")

# Using .into() on a Select
select(users.c.id).where(users.c.status == "inactive").into("inactive_users")

# With schema and IF NOT EXISTS
select(users.c.id).into("archived", schema="analytics", if_not_exists=True)

# Temporary table
select(users.c.id, users.c.name).into("temp_snapshot", temporary=True)

Fixes issue : #4950

Checklist

This pull request is:

  • A documentation / typographical / small typing error fix
    • Good to go, no issue or tests are needed
  • A short code fix
    • please include the issue number, and create an issue if none exists, which
      must include a complete example of the issue. one line code fixes without an
      issue and demonstration will not be accepted.
    • Please include: Fixes: #<issue number> in the commit message
    • please include tests. one line code fixes without tests will not be accepted.
  • A new feature implementation
    • please include the issue number, and create an issue if none exists, which must
      include a complete example of how the feature would look.
    • Please include: Fixes: #<issue number> in the commit message
    • please include tests.

@zzzeek zzzeek requested a review from sqla-tester September 15, 2025 22:10
Copy link
Collaborator

@sqla-tester sqla-tester left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, this is sqla-tester setting up my work on behalf of zzzeek to try to get revision a18f053 of this pull request into gerrit so we can run tests and reviews and stuff

@sqla-tester
Copy link
Collaborator

New Gerrit review created for change a18f053: https://gerrit.sqlalchemy.org/c/sqlalchemy/sqlalchemy/+/6115

@zzzeek
Copy link
Member

zzzeek commented Sep 15, 2025

I'm very swamped in PRs, sorry this is moving slowly

@zzzeek
Copy link
Member

zzzeek commented Sep 19, 2025

are you able to run tox -e pep484 and take a look at the typing errors ?

Copy link
Member

@zzzeek zzzeek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good so far. lots of tests. I want to use fixtures as much as we can for these tests to limit the verbosity. We have a decorator @testing.fixture() that is basically a synonym for pytest fixtures: https://docs.pytest.org/en/6.2.x/fixture.html

a lot of the code in this sqlite suite might be pretty old but let's try to use the more recent patterns for these new tests. (at some point I have to break test_sqlite into a package also).

temporary: bool = False,
if_not_exists: bool = False,
) -> "CreateTableAs":
from .ddl import CreateTableAs
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if this ddl import can't be at the top., we have a system used for in-method imports that's threadsafe

@util.preload_module("sqlalchemy.ddl")
def my_method(self, ...):
    ddl = util.preloaded.ddl
    return ddl.CreateTableAs(...)

self.src_def = "CREATE TABLE src (id INTEGER PRIMARY KEY, name TEXT)"
self.seed_def = "INSERT INTO src (name) VALUES ('a'), ('b')"

def teardown_test(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note in the exec_sql() function at the top of the file it has a comment "convert all tests to not use this" :) so for these raw SQL fixtures, I'd do it like this:

def teardown_test(self):
    with testing.db.begin() as conn:
         conn.exec_driver_sql(...)
         conn.exec_driver_sql(...)
         conn.exec_driver_sql(...)
         ...

but also I think these drops can all be turned into fixtures, see my other comments

__only_on__ = "sqlite"
__backend__ = True

@staticmethod
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use a fixture for this:

@testing.fixture
def source_table(self):
    return table("src", column("id"), column("name"))

then in a test

def test_thing(self, source_table, connection):
    stmt = select(source_table).where(....)

return table("src", column("id"), column("name"))

@staticmethod
def _two_sources():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use a fixture here also...


def setup_test(self):
# define a physical src table and seed a couple rows
self.src_def = "CREATE TABLE src (id INTEGER PRIMARY KEY, name TEXT)"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these can be fixtures

@testing.fixture
def src_def(self, connection):
    connection.exec_driver_sql("CREATE TABLE ....")
    yield
    connection.exec_driver_sql("DROP TABLE ....")

@testing.fixture
def seeded_src_def(self, connection, src_def):
    connection.exec_driver_sql("INSERT INTO src (name) VALUES ('a'), ('b')")

then in a test

def test_a_thing(self, seeded_src_def):
    # the table is there, and aill also drop when finished

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the feedback. I updated the SQLite and default dialect tests to use fixtures. A yield fixture also works nicely for cleaning up of tables created via CreateTableAs within the SQLite backend tests.

add CreateTableAs for default dialect and SQLite.
add Select.into constructor for CreateTableAs.
@gjarzab gjarzab force-pushed the feature/create-table-as branch from a18f053 to aa14126 Compare September 23, 2025 03:09
@gjarzab
Copy link
Author

gjarzab commented Sep 23, 2025

are you able to run tox -e pep484 and take a look at the typing errors ?

This was due to an instance of TableClause being assigned to the target attribute defined in ExecutableDDLElement which is of type Union[SchemaItem, str,None].

Now CreateTableAs assigns a TableClause instance to an attribute called table and leaves the target attribute as None. As far as I can tell this shouldn't cause any issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants