NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #683 most downloaded on PyPI
Snowflake SQLAlchemy Dialect
Last release 5 days ago
29 Sep 2026
Release timing varies
gaps range from 8 days to 3 months
Some releases are documented
notes for 24 of 55 stable releases
4 versions withdrawn
withdrawn after publishing
9 years old
63 releases · first in 2017
Nothing published for this version
Nothing published for this version
Nothing published for this version
One column per quarter.
Breaking change: drop SQLAlchemy 1.4 support. The dialect now requires SQLAlchemy>=2.0.0. Users still on SQLAlchemy 1.4 should pin to snowflake-sqlalc…
SQLAlchemy>=2.0.0. Users still on SQLAlchemy 1.4 should pin to snowflake-sqlalchemy<2.0.0.>=3.9, <=3.14.regexp_match and regexp_replace flags rendered as bound parameters instead of literal strings (#SNOW-3573046). Flags passed to ColumnElement.regexp_match(..., flags=...) and ColumnElement.regexp_replace(..., flags=...) were processed through the standard parameter pipeline, producing incorrect SQL. Flags are now rendered as inline string literals, matching Snowflake's expected REGEXP_LIKE(col, pattern, 'i') / REGEXP_REPLACE(col, pattern, replacement, 'i') syntax.Nothing published for this version
[Sensitive connection parameters](https://github.com/snowflakedb/snowflake-sqlalchemy#sensitive-connection-parameters): We curated a set of connector
v1.11.0 (July 7, 2026)
Sensitive connection parameters: We curated a set of connector kwargs (host, protocol, token_file_path, private_key_file, ocsp_response_cache_filename, connection_diag_log_path, crl_cache_dir, unsafe_file_write, unsafe_skip_file_permissions_check) that can no longer be supplied via the URL query string — pass them via connect_args= in create_engine() instead (applications already doing so are unaffected). If you encounter a possible behavioral change, set SNOWFLAKE_SQLALCHEMY_LEGACY_URL_PARAMS=1 and follow the instructions at Sensitive connection parameters.
Improve _url() helper and create_connect_args connection-parameter handling:
account and region values are now validated against an allowlist of DNS-safe characters (alphanumeric, -, ., _) before being interpolated into the connection URL, preventing URL-authority corruption from unexpected characters.user values are percent-encoded before being placed in the URL userinfo component, preserving the original value delivered to the connector while preventing @, ?, and # from being misinterpreted as URL delimiters.ClusterByOption now raises TypeError at DDL compile time when an expression element is neither a str nor a sqlalchemy.sql.expression.TextClause. Previously, such values were silently coerced via str(), which produced malformed DDL (e.g. bind-parameter placeholders like :id_1) for any expression beyond a bare column name. The accepted types match the documented constructor signature; code using only str or text(...) is unaffected.
Improve identifier quoting and string-literal escaping for caller-supplied values across the DDL compiler so they are rendered consistently with the rest of the dialect. Column keys in MERGE INTO (both the WHEN NOT MATCHED … INSERT list and WHEN MATCHED … SET targets), stage namespaces/names, format_name, and file_format are now routed through the identifier preparer, and a quote=False schema or column label is quoted when it contains characters that would otherwise require quoting instead of being emitted verbatim. Cloud-storage URIs, CREDENTIALS, and ENCRYPTION clauses (shared by COPY INTO and CREATE STAGE) and FILES=(…) entries now apply the dialect's standard literal escaping ('→'', \→\\); CREATE STAGE builds its SQL from the container's fields rather than repr(container). Legal identifiers — including upper-case names that Snowflake folds — still render bare, so existing DDL is unchanged.
Improve escaping in CopyIntoStorage / CreateStage / CreateFileFormat and add secret redaction (SNOW-3656048):
FILE_FORMAT option string values (e.g. CSVFormatter().date_format(...), file_extension, timestamp_format) are now escaped before being embedded in the compiled SQL, improving single-quote escaping (SNOW-3649888).repr() of AWSBucket, AzureContainer, GCSBucket (and, transitively, CopyIntoStorage) now masks cloud secrets — AWS_SECRET_KEY, AWS_KEY_ID, AWS_TOKEN, AZURE_SAS_TOKEN, MASTER_KEY are rendered as '***' (SNOW-3649782). Compiled SQL is unchanged.SnowflakeSecretRedactionFilter, add_secret_redaction_filter(), and redact_secrets(). Prefer STORAGE_INTEGRATION to avoid putting secrets in SQL at all (SNOW-3649850).Fix get_view_definition silently truncating or failing for view names that contain a single quote or backslash (e.g. o'brien). The name is now SQL-escaped (' → '', \ → \\) before being embedded in the SHOW VIEWS LIKE '...' literal, so such views are found correctly and no query manipulation is possible via a crafted view name.
Optimise single-table reflection (SNOW-3720548): reflecting one table no longer scans the entire schema, reducing latency and Snowflake credit usage for targeted Inspector calls.
Nothing published for this version
Fix regexp_match and regexp_replace flags rendered as bound parameters instead of literal strings (#SNOW-3573046). Flags passed to ColumnElement.regex
regexp_match and regexp_replace flags rendered as bound parameters instead of literal strings (#SNOW-3573046). Flags passed to ColumnElement.regexp_match(..., flags=...) and ColumnElement.regexp_replace(..., flags=...) were processed through the standard parameter pipeline, producing incorrect SQL. Flags are now rendered as inline string literals, matching Snowflake's expected REGEXP_LIKE(col, pattern, 'i') / REGEXP_REPLACE(col, pattern, replacement, 'i') syntax._StructuredTypeInfoManager.get_table_columns. The DESC TABLE fallback path used raw denormalised names in an f-string while all other reflection paths apply ip.quote(denormalize_name(...)) via _always_quote_join. Schema and table components are now consistently double-quoted before the statement is constructed, and the method delegates to get_table_columns_by_full_name to collapse the two previously divergent code paths.…the literal double-quoted form. Fix security vulnerability: schema names are now always URL-encoded regardless of case_sensitive_schema, preventing sp…
with_loader_criteria silently dropping filters on non-Snowflake dialects (#676). Importing snowflake-sqlalchemy previously altered SQLAlchemy's ORM compilation for every dialect in the process, causing loader-criteria filters to be omitted inside sealed subqueries when using PostgreSQL, MySQL, SQLite, etc. Snowflake dialect behavior is unchanged; the BCR-1057 lateral-join workaround is now scoped to Snowflake connections only.UUID column type to sqlalchemy.sql.sqltypes.UUID for reflection on SQLAlchemy 2.x (#681). Previously reflected as NullType. Values are returned as plain strings (as_uuid=False) rather than uuid.UUID instances. No change on SQLAlchemy 1.4 where the generic UUID type does not exist.CopyIntoStorage (SNOW-721174, #368).referred_schema=None normalization in foreign key reflection to the default schema only (#610, SNOW-2313675):
referred_schema=None, preserving compatibility with the upstream reflection test suite and with applications that do not qualify default-schema FK targets.referred_schema, which prevents SQLAlchemy's _reflect_fk from autoloading a non-default-schema target from the wrong place (the bug behind #610) and avoids the Alembic autogenerate mismatch that previously occurred when user metadata explicitly qualified a cross-schema FK that happened to target the default schema.SnowflakeBase, snowflake_declarative_base(), and SnowflakeSession to enable efficient bulk inserts for ORM models with nullable optional columns (SNOW-893080, #441). When session.bulk_save_objects() is used with models that have randomly populated nullable columns, SQLAlchemy normally groups objects by their set of non-None column keys, producing O(N) separate INSERT statements. SnowflakeBase / snowflake_declarative_base() pre-populate all plain-nullable columns at construction time, and SnowflakeSession passes render_nulls=True so all objects share the same parameter-key set and are batched into a single executemany INSERT._split_schema_by_dot now correctly parses SQL-escaped double-quotes ("") inside quoted schema/database identifiers (e.g. "my""schema" → my"schema), preventing silent truncation of identifiers containing literal quote characters.denormalize_column_name now correctly double-quotes quoted_name("mycol", True) columns in CLUSTER BY clauses instead of silently dropping the case-sensitivity signal. The caller has already opted into case-sensitive semantics by constructing a quoted_name(..., True), so this is honoured independently of the dialect flag._has_object (used by has_table / has_sequence) now applies denormalize_name to both the schema and object name before building the DESC SQL, making it consistent with all other reflection methods._NameUtils swap in create_connect_args — when the URL's case_sensitive_identifiers value differs from the current dialect state, the name_utils instance is replaced rather than mutated in place, so concurrent readers on other threads observe either the old or the new instance but never a torn update.case_sensitive_identifiers opt-in engine flag (kwarg or ?case_sensitive_identifiers=True URL param) governing three related behaviours. The default is False; existing applications are unaffected unless they explicitly opt in:
TABLE) are normalised to quoted_name("table", True) instead of returning unchanged, preventing key-lookup mismatches between creation and reflection.MyCol from a quoted Snowflake column) are returned as quoted_name("MyCol", True) instead of a plain str. Emitted SQL is identical in both modes (_requires_quotes force-quotes any name containing uppercase chars); the difference is only observable via isinstance(..., quoted_name) and .quote.'"myschema"' or '"mydb"."myschema"' — have their extracted parts marked quote=True by _split_schema_by_dot, preserving case-sensitivity in emitted SQL. Without the flag, the extracted parts keep quote=None and the preparer's _requires_quotes heuristic decides per-part (stripping inner quotes for all-lowercase parts, which matches pre-PR behaviour). Use quoted_name("myschema", True) or MetaData(schema=quoted_name(..., True)) to opt into case-sensitivity on a per-value basis without enabling the flag.create_snowflake_engine(url, schema=..., case_sensitive_schema=True) helper that URL-encodes case-sensitive schema names using %22 so the Snowflake connector receives the literal double-quoted form. Fix security vulnerability: schema names are now always URL-encoded regardless of case_sensitive_schema, preventing special characters (?, #, /) from being misinterpreted as URL delimiters by SQLAlchemy's URL parser.snowflake.sqlalchemy.alembic_util.render_item — a drop-in Alembic render_item hook for env.py that serialises quoted_name columns with quote=True correctly in generated migration files, preventing Alembic autogenerate from silently converting case-sensitive column names to uppercase.SnowflakeWarning at DDL compile time when Identity() is used on a primary key column, alerting users that ORM flush operations will raise a FlushError. The warning is emitted once per unique (table, column) pair per Python process. Use Sequence() instead.schema='database.schema' notation. This allows reflecting and joining tables from different databases in a single session without raw SQL. (#456)/) when div_is_floordiv=True: the Snowflake compiler now correctly delegates to the SQLAlchemy base implementation, emitting CAST(col AS NUMERIC) for integer operands as it did before #545 introduced the override (#618).get_multi_columns, get_multi_pk_constraint, get_multi_unique_constraints, get_multi_foreign_keys for SQLAlchemy 2.x bulk reflection — each issues one schema-wide query per reflection pass instead of one query per table.get_columns now uses DESC TABLE directly (per-table, live) since get_multi_columns handles all bulk reflection; temporary tables and dynamic tables are reflected correctly without schema-wide queries.SHOW INDEXES IN TABLE replacing the previous SHOW TABLES LIKE approach for single-table index reflection, eliminating SQL LIKE wildcard false-positives and case-sensitivity bugs._always_quote_join helper that always quotes denormalised identifiers — ensures correct SQL for case-sensitive table and schema names in per-table reflection paths.referred_schema resolution so reflected FKs always keep their actual schema unless the target lives in the connection's default schema. Previously FKs whose target shared the reflected non-default schema were reported with referred_schema=None, which caused SQLAlchemy's _reflect_fk to autoload from the wrong schema and raise NoReferencedColumnError during Alembic autogenerate._parse_pk_rows, _parse_uk_rows, _parse_fk_rows) so correctness fixes propagate to both per-table and schema-wide reflection paths.cache_column_metadata=True opt-in enables per-table SHOW … IN TABLE queries for get_pk_constraint, get_unique_constraints, get_foreign_keys, and get_indexes on SQLAlchemy 1.4.get_pk_constraint, get_unique_constraints, get_foreign_keys, and get_indexes now automatically use per-table SHOW … IN TABLE queries without any opt-in flag. Previously these methods always issued SHOW … IN SCHEMA even for single-table Inspector calls (e.g. pandas.read_sql_table()), causing ~20-second delays on schemas with thousands of tables (SNOW-689531).Add support for DECFLOAT and VECTOR data types
DECFLOAT and VECTOR data typesILIKE in queriesSYSDATE() renderingNone arguments in internal schema resolution (#623).SHOW TABLES returns empty string table names, causing IndexError during reflection (#296).always, cycle, order, etc.).pytest-xdist parallel test support via per-worker schema provisioning hooks.pandas lower bound in sa14 test environment from <2.1 to >=2.1.1,<2.2 to ensure pre-built wheels are available for Python 3.12Updated supported max python version to 3.13
v1.8.2 (December 9, 2025)
snowflake-connector-pythonv1.8.1 (December 9, 2025)
Add logging of SQLAlchemy version
snowflake-connector-python<5.0.0Fix exception for structured type columns dropped while collecting meetadata
Fix get_multi_indexes issue, wrong assign of returned indexes when processing multiple indexes in a table
Fix compilation of Merge and Copy Into was not working
Fix dependency on DESCRIBE TABLE columns quantity (differences in columns caused by Snowflake parameters).
Fix support for SqlAlchemy ARRAY.
_ as initial character.force_div_is_floordiv flag to override div_is_floordiv new default value False in SnowflakeDialect.
False, the / division operator will be treated as a float division and // as a floor division.div_is_floor_div as False.Fix quoting of _ as column name
_ as column nameAdd support for partition by to copy into
Add support for dynamic tables and required options
v1.7.0(November 22, 2024)
Update internal project workflow with pypi publishing
v1.6.1(July 9, 2024)
v1.6.0(July 8, 2024)
hatch & uv for managing project virtual environmentsv1.5.4
Limit SQLAlchemy to < 2.0.0 before releasing version compatible with 2.0
v1.5.3(April 16, 2024)
Bump min SQLAlchemy to 1.4.19 for outer lateral join
v1.5.2(April 11, 2024)
Fixed a compatibility issue with Snowflake Behavioral Change 1057 on outer lateral join, for more details check https://docs.snowflake.com/en/release-
externalbrowser authentication not caching due to incorrect parsing of boolean query parameters.
Added option to create a temporary stage command. Added support for geometry type. Fixed a compatibility issue of regex expression with SQLAlchemy 1.4
Added option to create a temporary stage command. Added support for geometry type. Fixed a compatibility issue of regex expression with SQLAlchemy 1.4.49.
Re-applied the application name of driver connection SnowflakeConnection to SnowflakeSQLAlchemy.
SnowflakeConnection to SnowflakeSQLAlchemy.SnowflakeDialect.get_columns now throws a NoSuchTableError exception when the specified table doesn't exist, instead of the more vague KeyError.sqlalchemy.func.now is not rendered correctly.Bumped snowflake-connector-python dependency to newest version which supports Python 3.11.
Updated the application name of driver connection SnowflakeConnection to SnowflakeSQLAlchemy.
SnowflakeConnection to SnowflakeSQLAlchemy.Fixed a bug that percent signs in a non-compiled statement should not be interpolated with emtpy sequence when executed.
Fixed a bug that SnowflakeDialect.normalize_name and SnowflakeDialect.denormalize_name could not handle empty string.
SnowflakeDialect.normalize_name and SnowflakeDialect.denormalize_name could not handle empty string.sqlalchemy.engine.url._rfc_1738_quote as it is removed from SQLAlchemy v1.4.42.Improved performance by standardizing string interpolations to f-strings.
Fixed breaking changes introduced in release 1.4.0 that:
Added support for regexp_match, regexp_replace in sqlalchemy.sql.expression.ColumnOperators.
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →