snowflake-snowpark-python 1.49.0__tar.gz → 1.50.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/CHANGELOG.md +32 -0
- {snowflake_snowpark_python-1.49.0/src/snowflake_snowpark_python.egg-info → snowflake_snowpark_python-1.50.1}/PKG-INFO +5 -3
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/setup.py +2 -1
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/analyzer/datatype_mapper.py +10 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/analyzer/select_statement.py +323 -33
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/analyzer/snowflake_plan.py +8 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/compiler/cte_utils.py +42 -1
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/compiler/plan_compiler.py +7 -2
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/compiler/telemetry_constants.py +5 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/data_source/datasource_partitioner.py +2 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/data_source/drivers/base_driver.py +11 -2
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/data_source/utils.py +71 -2
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/event_table_telemetry.py +1 -1
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/proto/generated/ast_pb2.pyi +317 -3
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/server_connection.py +129 -4
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/telemetry.py +42 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/type_utils.py +278 -5
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/udf_utils.py +3 -3
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/xml_schema_inference.py +31 -17
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/context.py +127 -2
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/dataframe.py +124 -52
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/dataframe_ai_functions.py +1 -1
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/dataframe_reader.py +123 -21
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/functions.py +3 -3
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/mock/_select_statement.py +2 -2
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/relational_grouped_dataframe.py +10 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/session.py +67 -3
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/types.py +3 -1
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/version.py +1 -1
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1/src/snowflake_snowpark_python.egg-info}/PKG-INFO +5 -3
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake_snowpark_python.egg-info/requires.txt +4 -2
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/LICENSE.txt +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/MANIFEST.in +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/README.md +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/pyproject.toml +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/setup.cfg +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/__init__.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_functions/__init__.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_functions/general_functions.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_functions/scalar_functions.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/__init__.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/analyzer/__init__.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/analyzer/analyzer.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/analyzer/analyzer_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/analyzer/binary_expression.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/analyzer/binary_plan_node.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/analyzer/expression.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/analyzer/grouping_set.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/analyzer/metadata_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/analyzer/query_plan_analysis_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/analyzer/schema_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/analyzer/snowflake_plan_node.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/analyzer/sort_expression.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/analyzer/table_function.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/analyzer/table_merge_expression.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/analyzer/unary_expression.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/analyzer/unary_plan_node.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/analyzer/window_expression.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/ast/__init__.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/ast/batch.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/ast/builder.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/ast/utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/code_generation.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/compiler/__init__.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/compiler/large_query_breakdown.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/compiler/query_generator.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/compiler/repeated_subquery_elimination.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/compiler/utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/data_source/__init__.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/data_source/datasource_reader.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/data_source/datasource_typing.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/__init__.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/base_dialect.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/databricks_dialect.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/mysql_dialect.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/oracledb_dialect.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/postgresql_dialect.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/sqlite3_dialect.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/sqlserver_dialect.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/data_source/drivers/__init__.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/data_source/drivers/databricks_driver.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/data_source/drivers/oracledb_driver.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/data_source/drivers/psycopg2_driver.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/data_source/drivers/pymsql_driver.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/data_source/drivers/pyodbc_driver.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/data_source/drivers/sqlite_driver.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/data_source/jdbc.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/debug_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/error_message.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/open_telemetry.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/packaging_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/proto/generated/__init__.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/proto/generated/ast_pb2.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/select_projection_complexity_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/snowpark_profiler.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/temp_table_auto_cleaner.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/xml_reader.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/_internal/xpath_handlers.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/async_job.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/catalog.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/column.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/dataframe_analytics_functions.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/dataframe_na_functions.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/dataframe_profiler.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/dataframe_stat_functions.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/dataframe_writer.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/exceptions.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/file_operation.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/files.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/lineage.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/mock/__init__.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/mock/_analyzer.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/mock/_connection.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/mock/_constants.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/mock/_functions.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/mock/_nop_analyzer.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/mock/_nop_connection.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/mock/_nop_plan.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/mock/_options.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/mock/_pandas_util.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/mock/_plan.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/mock/_plan_builder.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/mock/_snowflake_data_type.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/mock/_snowflake_to_pandas_converter.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/mock/_stage_registry.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/mock/_stored_procedure.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/mock/_telemetry.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/mock/_udaf.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/mock/_udf.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/mock/_udf_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/mock/_udtf.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/mock/_util.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/mock/_window_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/mock/exceptions.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/__init__.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/config/__init__.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/config/__main__.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/config/envvars.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/config/pubsub.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/conftest.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/__init__.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/__init__.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/aggregation_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/align_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/apply_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/binary_op_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/concat_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/cumulative_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/cut_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/frame.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/generator_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/get_dummies_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/groupby_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/indexing_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/io_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/isin_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/join_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/ordered_dataframe.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/pivot_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/resample_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/row_count_estimation.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/session.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/snowpark_pandas_types.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/statement_params_constants.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/telemetry.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/timestamp_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/transpose_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/type_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/unpivot_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/where_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_internal/window_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/_typing.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/compiler/__init__.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/compiler/doc_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/compiler/ray_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/compiler/snowflake_query_compiler.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/docstrings/__init__.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/docstrings/base.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/docstrings/dataframe.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/docstrings/datetime_index.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/docstrings/general.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/docstrings/groupby.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/docstrings/index.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/docstrings/io.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/docstrings/resample.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/docstrings/series.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/docstrings/series_utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/docstrings/shared_docs.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/docstrings/timedelta_index.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/docstrings/window.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/extensions/__init__.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/extensions/base_overrides.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/extensions/dataframe_extensions.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/extensions/dataframe_groupby_overrides.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/extensions/dataframe_overrides.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/extensions/datetime_index.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/extensions/general_overrides.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/extensions/index.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/extensions/indexing_overrides.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/extensions/io_overrides.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/extensions/pd_extensions.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/extensions/resample_overrides.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/extensions/resampler_groupby_overrides.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/extensions/rolling_groupby_overrides.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/extensions/series_extensions.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/extensions/series_groupby_overrides.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/extensions/series_overrides.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/extensions/snow_partition_iterator.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/extensions/timedelta_index.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/extensions/utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/extensions/window_overrides.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/io/__init__.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/io/factories.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/io/snow_io.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/utils/__init__.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/utils/error_message.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/utils/exceptions.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/utils/frontend_constants.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/utils/numpy_to_pandas.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/plugin/utils/warning_message.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/modin/utils.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/py.typed +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/query_history.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/row.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/secrets.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/stored_procedure.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/stored_procedure_profiler.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/table.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/table_function.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/testing.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/udaf.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/udf.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/udf_profiler.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/udtf.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake/snowpark/window.py +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake_snowpark_python.egg-info/SOURCES.txt +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake_snowpark_python.egg-info/dependency_links.txt +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake_snowpark_python.egg-info/namespace_packages.txt +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake_snowpark_python.egg-info/not-zip-safe +0 -0
- {snowflake_snowpark_python-1.49.0 → snowflake_snowpark_python-1.50.1}/src/snowflake_snowpark_python.egg-info/top_level.txt +0 -0
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# Release History
|
|
2
2
|
|
|
3
|
+
## 1.50.1 (2026-05-06)
|
|
4
|
+
|
|
5
|
+
### Snowpark Python API Updates
|
|
6
|
+
|
|
7
|
+
#### Bug Fixes
|
|
8
|
+
|
|
9
|
+
- Fixed a bug where using parameter bindings for `CALL` queries issued through `session.sql` would raise an error.
|
|
10
|
+
- Fixed a bug where `StringType` columns from Iceberg tables were not recognized as max-size strings.
|
|
11
|
+
- Improved the `FileNotFoundError` message raised when `INFER_SCHEMA` returns zero rows so it also points to file format options (`PARSE_HEADER`, `SKIP_HEADER`, `ON_ERROR=CONTINUE`) that can silently filter everything out, instead of only suggesting a missing path.
|
|
12
|
+
|
|
13
|
+
## 1.50.0 (2026-04-23)
|
|
14
|
+
|
|
15
|
+
### Snowpark Python API Updates
|
|
16
|
+
|
|
17
|
+
#### New Features
|
|
18
|
+
|
|
19
|
+
- Added `artifact_repository` support to `udtf_configs` in `session.read.dbapi()`, enabling users to specify a custom artifact repository (e.g. PyPI) for packages used by the internal UDTF during distributed ingestion.
|
|
20
|
+
|
|
21
|
+
#### Bug Fixes
|
|
22
|
+
|
|
23
|
+
- Fixed a bug where `TRY_CAST` reader option is ignored when calling `DataFrameReader.schema().csv()`.
|
|
24
|
+
- Fixed a bug where `event_table_telemetry` is using incorrect resource attributes.
|
|
25
|
+
- Fixed a bug where `value_contains_null` was not propagated for `MapType` in `_as_nested` function.
|
|
26
|
+
- Fixed a bug where CTE optimization incorrectly deduplicated subtrees containing non-deterministic data generation functions (e.g. `uuid_string()`).
|
|
27
|
+
- Fixed a bug where vectorized UDFs using non-anaconda package repositories did not specify the pandas package by default.
|
|
28
|
+
|
|
29
|
+
### Snowpark pandas API Updates
|
|
30
|
+
|
|
31
|
+
#### Dependency Updates
|
|
32
|
+
|
|
33
|
+
- Updated the supported `pandas` versions to <=2.4 (was previously <=2.3.1).
|
|
34
|
+
|
|
3
35
|
## 1.49.0 (2026-04-13)
|
|
4
36
|
|
|
5
37
|
### Snowpark Python API Updates
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: snowflake-snowpark-python
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.50.1
|
|
4
4
|
Summary: Snowflake Snowpark for Python
|
|
5
5
|
Home-page: https://www.snowflake.com/
|
|
6
6
|
Author: Snowflake, Inc
|
|
@@ -50,7 +50,7 @@ Requires-Dist: snowflake-connector-python[pandas]<5.0.0,>=3.17.0; extra == "pand
|
|
|
50
50
|
Provides-Extra: modin
|
|
51
51
|
Requires-Dist: snowflake-connector-python[pandas]<5.0.0,>=3.17.0; extra == "modin"
|
|
52
52
|
Requires-Dist: modin<0.38.0,>=0.36.0; extra == "modin"
|
|
53
|
-
Requires-Dist: pandas<=2.
|
|
53
|
+
Requires-Dist: pandas<=2.4; extra == "modin"
|
|
54
54
|
Requires-Dist: tqdm; extra == "modin"
|
|
55
55
|
Requires-Dist: ipywidgets; extra == "modin"
|
|
56
56
|
Provides-Extra: secure-local-storage
|
|
@@ -74,10 +74,11 @@ Requires-Dist: tox; extra == "development"
|
|
|
74
74
|
Requires-Dist: snowflake.core<2,>=1.0.0; extra == "development"
|
|
75
75
|
Requires-Dist: psutil; extra == "development"
|
|
76
76
|
Requires-Dist: lxml; extra == "development"
|
|
77
|
+
Requires-Dist: pyarrow; extra == "development"
|
|
77
78
|
Provides-Extra: modin-development
|
|
78
79
|
Requires-Dist: snowflake-connector-python[pandas]<5.0.0,>=3.17.0; extra == "modin-development"
|
|
79
80
|
Requires-Dist: modin<0.38.0,>=0.36.0; extra == "modin-development"
|
|
80
|
-
Requires-Dist: pandas<=2.
|
|
81
|
+
Requires-Dist: pandas<=2.4; extra == "modin-development"
|
|
81
82
|
Requires-Dist: tqdm; extra == "modin-development"
|
|
82
83
|
Requires-Dist: ipywidgets; extra == "modin-development"
|
|
83
84
|
Requires-Dist: pytest<8.0.0; extra == "modin-development"
|
|
@@ -98,6 +99,7 @@ Requires-Dist: tox; extra == "modin-development"
|
|
|
98
99
|
Requires-Dist: snowflake.core<2,>=1.0.0; extra == "modin-development"
|
|
99
100
|
Requires-Dist: psutil; extra == "modin-development"
|
|
100
101
|
Requires-Dist: lxml; extra == "modin-development"
|
|
102
|
+
Requires-Dist: pyarrow; extra == "modin-development"
|
|
101
103
|
Requires-Dist: scipy<=1.16.3; extra == "modin-development"
|
|
102
104
|
Requires-Dist: statsmodels; extra == "modin-development"
|
|
103
105
|
Requires-Dist: scikit-learn; extra == "modin-development"
|
|
@@ -43,7 +43,7 @@ PANDAS_REQUIREMENTS = [
|
|
|
43
43
|
MODIN_REQUIREMENTS = [
|
|
44
44
|
*PANDAS_REQUIREMENTS,
|
|
45
45
|
f"modin{MODIN_DEPENDENCY_VERSION}",
|
|
46
|
-
"pandas<=2.
|
|
46
|
+
"pandas<=2.4",
|
|
47
47
|
"tqdm", # For progress bars during backend switching
|
|
48
48
|
"ipywidgets", # For enhanced progress bars in Jupyter notebooks
|
|
49
49
|
]
|
|
@@ -66,6 +66,7 @@ DEVELOPMENT_REQUIREMENTS = [
|
|
|
66
66
|
"snowflake.core>=1.0.0, <2", # Catalog
|
|
67
67
|
"psutil", # testing for telemetry
|
|
68
68
|
"lxml", # used in XML reader unit tests
|
|
69
|
+
"pyarrow", # used in dataframe reader tests
|
|
69
70
|
]
|
|
70
71
|
MODIN_DEVELOPMENT_REQUIREMENTS = [
|
|
71
72
|
# Snowpark pandas 3rd party library testing. Cap the scipy version because
|
|
@@ -401,6 +401,16 @@ def to_sql(
|
|
|
401
401
|
else str_to_sql(value)
|
|
402
402
|
)
|
|
403
403
|
|
|
404
|
+
if isinstance(datatype, StringType) and isinstance(
|
|
405
|
+
value, (bool, int, float, Decimal)
|
|
406
|
+
):
|
|
407
|
+
# Coerce common Python scalars to str so that VALUES and bind-param
|
|
408
|
+
# paths produce identical string representations. bool is a subclass
|
|
409
|
+
# of int so it must be checked first. Use lowercase for bools to
|
|
410
|
+
# match Snowflake's BOOLEAN::STRING cast semantics.
|
|
411
|
+
s = str(value).lower() if isinstance(value, bool) else str(value)
|
|
412
|
+
return to_sql(s, datatype, from_values_statement=from_values_statement)
|
|
413
|
+
|
|
404
414
|
if isinstance(datatype, _IntegralType):
|
|
405
415
|
return f"{value} :: INT"
|
|
406
416
|
|
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
import sys
|
|
6
6
|
import uuid
|
|
7
|
+
import re
|
|
7
8
|
from abc import ABC, abstractmethod
|
|
8
9
|
from collections import UserDict, defaultdict
|
|
9
10
|
from copy import copy, deepcopy
|
|
10
11
|
from enum import Enum
|
|
11
|
-
from functools import reduce
|
|
12
|
+
from functools import cached_property, reduce
|
|
12
13
|
from typing import (
|
|
13
14
|
TYPE_CHECKING,
|
|
14
15
|
AbstractSet,
|
|
@@ -20,6 +21,7 @@ from typing import (
|
|
|
20
21
|
Sequence,
|
|
21
22
|
Set,
|
|
22
23
|
Union,
|
|
24
|
+
Literal,
|
|
23
25
|
)
|
|
24
26
|
|
|
25
27
|
import snowflake.snowpark._internal.utils
|
|
@@ -86,6 +88,7 @@ from snowflake.snowpark._internal.utils import (
|
|
|
86
88
|
is_sql_select_statement,
|
|
87
89
|
ExprAliasUpdateDict,
|
|
88
90
|
)
|
|
91
|
+
import snowflake.snowpark.context as context
|
|
89
92
|
|
|
90
93
|
# Python 3.8 needs to use typing.Iterable because collections.abc.Iterable is not subscriptable
|
|
91
94
|
# Python 3.9 can use both
|
|
@@ -109,6 +112,22 @@ SEQUENCE_DEPENDENT_DATA_GENERATION = (
|
|
|
109
112
|
"seq8",
|
|
110
113
|
)
|
|
111
114
|
|
|
115
|
+
# Functions that are non-deterministic when called with zero arguments.
|
|
116
|
+
# Used only by the CTE optimizer to prevent deduplication of subtrees that
|
|
117
|
+
# generate random data. Other data generation functions (normal, zipf,
|
|
118
|
+
# uniform, randstr) always require a generator argument (e.g. random()),
|
|
119
|
+
# which is caught by recursive child inspection. seq* functions produce
|
|
120
|
+
# deterministic row-local counters and are safe to dedup.
|
|
121
|
+
NONDETERMINISTIC_DATA_GENERATION = (
|
|
122
|
+
"uuid_string",
|
|
123
|
+
"random",
|
|
124
|
+
)
|
|
125
|
+
# Matches zero-arg calls to nondeterministic functions in SQL text, e.g. "random()" or "UUID_STRING( )".
|
|
126
|
+
NONDETERMINISTIC_ZERO_ARG_RE = re.compile(
|
|
127
|
+
r"\b(?:" + "|".join(NONDETERMINISTIC_DATA_GENERATION) + r")\s*\(\s*\)",
|
|
128
|
+
re.IGNORECASE,
|
|
129
|
+
)
|
|
130
|
+
|
|
112
131
|
|
|
113
132
|
class ColumnChangeState(Enum):
|
|
114
133
|
"""The change state of a column when building a query from its subquery."""
|
|
@@ -653,9 +672,12 @@ class SelectableEntity(Selectable):
|
|
|
653
672
|
|
|
654
673
|
@SnowflakePlan.Decorator.wrap_exception
|
|
655
674
|
def _analyze_attributes(
|
|
656
|
-
sql: str,
|
|
675
|
+
sql: str,
|
|
676
|
+
session: "snowflake.snowpark.session.Session", # type: ignore
|
|
677
|
+
dataframe_uuid: Optional[str] = None,
|
|
678
|
+
query_params: Optional[Sequence[Any]] = None,
|
|
657
679
|
) -> List[Attribute]:
|
|
658
|
-
return analyze_attributes(sql, session, dataframe_uuid)
|
|
680
|
+
return analyze_attributes(sql, session, dataframe_uuid, query_params)
|
|
659
681
|
|
|
660
682
|
|
|
661
683
|
class SelectSQL(Selectable):
|
|
@@ -688,7 +710,7 @@ class SelectSQL(Selectable):
|
|
|
688
710
|
self.pre_actions[0].query_id_place_holder
|
|
689
711
|
)
|
|
690
712
|
self._schema_query = analyzer_utils.schema_value_statement(
|
|
691
|
-
_analyze_attributes(sql, self._session, self._uuid)
|
|
713
|
+
_analyze_attributes(sql, self._session, self._uuid, query_params=params)
|
|
692
714
|
) # Change to subqueryable schema query so downstream query plan can describe the SQL
|
|
693
715
|
self._query_param = None
|
|
694
716
|
else:
|
|
@@ -995,6 +1017,21 @@ class SelectStatement(Selectable):
|
|
|
995
1017
|
)
|
|
996
1018
|
return copied
|
|
997
1019
|
|
|
1020
|
+
@cached_property
|
|
1021
|
+
def contains_data_generation(self) -> bool:
|
|
1022
|
+
"""True when this node's projection, where, or order_by clauses
|
|
1023
|
+
contain non-deterministic data-generation expressions (e.g. zero-arg
|
|
1024
|
+
``uuid_string()``, ``random()``, ``uniform(1,100,random())``).
|
|
1025
|
+
limit and offset do not accept data generation expressions in snowflake.
|
|
1026
|
+
"""
|
|
1027
|
+
return (
|
|
1028
|
+
has_nondeterministic_data_generation_exp(self.projection)
|
|
1029
|
+
or has_nondeterministic_data_generation_exp(
|
|
1030
|
+
[self.where] if self.where else None
|
|
1031
|
+
)
|
|
1032
|
+
or has_nondeterministic_data_generation_exp(self.order_by)
|
|
1033
|
+
)
|
|
1034
|
+
|
|
998
1035
|
@property
|
|
999
1036
|
def column_states(self) -> ColumnStateDict:
|
|
1000
1037
|
if self._column_states is None:
|
|
@@ -1386,9 +1423,9 @@ class SelectStatement(Selectable):
|
|
|
1386
1423
|
):
|
|
1387
1424
|
# TODO: Clean up, this entire if case is parameter protection
|
|
1388
1425
|
can_be_flattened = False
|
|
1389
|
-
elif (
|
|
1390
|
-
|
|
1391
|
-
):
|
|
1426
|
+
elif (
|
|
1427
|
+
self.where or self.order_by or self.limit_
|
|
1428
|
+
) and has_data_generator_or_window_function_exp(cols):
|
|
1392
1429
|
can_be_flattened = False
|
|
1393
1430
|
elif self.where and (
|
|
1394
1431
|
(subquery_dependent_columns := derive_dependent_columns(self.where))
|
|
@@ -1399,6 +1436,23 @@ class SelectStatement(Selectable):
|
|
|
1399
1436
|
subquery_dependent_columns & new_column_states.active_columns
|
|
1400
1437
|
)
|
|
1401
1438
|
)
|
|
1439
|
+
or (
|
|
1440
|
+
# unflattenable condition: dropped column is used in subquery WHERE clause and dropped column status is NEW or CHANGED in the subquery
|
|
1441
|
+
# reason: we should not flatten because the dropped column is not available in the new query, leading to WHERE clause error
|
|
1442
|
+
# sample query: 'select "b" from (select "a" as "c", "b" from table where "c" > 1)' can not be flatten to 'select "b" from table where "c" > 1'
|
|
1443
|
+
(
|
|
1444
|
+
context._is_snowpark_connect_compatible_mode
|
|
1445
|
+
and context._snowpark_connect_flatten_select_after_sort
|
|
1446
|
+
)
|
|
1447
|
+
and new_column_states.dropped_columns
|
|
1448
|
+
and any(
|
|
1449
|
+
self.column_states[_col].change_state
|
|
1450
|
+
in (ColumnChangeState.NEW, ColumnChangeState.CHANGED_EXP)
|
|
1451
|
+
for _col in (
|
|
1452
|
+
subquery_dependent_columns & new_column_states.dropped_columns
|
|
1453
|
+
)
|
|
1454
|
+
)
|
|
1455
|
+
)
|
|
1402
1456
|
):
|
|
1403
1457
|
can_be_flattened = False
|
|
1404
1458
|
elif self.order_by and (
|
|
@@ -1411,6 +1465,23 @@ class SelectStatement(Selectable):
|
|
|
1411
1465
|
subquery_dependent_columns & new_column_states.active_columns
|
|
1412
1466
|
)
|
|
1413
1467
|
)
|
|
1468
|
+
or (
|
|
1469
|
+
# unflattenable condition: dropped column is used in subquery ORDER BY clause and dropped column status is NEW or CHANGED in the subquery
|
|
1470
|
+
# reason: we should not flatten because the dropped column is not available in the new query, leading to ORDER BY clause error
|
|
1471
|
+
# sample query: 'select "b" from (select "a" as "c", "b" order by "c")' can not be flatten to 'select "b" from table order by "c"'
|
|
1472
|
+
(
|
|
1473
|
+
context._is_snowpark_connect_compatible_mode
|
|
1474
|
+
and context._snowpark_connect_flatten_select_after_sort
|
|
1475
|
+
)
|
|
1476
|
+
and new_column_states.dropped_columns
|
|
1477
|
+
and any(
|
|
1478
|
+
self.column_states[_col].change_state
|
|
1479
|
+
in (ColumnChangeState.NEW, ColumnChangeState.CHANGED_EXP)
|
|
1480
|
+
for _col in (
|
|
1481
|
+
subquery_dependent_columns & new_column_states.dropped_columns
|
|
1482
|
+
)
|
|
1483
|
+
)
|
|
1484
|
+
)
|
|
1414
1485
|
):
|
|
1415
1486
|
can_be_flattened = False
|
|
1416
1487
|
elif self.distinct_:
|
|
@@ -1456,8 +1527,62 @@ class SelectStatement(Selectable):
|
|
|
1456
1527
|
self.df_ast_ids.copy() if self.df_ast_ids is not None else None
|
|
1457
1528
|
)
|
|
1458
1529
|
else:
|
|
1530
|
+
new_order_by = None
|
|
1531
|
+
new_from = self
|
|
1532
|
+
if (
|
|
1533
|
+
context._is_snowpark_connect_compatible_mode
|
|
1534
|
+
and context._snowpark_connect_flatten_select_after_sort
|
|
1535
|
+
) and self.order_by:
|
|
1536
|
+
order_by_dependent_columns = derive_dependent_columns(*self.order_by)
|
|
1537
|
+
if order_by_dependent_columns in (
|
|
1538
|
+
COLUMN_DEPENDENCY_DOLLAR,
|
|
1539
|
+
COLUMN_DEPENDENCY_ALL,
|
|
1540
|
+
):
|
|
1541
|
+
new_order_by = None
|
|
1542
|
+
elif any(
|
|
1543
|
+
col not in self.from_.column_states
|
|
1544
|
+
and col not in self.column_states
|
|
1545
|
+
for col in order_by_dependent_columns
|
|
1546
|
+
):
|
|
1547
|
+
new_order_by = None
|
|
1548
|
+
elif any(
|
|
1549
|
+
_col not in self.column_states
|
|
1550
|
+
or self.column_states[_col].change_state
|
|
1551
|
+
in (ColumnChangeState.CHANGED_EXP, ColumnChangeState.DROPPED)
|
|
1552
|
+
for _col in order_by_dependent_columns
|
|
1553
|
+
):
|
|
1554
|
+
new_from = copy(self)
|
|
1555
|
+
missing_columns = (
|
|
1556
|
+
order_by_dependent_columns
|
|
1557
|
+
- new_from.column_states.active_columns
|
|
1558
|
+
)
|
|
1559
|
+
base_projection: List[Expression] = (
|
|
1560
|
+
new_from.projection
|
|
1561
|
+
if new_from.projection is not None
|
|
1562
|
+
else list(new_from.column_states.projection)
|
|
1563
|
+
)
|
|
1564
|
+
new_from.projection = base_projection + [
|
|
1565
|
+
Attribute(col, DataType()) for col in missing_columns
|
|
1566
|
+
]
|
|
1567
|
+
new_col_states = derive_column_states_from_subquery(
|
|
1568
|
+
new_from.projection, new_from.from_
|
|
1569
|
+
)
|
|
1570
|
+
if new_col_states is not None:
|
|
1571
|
+
new_from.column_states = new_col_states
|
|
1572
|
+
new_from._projection_in_str = None
|
|
1573
|
+
new_from._commented_sql = None
|
|
1574
|
+
new_from._sql_query = None
|
|
1575
|
+
new_order_by = self.order_by
|
|
1576
|
+
else:
|
|
1577
|
+
new_from = self
|
|
1578
|
+
new_order_by = None
|
|
1579
|
+
else:
|
|
1580
|
+
new_order_by = self.order_by
|
|
1459
1581
|
new = SelectStatement(
|
|
1460
|
-
projection=cols,
|
|
1582
|
+
projection=cols,
|
|
1583
|
+
from_=new_from.to_subqueryable(),
|
|
1584
|
+
order_by=new_order_by,
|
|
1585
|
+
analyzer=self.analyzer,
|
|
1461
1586
|
)
|
|
1462
1587
|
new._merge_projection_complexity_with_subquery = (
|
|
1463
1588
|
can_select_projection_complexity_be_merged(
|
|
@@ -1478,12 +1603,30 @@ class SelectStatement(Selectable):
|
|
|
1478
1603
|
return new
|
|
1479
1604
|
|
|
1480
1605
|
def filter(self, col: Expression) -> "SelectStatement":
|
|
1606
|
+
self._session._retrieve_aggregation_function_list()
|
|
1481
1607
|
can_be_flattened = (
|
|
1482
1608
|
(not self.flatten_disabled)
|
|
1483
1609
|
and can_clause_dependent_columns_flatten(
|
|
1484
|
-
derive_dependent_columns(col),
|
|
1610
|
+
derive_dependent_columns(col),
|
|
1611
|
+
self.column_states,
|
|
1612
|
+
"filter",
|
|
1613
|
+
# In Snowpark Connect compatible mode, the NEW-column branch
|
|
1614
|
+
# below allows flattening through any subquery. Pass
|
|
1615
|
+
# subquery_has_limit so that branch can still reject
|
|
1616
|
+
# flattening across LIMIT/OFFSET, since WHERE cannot cross
|
|
1617
|
+
# LIMIT/OFFSET without changing semantics.
|
|
1618
|
+
subquery_has_limit_or_offset=(
|
|
1619
|
+
self.limit_ is not None or self.offset is not None
|
|
1620
|
+
),
|
|
1485
1621
|
)
|
|
1486
|
-
and not
|
|
1622
|
+
and not has_data_generator_or_window_function_exp(self.projection)
|
|
1623
|
+
and not (
|
|
1624
|
+
(
|
|
1625
|
+
context._is_snowpark_connect_compatible_mode
|
|
1626
|
+
and context._snowpark_connect_flatten_select_after_sort
|
|
1627
|
+
)
|
|
1628
|
+
and has_aggregation_function_exp(self.projection)
|
|
1629
|
+
) # sum(col) as new_col, new_col can not be flattened in where clause
|
|
1487
1630
|
and not (self.order_by and self.limit_ is not None)
|
|
1488
1631
|
)
|
|
1489
1632
|
if can_be_flattened:
|
|
@@ -1509,16 +1652,12 @@ class SelectStatement(Selectable):
|
|
|
1509
1652
|
def sort(self, cols: List[Expression]) -> "SelectStatement":
|
|
1510
1653
|
can_be_flattened = (
|
|
1511
1654
|
(not self.flatten_disabled)
|
|
1512
|
-
#
|
|
1513
|
-
#
|
|
1514
|
-
# number of record is satisfied.
|
|
1515
|
-
# Therefore, disallow sql simplification when the
|
|
1516
|
-
# current SelectStatement has a limit clause to avoid moving
|
|
1517
|
-
# order by in front of limit.
|
|
1655
|
+
# Disallow flattening when the current SelectStatement has a
|
|
1656
|
+
# limit clause to avoid moving order by in front of limit.
|
|
1518
1657
|
and (not self.limit_)
|
|
1519
1658
|
and (not self.offset)
|
|
1520
1659
|
and can_clause_dependent_columns_flatten(
|
|
1521
|
-
derive_dependent_columns(*cols), self.column_states
|
|
1660
|
+
derive_dependent_columns(*cols), self.column_states, "sort"
|
|
1522
1661
|
)
|
|
1523
1662
|
and not has_data_generator_exp(self.projection)
|
|
1524
1663
|
)
|
|
@@ -1557,7 +1696,7 @@ class SelectStatement(Selectable):
|
|
|
1557
1696
|
# .order_by(col1).select(col2).distinct() cannot be flattened because
|
|
1558
1697
|
# SELECT DISTINCT B FROM TABLE ORDER BY A is not valid SQL
|
|
1559
1698
|
and (not (self.order_by and self.has_projection))
|
|
1560
|
-
and not
|
|
1699
|
+
and not has_data_generator_or_window_function_exp(self.projection)
|
|
1561
1700
|
)
|
|
1562
1701
|
if can_be_flattened:
|
|
1563
1702
|
new = copy(self)
|
|
@@ -2048,7 +2187,13 @@ def can_projection_dependent_columns_be_flattened(
|
|
|
2048
2187
|
def can_clause_dependent_columns_flatten(
|
|
2049
2188
|
dependent_columns: Optional[AbstractSet[str]],
|
|
2050
2189
|
subquery_column_states: ColumnStateDict,
|
|
2190
|
+
clause: Literal["filter", "sort"],
|
|
2191
|
+
subquery_has_limit_or_offset: bool = False,
|
|
2051
2192
|
) -> bool:
|
|
2193
|
+
assert clause in (
|
|
2194
|
+
"filter",
|
|
2195
|
+
"sort",
|
|
2196
|
+
), f"Invalid clause called in can_clause_dependent_columns_flatten: {clause}"
|
|
2052
2197
|
if dependent_columns == COLUMN_DEPENDENCY_DOLLAR:
|
|
2053
2198
|
return False
|
|
2054
2199
|
elif (
|
|
@@ -2063,15 +2208,39 @@ def can_clause_dependent_columns_flatten(
|
|
|
2063
2208
|
dc_state = subquery_column_states.get(dc)
|
|
2064
2209
|
if dc_state:
|
|
2065
2210
|
if dc_state.change_state == ColumnChangeState.CHANGED_EXP:
|
|
2066
|
-
|
|
2211
|
+
if clause == "filter":
|
|
2212
|
+
return False
|
|
2213
|
+
# sort + CHANGED_EXP: safe in SCOS mode since ORDER BY
|
|
2214
|
+
# is evaluated after projection. Keep checking remaining
|
|
2215
|
+
# columns though — another column may be unsafe.
|
|
2216
|
+
elif not (
|
|
2217
|
+
context._is_snowpark_connect_compatible_mode
|
|
2218
|
+
and context._snowpark_connect_flatten_select_after_sort
|
|
2219
|
+
):
|
|
2220
|
+
return False
|
|
2067
2221
|
elif dc_state.change_state == ColumnChangeState.NEW:
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2222
|
+
if clause == "sort" and dc_state.dependent_columns in (
|
|
2223
|
+
COLUMN_DEPENDENCY_DOLLAR,
|
|
2224
|
+
COLUMN_DEPENDENCY_ALL,
|
|
2225
|
+
):
|
|
2226
|
+
# Scalar subqueries in sort can trigger Snowflake
|
|
2227
|
+
# internal errors when ORDER BY references them
|
|
2228
|
+
# at the same SELECT level.
|
|
2229
|
+
return False
|
|
2230
|
+
if not (
|
|
2231
|
+
context._is_snowpark_connect_compatible_mode
|
|
2232
|
+
and context._snowpark_connect_flatten_select_after_sort
|
|
2233
|
+
):
|
|
2234
|
+
return False
|
|
2235
|
+
# Compatible-mode safety: even though we loosened the
|
|
2236
|
+
# NEW-column flatten rule above, we must not flatten a
|
|
2237
|
+
# WHERE across LIMIT/OFFSET on a NEW column — that
|
|
2238
|
+
# would push the filter in front of the limit and
|
|
2239
|
+
# change the result set. (Sort has its own
|
|
2240
|
+
# `not self.limit_` guard at the call site.)
|
|
2241
|
+
if clause == "filter" and subquery_has_limit_or_offset:
|
|
2242
|
+
return False
|
|
2243
|
+
|
|
2075
2244
|
return True
|
|
2076
2245
|
|
|
2077
2246
|
|
|
@@ -2295,18 +2464,139 @@ def derive_column_states_from_subquery(
|
|
|
2295
2464
|
return column_states
|
|
2296
2465
|
|
|
2297
2466
|
|
|
2298
|
-
def
|
|
2467
|
+
def _check_expressions_for_types(
|
|
2468
|
+
expressions: Optional[List["Expression"]],
|
|
2469
|
+
check_data_gen: bool = False,
|
|
2470
|
+
check_window: bool = False,
|
|
2471
|
+
check_aggregation: bool = False,
|
|
2472
|
+
) -> bool:
|
|
2473
|
+
"""Efficiently check if expressions contain specific types in a single pass.
|
|
2474
|
+
|
|
2475
|
+
Args:
|
|
2476
|
+
expressions: List of expressions to check
|
|
2477
|
+
check_data_gen: Check for data generator functions
|
|
2478
|
+
check_window: Check for window functions
|
|
2479
|
+
check_aggregation: Check for aggregation functions
|
|
2480
|
+
|
|
2481
|
+
Returns:
|
|
2482
|
+
True if any requested type is found
|
|
2483
|
+
"""
|
|
2299
2484
|
if expressions is None:
|
|
2300
2485
|
return False
|
|
2486
|
+
|
|
2301
2487
|
for exp in expressions:
|
|
2302
|
-
if
|
|
2488
|
+
if exp is None:
|
|
2489
|
+
continue
|
|
2490
|
+
|
|
2491
|
+
# Check window functions
|
|
2492
|
+
if check_window and isinstance(exp, WindowExpression):
|
|
2303
2493
|
return True
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2494
|
+
|
|
2495
|
+
if check_data_gen:
|
|
2496
|
+
if isinstance(exp, FunctionExpression) and (
|
|
2497
|
+
exp.is_data_generator
|
|
2498
|
+
or exp.name.lower() in SEQUENCE_DEPENDENT_DATA_GENERATION
|
|
2499
|
+
):
|
|
2500
|
+
# https://docs.snowflake.com/en/sql-reference/functions-data-generation
|
|
2501
|
+
return True
|
|
2502
|
+
|
|
2503
|
+
# Check aggregation functions
|
|
2504
|
+
if check_aggregation and isinstance(exp, FunctionExpression):
|
|
2505
|
+
if exp.name.lower() in context._aggregation_function_set:
|
|
2506
|
+
return True
|
|
2507
|
+
|
|
2508
|
+
# Recursively check children.
|
|
2509
|
+
# Some expression types (e.g. CaseWhen) store sub-expressions in
|
|
2510
|
+
# _child_expressions rather than children; fall back to that.
|
|
2511
|
+
sub_exps = exp.children
|
|
2512
|
+
if not sub_exps:
|
|
2513
|
+
sub_exps = getattr(exp, "_child_expressions", None)
|
|
2514
|
+
if _check_expressions_for_types(
|
|
2515
|
+
sub_exps, check_data_gen, check_window, check_aggregation
|
|
2516
|
+
):
|
|
2517
|
+
return True
|
|
2518
|
+
|
|
2519
|
+
return False
|
|
2520
|
+
|
|
2521
|
+
|
|
2522
|
+
def has_data_generator_exp(expressions: Optional[List["Expression"]]) -> bool:
|
|
2523
|
+
"""Check if expressions contain data generator functions.
|
|
2524
|
+
|
|
2525
|
+
Note:
|
|
2526
|
+
In non-connect mode, window expressions are also treated as data generators
|
|
2527
|
+
for backward compatibility.
|
|
2528
|
+
"""
|
|
2529
|
+
if not (
|
|
2530
|
+
context._is_snowpark_connect_compatible_mode
|
|
2531
|
+
and context._snowpark_connect_flatten_select_after_sort
|
|
2532
|
+
):
|
|
2533
|
+
return _check_expressions_for_types(
|
|
2534
|
+
expressions, check_data_gen=True, check_window=True
|
|
2535
|
+
)
|
|
2536
|
+
return _check_expressions_for_types(expressions, check_data_gen=True)
|
|
2537
|
+
|
|
2538
|
+
|
|
2539
|
+
def has_data_generator_or_window_function_exp(
|
|
2540
|
+
expressions: Optional[List["Expression"]],
|
|
2541
|
+
) -> bool:
|
|
2542
|
+
"""Check if expressions contain data generators or window functions."""
|
|
2543
|
+
return _check_expressions_for_types(
|
|
2544
|
+
expressions, check_data_gen=True, check_window=True
|
|
2545
|
+
)
|
|
2546
|
+
|
|
2547
|
+
|
|
2548
|
+
def has_aggregation_function_exp(expressions: Optional[List["Expression"]]) -> bool:
|
|
2549
|
+
"""Check if expressions contain aggregation functions."""
|
|
2550
|
+
return _check_expressions_for_types(expressions, check_aggregation=True)
|
|
2551
|
+
|
|
2552
|
+
|
|
2553
|
+
def has_nondeterministic_data_generation_exp(
|
|
2554
|
+
expressions: Optional[List["Expression"]],
|
|
2555
|
+
) -> bool:
|
|
2556
|
+
"""Check if expressions contain non-deterministic data generation that would
|
|
2557
|
+
produce different results when materialized once via a CTE vs evaluated
|
|
2558
|
+
multiple times.
|
|
2559
|
+
|
|
2560
|
+
This is a different check than ``has_data_generator_exp`` (which is used
|
|
2561
|
+
for SQL-flattening decisions). Here we only care about functions whose
|
|
2562
|
+
output *changes across evaluations* — i.e. true randomness or
|
|
2563
|
+
sequence-dependent generators invoked **without arguments** (zero-arg
|
|
2564
|
+
``random()``, ``uuid_string()``, ``randstr()``).
|
|
2565
|
+
|
|
2566
|
+
Generators like ``seq1(sign)``, ``uniform(lo, hi, gen)`` with explicit
|
|
2567
|
+
seed, or ``uuid_string(uuid, name)`` are *not* flagged by this function
|
|
2568
|
+
because CTE deduplication is safe for them. Note that ``seq*`` functions
|
|
2569
|
+
are not fully deterministic — values may have gaps and ordering is not
|
|
2570
|
+
guaranteed (see https://docs.snowflake.com/en/user-guide/querying-sequences),
|
|
2571
|
+
however values within a single query are always distinct. This does not
|
|
2572
|
+
affect CTE safety: the concern here is whether *re-evaluating* a subtree
|
|
2573
|
+
would produce *entirely different* values (as ``random()`` or
|
|
2574
|
+
``uuid_string()`` would), not whether sequences are gap-free or ordered.
|
|
2575
|
+
|
|
2576
|
+
Heuristic: a ``FunctionExpression`` is flagged when:
|
|
2577
|
+
- it has ``is_data_generator=True`` **and** zero arguments, OR
|
|
2578
|
+
- its name is in ``NONDETERMINISTIC_DATA_GENERATION`` **and** zero
|
|
2579
|
+
arguments, OR
|
|
2580
|
+
- any of its *children* satisfy the above recursively (catches patterns
|
|
2581
|
+
like ``uniform(1, 100, random())``).
|
|
2582
|
+
|
|
2583
|
+
The zero-arg gate safely distinguishes non-deterministic calls (e.g.
|
|
2584
|
+
``random()``) from deterministic ones (e.g. ``random(seed)``), because the
|
|
2585
|
+
latter have ``len(children) > 0``.
|
|
2586
|
+
|
|
2587
|
+
Known limitations:
|
|
2588
|
+
- ``session.sql(...)`` has no expression tree, so it cannot be
|
|
2589
|
+
auto-detected.
|
|
2590
|
+
"""
|
|
2591
|
+
if expressions is None:
|
|
2592
|
+
return False
|
|
2593
|
+
for exp in expressions:
|
|
2594
|
+
if (
|
|
2595
|
+
isinstance(exp, FunctionExpression)
|
|
2596
|
+
and len(exp.children) == 0
|
|
2597
|
+
and exp.name.lower() in NONDETERMINISTIC_DATA_GENERATION
|
|
2307
2598
|
):
|
|
2308
|
-
# https://docs.snowflake.com/en/sql-reference/functions-data-generation
|
|
2309
2599
|
return True
|
|
2310
|
-
if exp is not None and
|
|
2600
|
+
if exp is not None and has_nondeterministic_data_generation_exp(exp.children):
|
|
2311
2601
|
return True
|
|
2312
2602
|
return False
|
|
@@ -526,6 +526,14 @@ class SnowflakePlan(LogicalPlan):
|
|
|
526
526
|
compiler = PlanCompiler(self)
|
|
527
527
|
return compiler.compile()
|
|
528
528
|
|
|
529
|
+
def get_execution_queries_without_cte(self) -> Dict["PlanQueryType", List["Query"]]:
|
|
530
|
+
"""Compile execution queries with CTE optimization skipped.
|
|
531
|
+
Used for retry when CTE-optimized SQL fails at the server."""
|
|
532
|
+
from snowflake.snowpark._internal.compiler.plan_compiler import PlanCompiler
|
|
533
|
+
|
|
534
|
+
compiler = PlanCompiler(self)
|
|
535
|
+
return compiler.compile(skip_cte_optimization=True)
|
|
536
|
+
|
|
529
537
|
@property
|
|
530
538
|
def children_plan_nodes(self) -> List[Union["Selectable", "SnowflakePlan"]]:
|
|
531
539
|
"""
|
|
@@ -105,6 +105,45 @@ def find_duplicate_subtrees(
|
|
|
105
105
|
|
|
106
106
|
return False
|
|
107
107
|
|
|
108
|
+
def is_node_with_data_generation_exp(node: "TreeNode") -> bool:
|
|
109
|
+
"""Check if a tree node contains non-deterministic data-generation
|
|
110
|
+
expressions (e.g. zero-arg ``uuid_string()``, ``random()``).
|
|
111
|
+
|
|
112
|
+
CTE deduplication must be skipped for such nodes because Snowflake
|
|
113
|
+
materializes CTEs; re-using a single CTE would repeat the same
|
|
114
|
+
generated values instead of producing fresh ones per branch.
|
|
115
|
+
|
|
116
|
+
When sql_simplifier is enabled the plan tree contains
|
|
117
|
+
SelectStatement nodes whose expression trees we can inspect
|
|
118
|
+
directly. When it is disabled the plan tree uses generic
|
|
119
|
+
LogicalPlan nodes (Union, Project, …) that lack expression
|
|
120
|
+
metadata, so we fall back to a regex check on the resolved SQL.
|
|
121
|
+
"""
|
|
122
|
+
if isinstance(node, SelectStatement) and node.contains_data_generation:
|
|
123
|
+
return True
|
|
124
|
+
|
|
125
|
+
if isinstance(node, SnowflakePlan) and isinstance(
|
|
126
|
+
node.source_plan, (SnowflakePlan, Selectable)
|
|
127
|
+
):
|
|
128
|
+
return is_node_with_data_generation_exp(node.source_plan)
|
|
129
|
+
elif (
|
|
130
|
+
isinstance(node, SnowflakePlan)
|
|
131
|
+
and node.source_plan is not None
|
|
132
|
+
and not node.session.sql_simplifier_enabled
|
|
133
|
+
):
|
|
134
|
+
# sql_simplifier disabled path — source_plan is a generic
|
|
135
|
+
# LogicalPlan (e.g. Union, Project) without expression trees
|
|
136
|
+
from snowflake.snowpark._internal.analyzer.select_statement import (
|
|
137
|
+
NONDETERMINISTIC_ZERO_ARG_RE,
|
|
138
|
+
) # prevent circular import
|
|
139
|
+
|
|
140
|
+
return bool(NONDETERMINISTIC_ZERO_ARG_RE.search(node.queries[-1].sql))
|
|
141
|
+
|
|
142
|
+
if isinstance(node, SelectSnowflakePlan):
|
|
143
|
+
return is_node_with_data_generation_exp(node.snowflake_plan)
|
|
144
|
+
|
|
145
|
+
return False
|
|
146
|
+
|
|
108
147
|
def traverse(root: "TreeNode") -> None:
|
|
109
148
|
"""
|
|
110
149
|
This function uses an iterative approach to avoid hitting Python's maximum recursion depth limit.
|
|
@@ -117,7 +156,9 @@ def find_duplicate_subtrees(
|
|
|
117
156
|
for node in current_level:
|
|
118
157
|
id_node_map[node.encoded_node_id_with_query].append(node)
|
|
119
158
|
|
|
120
|
-
if is_select_from_file_node(node)
|
|
159
|
+
if is_select_from_file_node(node) or is_node_with_data_generation_exp(
|
|
160
|
+
node
|
|
161
|
+
):
|
|
121
162
|
invalid_ids_for_deduplication.add(node.encoded_node_id_with_query)
|
|
122
163
|
|
|
123
164
|
for child in node.children_plan_nodes:
|