Skip to content

SnowflakeHook.run() doesn't accept multiple statements without split_statements #48233

Description

@set92

Apache Airflow version

Other Airflow 2 version (please specify below)

If "Other Airflow 2 version" selected, which one?

2.10.3

What happened?

I have a query like this:

BEGIN;
CREATE TABLE ();
INSERT INTO () SELECT FROM ();
INSERT INTO () SELECT FROM ();
DELETE FROM WHERE;
COMMIT;

If using SnowflakeSqlApiOperator() runs without any problem, or without specifying anything. All in a single block. With the hook I tried to run it with semicolons, without them (snowflake support team recommended it), and the only option that worked was with the split_statements=True, but then you have multiple query id, harder to review, and I think the transaction will keep intact, but not sure.

Also if you try to run with split_statements=False, it will throw the error

Traceback (most recent call last):
  File "/usr/local/airflow/.local/lib/python3.11/site-packages/airflow/models/taskinstance.py", line 767, in _execute_task
    result = _execute_callable(context=context, **execute_callable_kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/airflow/.local/lib/python3.11/site-packages/airflow/models/taskinstance.py", line 733, in _execute_callable
    return ExecutionCallableRunner(
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/airflow/.local/lib/python3.11/site-packages/airflow/utils/operator_helpers.py", line 252, in run
    return self.func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/airflow/.local/lib/python3.11/site-packages/airflow/models/baseoperator.py", line 417, in wrapper
    return func(self, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/airflow/.local/lib/python3.11/site-packages/airflow/operators/python.py", line 238, in execute
    return_value = self.execute_callable()
                   ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/airflow/.local/lib/python3.11/site-packages/airflow/operators/python.py", line 256, in execute_callable
    return runner.run(*self.op_args, **self.op_kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/airflow/.local/lib/python3.11/site-packages/airflow/utils/operator_helpers.py", line 252, in run
    return self.func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/airflow/dags/ghs/bi/spl_on_snowflake/actions.py", line 71, in create_pu_per_client_func
    snflk_hook.run(sql_statement, split_statements=False)
  File "/usr/local/airflow/.local/lib/python3.11/site-packages/airflow/providers/snowflake/hooks/snowflake.py", line 435, in run
    self._run_command(cur, sql_statement, parameters)  # type: ignore[attr-defined]
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/airflow/.local/lib/python3.11/site-packages/airflow/providers/common/sql/hooks/sql.py", line 549, in _run_command
    cur.execute(sql_statement)
  File "/usr/local/airflow/.local/lib/python3.11/site-packages/snowflake/connector/cursor.py", line 1097, in execute
    Error.errorhandler_wrapper(self.connection, self, error_class, errvalue)
  File "/usr/local/airflow/.local/lib/python3.11/site-packages/snowflake/connector/errors.py", line 284, in errorhandler_wrapper
    handed_over = Error.hand_to_other_handler(
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/airflow/.local/lib/python3.11/site-packages/snowflake/connector/errors.py", line 339, in hand_to_other_handler
    cursor.errorhandler(connection, cursor, error_class, error_value)
  File "/usr/local/airflow/.local/lib/python3.11/site-packages/snowflake/connector/errors.py", line 215, in default_errorhandler
    raise error_class(
snowflake.connector.errors.ProgrammingError: 000008 (0A000): 01bb3de5-020c-cab0-0006-21fb059c3996: Actual statement count 6 did not match the desired statement count 1.

Following with this error you can get to https://docs.snowflake.com/en/developer-guide/sql-api/submitting-multiple-statements, where it mentions a parameter MULTI_STATEMENT_COUNT that can be modified to send the same number as the queries you have in the string and it will work. But I wasn't sure how, or if it is possible to pass it to the Hook.

What you think should happen instead?

As with SnowflakeSqlApiOperator(), I would have expected to be able to run all in a single string.

How to reproduce

I suppose you can test it with

sql_statement = """
BEGIN TRANSACTION;
CREATE TABLE Persons (id int);
SELECT * FROM Persons;
COMMIT;
"""
snflk_hook = SnowflakeHook(conn_id=snflk_conn_id).run(sql_statement, split_statements=False)

Operating System

MWAA - Linux

Versions of Apache Airflow Providers

No response

Deployment

Amazon (AWS) MWAA

Deployment details

No response

Anything else?

No response

Are you willing to submit PR?

  • Yes I am willing to submit a PR!

Code of Conduct

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions