Skip to content

Fix SnowflakeHook transaction support: multi-statement SQL and AUTOCOMMIT#65040

Open
kaxil wants to merge 3 commits intoapache:mainfrom
astronomer:add-snowflake-transaction-support
Open

Fix SnowflakeHook transaction support: multi-statement SQL and AUTOCOMMIT#65040
kaxil wants to merge 3 commits intoapache:mainfrom
astronomer:add-snowflake-transaction-support

Conversation

@kaxil
Copy link
Copy Markdown
Member

@kaxil kaxil commented Apr 11, 2026

Fixes two longstanding issues with SnowflakeHook.run() that broke Snowflake transaction support:

  1. Multi-statement SQL with split_statements=False (SnowflakeHook.run() doesn't accept multiple statements without split_statements #48233): When sending a multi-statement block like BEGIN; INSERT ...; COMMIT; as a single cursor.execute() call, Snowflake rejects it because the connector defaults MULTI_STATEMENT_COUNT=1. Now passes num_statements=0 (auto-detect) to cursor.execute() when split_statements=False.

  2. AUTOCOMMIT session parameter override (Session_parameter AUTOCOMMIT is not set in Snowflake connection #30236): Users who set session_parameters={"AUTOCOMMIT": True} on their connection had it immediately overridden by set_autocommit(conn, False) in run(). Now respects the session parameter when autocommit=False (the default).

Design rationale

Why override _run_command() instead of modifying run() inline? The base DbApiHook._run_command() handles logging, lineage tracking, and row counts. Overriding it in SnowflakeHook keeps the num_statements logic close to cursor.execute() while preserving all side effects. The override drops the psycopg list-to-tuple conversion since Snowflake never uses psycopg.

Why case-insensitive AUTOCOMMIT check? Snowflake session parameters are case-insensitive, so users may write {"autocommit": True} or {"AUTOCOMMIT": True}. The check normalizes to uppercase.

Why set conn.autocommit_mode = True in the else branch? When we skip set_autocommit() to respect the session parameter, get_autocommit() would return False (since autocommit_mode was never set), causing a redundant conn.commit() at the end of run(). Setting the mode explicitly avoids this.

Why _get_static_conn_params instead of _get_conn_params()? The static version is a @cached_property and doesn't trigger OAuth token refresh, avoiding surprise HTTP requests from what should be a simple config check.

Validated against real Snowflake

All three scenarios pass against a real Snowflake instance:

  • Multi-statement block (CREATE + INSERT + SELECT + DROP) with split_statements=False
  • Transaction block (CREATE + BEGIN + INSERT x3 + COMMIT) with split_statements=False
  • Backward compat: split_statements=True (default) still works with separate query IDs

Closes #48233
Closes #30236

@kaxil kaxil requested a review from potiuk as a code owner April 11, 2026 00:55
@boring-cyborg boring-cyborg bot added area:providers provider:snowflake Issues related to Snowflake provider labels Apr 11, 2026
@kaxil kaxil requested a review from josh-fell April 11, 2026 00:55
@kaxil
Copy link
Copy Markdown
Member Author

kaxil commented Apr 11, 2026

cc @josh-fell

…MMIT

When split_statements=False, pass num_statements=0 to cursor.execute()
so Snowflake accepts multi-statement SQL blocks (BEGIN/INSERT/COMMIT).
Previously this failed with "Actual statement count N did not match
the desired statement count 1".

Also respect AUTOCOMMIT in session_parameters instead of unconditionally
overriding it with set_autocommit(conn, False).

Closes: apache#48233
Closes: apache#30236
@kaxil kaxil force-pushed the add-snowflake-transaction-support branch from 646758c to 226f277 Compare April 11, 2026 00:56
kaxil added 2 commits April 11, 2026 03:38
_session_params_has_autocommit already handles non-dict inputs, so
the intermediate variable with a dict annotation is unnecessary and
causes a mypy assignment error.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:providers provider:snowflake Issues related to Snowflake provider

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SnowflakeHook.run() doesn't accept multiple statements without split_statements Session_parameter AUTOCOMMIT is not set in Snowflake connection

1 participant