Skip to content

Releases: snowflakedb/snowflake-sqlalchemy

Release

21 May 11:49
cad3497

Choose a tag to compare

  • v1.10.0 (May 20, 2026)
    • Fix 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.
    • Map Snowflake 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.
    • Add GCS bucket support for CopyIntoStorage (SNOW-721174, #368).
    • Scope referred_schema=None normalization in foreign key reflection to the default schema only (#610, SNOW-2313675):
      • When reflecting the default schema, same-schema FKs (default → default) keep the established SQLAlchemy convention of referred_schema=None, preserving compatibility with the upstream reflection test suite and with applications that do not qualify default-schema FK targets.
      • When reflecting a non-default schema every FK keeps its actual 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.
    • Add 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.
    • Fix case-sensitive identifier handling (SNOW-1232488). Always-active bug fixes with no behavioural change for default users:
      • _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.
      • Atomic _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.
    • Add 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:
      • ALL-UPPERCASE reserved-word identifiers (e.g. TABLE) are normalised to quoted_name("table", True) instead of returning unchanged, preventing key-lookup mismatches between creation and reflection.
      • Mixed-case reflected identifiers (e.g. 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.
      • Schema strings with inner double-quotes — e.g. '"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.
    • Add 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.
    • Add 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.
    • Emit 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.
    • Add support for cross-database schema reflection using schema='database.schema' notation. This allows reflecting and joining tables from different databases in a single session without raw SQL. (#456)
    • Restored backward-compatible SQL generation for true division (/) 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).
    • Introduce composite key ordering, fixes #450
    • Optimise reflection performance (SNOW-689531, #656):
      • Add 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.
      • SQLAlchemy 2.x 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.
      • Fix 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.
      • Add _always_quote_join helper that always quotes denormalised identifiers — ensures correct SQL for case-sensitive table and schema names in per-table reflection paths.
      • Fix foreign key 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.
      • Add shared row-parsing helpers (_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.
      • On SQLAlchemy 2.x, 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).

Release

04 Mar 13:47
c382492

Choose a tag to compare

  • v1.9.0 (March 4, 2026)
    • Add support for DECFLOAT and VECTOR data types
    • Add server_version_info support
    • Add support for ILIKE in queries
    • Fix SYSDATE() rendering
    • Fix and improve schema reflection (SNOW-593204, SNOW-2331576, SNOW-2852779)
      • Fix crash when reflecting without specifying a schema, caused by None arguments in internal schema resolution (#623).
      • Fix crash when SHOW TABLES returns empty string table names, causing IndexError during reflection (#296).
      • Fix incomplete identity column reflection metadata, now includes all fields required by SQLAlchemy 2.0+ (always, cycle, order, etc.).
      • Introduce shared helper for fully-qualified schema name resolution, replacing inconsistent ad-hoc patterns across reflection methods.
      • Refactor column reflection internals into dedicated helpers to reduce complexity without changing behavior.
      • Add pytest-xdist parallel test support via per-worker schema provisioning hooks.
    • Bump 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.12
    • Fix SQLAlchemy version parsing (SNOW-3066571)
    • Document support for session parameters (like QUERY_TAG), references: #644
    • Support timezone in timestamp and datetime types (#199)

Release

10 Dec 08:33
a24e666

Choose a tag to compare

  • v1.8.2 (December 9, 2025)

    • Updated supported max python version to 3.13
    • Version 1.8.1 yanked due to max python version supported by snowflake-connector-python
  • v1.8.1 (December 9, 2025)

    • Add python 3.14 to project metadata

Release

04 Dec 20:12
c5bad89

Choose a tag to compare

  • v1.8.0(December 5, 2025)
    • Add logging of SQLAlchemy version
    • Bump snowflake-connector-python<5.0.0
    • Add python up to 3.14
    • Add logging of SQLAlchemy version and pandas (if used)

Release

09 Sep 14:36
d5f155f

Choose a tag to compare

  • v1.7.7(September 3, 2025)
    • Fix exception for structured type columns dropped while collecting meetadata

Release

10 Jul 02:36
3d90790

Choose a tag to compare

  • v1.7.6(July 10, 2025)
    • Fix get_multi_indexes issue, wrong assign of returned indexes when processing multiple indexes in a table

Release

24 Jun 16:25
10ce071

Choose a tag to compare

  • v1.7.5(June 20, 2025)
    • Fix compilation of Merge and Copy Into was not working

Release

10 Jun 15:54
09f47b0

Choose a tag to compare

  • v1.7.4(June 10, 2025)
    • Fix dependency on DESCRIBE TABLE columns quantity (differences in columns caused by Snowflake parameters).
    • Fix unnecessary condition was causing issues when parsing StructuredTypes columns.
    • Update README.md to include instructions on how to verify package signatures using cosign.

Release

14 Jan 19:49
87c48cc

Choose a tag to compare

  • v1.7.3(January 15, 2025)
    • Fix support for SqlAlchemy ARRAY.
    • Fix return value of snowflake get_table_names.
    • Fix incorrect quoting of identifiers with _ as initial character.
    • Fix ARRAY type not supported in HYBRID tables.
    • Add force_div_is_floordiv flag to override div_is_floordiv new default value False in SnowflakeDialect.
      • With the flag in False, the / division operator will be treated as a float division and // as a floor division.
      • This flag is added to maintain backward compatibility with the previous behavior of Snowflake Dialect division.
      • This flag will be removed in the future and Snowflake Dialect will use div_is_floor_div as False.

Release

17 Dec 21:37
115da35

Choose a tag to compare

  • v1.7.2(December 18, 2024)
    • Fix quoting of _ as column name
    • Fix index columns was not being reflected
    • Fix index reflection cache not working
    • Add support for structured OBJECT datatype
    • Add support for structured ARRAY datatype