snowflake-snowpark-python 1.51.1__tar.gz → 1.53.0__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.51.1 → snowflake_snowpark_python-1.53.0}/CHANGELOG.md +47 -0
- {snowflake_snowpark_python-1.51.1/src/snowflake_snowpark_python.egg-info → snowflake_snowpark_python-1.53.0}/PKG-INFO +9 -6
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/README.md +2 -2
- snowflake_snowpark_python-1.53.0/pyproject.toml +13 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/setup.py +9 -4
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/analyzer_utils.py +159 -37
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/select_statement.py +32 -13
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/snowflake_plan.py +16 -10
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/snowflake_plan_node.py +4 -10
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/table_function.py +1 -9
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/code_generation.py +1 -7
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/compiler/cte_utils.py +6 -1
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/compiler/repeated_subquery_elimination.py +38 -10
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/base_dialect.py +8 -4
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/databricks_dialect.py +8 -8
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/mysql_dialect.py +8 -8
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/oracledb_dialect.py +8 -8
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/postgresql_dialect.py +16 -11
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/sqlserver_dialect.py +4 -4
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/debug_utils.py +1 -1
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/type_utils.py +121 -10
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/udf_utils.py +2 -8
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/utils.py +227 -9
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/xml_schema_inference.py +1 -1
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/column.py +1 -8
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/dataframe.py +17 -10
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/dataframe_ai_functions.py +4 -4
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/dataframe_na_functions.py +1 -9
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/dataframe_reader.py +192 -13
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/dataframe_stat_functions.py +1 -9
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/dataframe_writer.py +1 -9
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/files.py +1 -8
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/functions.py +134 -30
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/lineage.py +9 -2
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/__init__.py +2 -2
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/ordered_dataframe.py +1 -8
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/indexing_overrides.py +1 -1
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/pd_extensions.py +1 -1
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/utils.py +2 -2
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/row.py +1 -9
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/secrets.py +39 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/session.py +24 -8
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/stored_procedure.py +1 -7
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/table.py +46 -8
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/types.py +3 -9
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/udaf.py +1 -7
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/udf.py +1 -7
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/udtf.py +1 -7
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/version.py +1 -1
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/window.py +1 -7
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0/src/snowflake_snowpark_python.egg-info}/PKG-INFO +9 -6
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake_snowpark_python.egg-info/requires.txt +9 -1
- snowflake_snowpark_python-1.51.1/pyproject.toml +0 -7
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/LICENSE.txt +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/MANIFEST.in +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/setup.cfg +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/__init__.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_functions/__init__.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_functions/general_functions.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_functions/scalar_functions.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/__init__.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/__init__.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/analyzer.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/binary_expression.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/binary_plan_node.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/datatype_mapper.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/expression.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/grouping_set.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/metadata_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/query_plan_analysis_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/schema_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/sort_expression.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/table_merge_expression.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/unary_expression.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/unary_plan_node.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/window_expression.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/ast/__init__.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/ast/batch.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/ast/builder.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/ast/utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/compiler/__init__.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/compiler/large_query_breakdown.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/compiler/plan_compiler.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/compiler/query_generator.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/compiler/telemetry_constants.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/compiler/utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/__init__.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/datasource_partitioner.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/datasource_reader.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/datasource_typing.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/__init__.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/sqlite3_dialect.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/drivers/__init__.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/drivers/base_driver.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/drivers/databricks_driver.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/drivers/oracledb_driver.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/drivers/psycopg2_driver.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/drivers/pymsql_driver.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/drivers/pyodbc_driver.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/drivers/sqlite_driver.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/jdbc.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/error_message.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/event_table_telemetry.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/open_telemetry.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/packaging_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/proto/generated/__init__.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/proto/generated/ast_pb2.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/proto/generated/ast_pb2.pyi +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/select_projection_complexity_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/server_connection.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/snowpark_profiler.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/telemetry.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/temp_table_auto_cleaner.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/xml_reader.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/xpath_handlers.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/async_job.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/catalog.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/context.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/dataframe_analytics_functions.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/dataframe_profiler.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/exceptions.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/file_operation.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/__init__.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_analyzer.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_connection.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_constants.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_functions.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_nop_analyzer.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_nop_connection.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_nop_plan.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_options.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_pandas_util.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_plan.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_plan_builder.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_select_statement.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_snowflake_data_type.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_snowflake_to_pandas_converter.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_stage_registry.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_stored_procedure.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_telemetry.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_udaf.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_udf.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_udf_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_udtf.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_util.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_window_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/exceptions.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/__init__.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/config/__init__.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/config/__main__.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/config/envvars.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/config/pubsub.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/conftest.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/__init__.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/aggregation_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/align_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/apply_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/binary_op_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/concat_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/cumulative_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/cut_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/frame.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/generator_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/get_dummies_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/groupby_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/indexing_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/io_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/isin_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/join_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/pivot_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/resample_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/row_count_estimation.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/session.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/snowpark_pandas_types.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/statement_params_constants.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/telemetry.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/timestamp_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/transpose_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/type_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/unpivot_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/where_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/window_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_typing.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/compiler/__init__.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/compiler/doc_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/compiler/ray_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/compiler/snowflake_query_compiler.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/docstrings/__init__.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/docstrings/base.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/docstrings/dataframe.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/docstrings/datetime_index.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/docstrings/general.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/docstrings/groupby.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/docstrings/index.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/docstrings/io.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/docstrings/resample.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/docstrings/series.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/docstrings/series_utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/docstrings/shared_docs.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/docstrings/timedelta_index.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/docstrings/window.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/__init__.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/base_overrides.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/dataframe_extensions.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/dataframe_groupby_overrides.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/dataframe_overrides.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/datetime_index.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/general_overrides.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/index.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/io_overrides.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/resample_overrides.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/resampler_groupby_overrides.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/rolling_groupby_overrides.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/series_extensions.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/series_groupby_overrides.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/series_overrides.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/snow_partition_iterator.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/timedelta_index.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/window_overrides.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/io/__init__.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/io/factories.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/io/snow_io.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/utils/__init__.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/utils/error_message.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/utils/exceptions.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/utils/frontend_constants.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/utils/numpy_to_pandas.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/utils/warning_message.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/utils.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/py.typed +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/query_history.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/relational_grouped_dataframe.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/stored_procedure_profiler.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/table_function.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/testing.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/udf_profiler.py +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake_snowpark_python.egg-info/SOURCES.txt +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake_snowpark_python.egg-info/dependency_links.txt +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake_snowpark_python.egg-info/namespace_packages.txt +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake_snowpark_python.egg-info/not-zip-safe +0 -0
- {snowflake_snowpark_python-1.51.1 → snowflake_snowpark_python-1.53.0}/src/snowflake_snowpark_python.egg-info/top_level.txt +0 -0
|
@@ -1,5 +1,52 @@
|
|
|
1
1
|
# Release History
|
|
2
2
|
|
|
3
|
+
## 1.53.0 (2026-07-09)
|
|
4
|
+
|
|
5
|
+
### Snowpark Python API Updates
|
|
6
|
+
|
|
7
|
+
#### New Features
|
|
8
|
+
|
|
9
|
+
- Added the `udf_init_once` decorator in `snowflake.snowpark.functions` for marking functions to be executed once during pre-fork initialization on Snowflake workers, matching the server-side `_snowflake.udf_init_once` API.
|
|
10
|
+
|
|
11
|
+
#### Bug Fixes
|
|
12
|
+
|
|
13
|
+
- Fixed a bug where stage paths and file format names that contain single quotes were not consistently escaped when generating SQL, which could produce malformed statements. This affects `INFER_SCHEMA` (used by `DataFrameReader.csv`/`json`/`parquet`/`orc`/`avro`) and `COPY FILES` (used by `FileOperation.copy_files`).
|
|
14
|
+
- Fixed a bug where single quotes and backslashes in stage/file paths were not correctly escaped when generating `COPY INTO` / `PUT` / `GET` SQL, which could produce malformed statements. This affects `DataFrame.write.csv`/`copy_into_location` and the Snowpark-pandas `DataFrame.to_csv` stage path.
|
|
15
|
+
- Fixed a bug where column names containing quote characters returned by an external database were not correctly escaped when generating the `SELECT` query for `DataFrameReader.dbapi`, which could produce malformed SQL. Embedded quote characters in identifiers are now doubled (backticks for Databricks/MySQL, double quotes for Oracle/PostgreSQL/SQL Server).
|
|
16
|
+
- Fixed a bug where the destination passed to `DataFrameWriter.copy_into_location` (and `csv`/`json`/`parquet`/`save`) was embedded into the generated `COPY INTO` statement without quoting, which could produce malformed SQL for locations containing single quotes. The location is now consistently quoted and escaped, and a string that merely starts and ends with a single quote but contains unescaped interior quotes is no longer treated as an already-quoted literal; it is fully escaped so it stays a single SQL string literal.
|
|
17
|
+
- Fixed a bug where UDF default argument values reconstructed from a source file in `register_from_file` were evaluated with `eval()`; they are now evaluated only against the documented set of supported default-value types, and unsupported expressions are ignored.
|
|
18
|
+
- Fixed a bug where `object_name`, `object_domain`, or `object_version` values containing single quotes or backslashes in `session.lineage.trace()` caused incorrect SQL generation. These values are now properly escaped before being embedded in the `SYSTEM$DGQL` call.
|
|
19
|
+
- Fixed a bug where single quotes and backslashes in `comment` (`create_or_replace_view` / dynamic table / `save_as_table`), collation specs (`Column.collate`), VARIANT/OBJECT subfield keys (`Column[...]`), and `DataFrame`/`Session.flatten` paths were not correctly escaped when generating SQL, which could produce malformed statements. Backslash sequences (e.g. `\t`, `\n`) in these values are now applied literally rather than interpreted.
|
|
20
|
+
- Fixed a bug where string values in the AI functions (`ai_extract`, `ai_classify`, `ai_similarity`, `ai_parse_document`, `ai_transcribe`, `ai_complete`) configuration and `response_format` were not correctly escaped when generating the SQL object literal, which could produce malformed statements when a value contained single quotes or backslashes (for example, an apostrophe in a natural-language question).
|
|
21
|
+
|
|
22
|
+
#### Dependency Updates
|
|
23
|
+
|
|
24
|
+
- Lifted `protobuf` restriction for Python 3.14 from `==5.29.3` to `>=5.29.3,<6.34`.
|
|
25
|
+
- Capped `pandas` to `<3.0.0` for the `[pandas]` install extra, as Snowpark Python pandas-related features may not be fully compatible with pandas 3.0 or later.
|
|
26
|
+
|
|
27
|
+
## 1.52.0 (2026-06-10)
|
|
28
|
+
|
|
29
|
+
### Snowpark Python API Updates
|
|
30
|
+
|
|
31
|
+
#### New Features
|
|
32
|
+
|
|
33
|
+
- Added `get_wif_token` to `snowflake.snowpark.secrets` for workload identity federation tokens on the Snowflake server (not available in SPCS file-based secret environments).
|
|
34
|
+
|
|
35
|
+
#### Bug Fixes
|
|
36
|
+
|
|
37
|
+
- Fixed a bug where copying a `DataFrame` via `copy.copy()` lost post-aggregate state, causing subsequent `.limit()` or `.sort()` to generate incorrect SQL.
|
|
38
|
+
- Fixed a bug where calling `DataFrame.alias()` twice on the same DataFrame (e.g. for a self-join) caused both aliases to share the same internal column-mapping dictionary. This made `col("R", "col")` resolve to the same column as `col("L", "col")`, producing incorrect join conditions and filter expressions.
|
|
39
|
+
- Fixed a bug where `cloudpickle` could not be resolved when registering a Python stored procedure or UDF with `runtime_version='3.13'`.
|
|
40
|
+
|
|
41
|
+
#### Improvements
|
|
42
|
+
|
|
43
|
+
- Improved CTE optimization to deduplicate identical subtrees in self-joins, which were previously emitted as repeated subqueries.
|
|
44
|
+
- Reduced the size of generated query text for repeated join operations.
|
|
45
|
+
|
|
46
|
+
#### Deprecations
|
|
47
|
+
|
|
48
|
+
- Removed support for Python 3.9.
|
|
49
|
+
|
|
3
50
|
## 1.51.1 (2026-05-28)
|
|
4
51
|
|
|
5
52
|
#### Documentation
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: snowflake-snowpark-python
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.53.0
|
|
4
4
|
Summary: Snowflake Snowpark for Python
|
|
5
5
|
Home-page: https://www.snowflake.com/
|
|
6
6
|
Author: Snowflake, Inc
|
|
@@ -22,7 +22,6 @@ Classifier: License :: OSI Approved :: Apache Software License
|
|
|
22
22
|
Classifier: Operating System :: OS Independent
|
|
23
23
|
Classifier: Programming Language :: SQL
|
|
24
24
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
25
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
26
25
|
Classifier: Programming Language :: Python :: 3.10
|
|
27
26
|
Classifier: Programming Language :: Python :: 3.11
|
|
28
27
|
Classifier: Programming Language :: Python :: 3.12
|
|
@@ -33,7 +32,7 @@ Classifier: Topic :: Software Development :: Libraries
|
|
|
33
32
|
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
34
33
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
35
34
|
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
36
|
-
Requires-Python: >=3.
|
|
35
|
+
Requires-Python: >=3.10, <3.15
|
|
37
36
|
Description-Content-Type: text/markdown
|
|
38
37
|
License-File: LICENSE.txt
|
|
39
38
|
Requires-Dist: setuptools>=40.6.0
|
|
@@ -42,13 +41,16 @@ Requires-Dist: snowflake-connector-python<5.0.0,>=3.17.0
|
|
|
42
41
|
Requires-Dist: typing-extensions<5.0.0,>=4.1.0
|
|
43
42
|
Requires-Dist: pyyaml
|
|
44
43
|
Requires-Dist: cloudpickle!=2.1.0,!=2.2.0,<=3.1.1,>=1.6.0
|
|
45
|
-
Requires-Dist: protobuf<6.34,>=3.20
|
|
44
|
+
Requires-Dist: protobuf<6.34,>=3.20; python_version < "3.14"
|
|
45
|
+
Requires-Dist: protobuf<6.34,>=5.29.0; python_version >= "3.14"
|
|
46
46
|
Requires-Dist: python-dateutil
|
|
47
47
|
Requires-Dist: tzlocal
|
|
48
48
|
Provides-Extra: pandas
|
|
49
49
|
Requires-Dist: snowflake-connector-python[pandas]<5.0.0,>=3.17.0; extra == "pandas"
|
|
50
|
+
Requires-Dist: pandas<3.0.0; extra == "pandas"
|
|
50
51
|
Provides-Extra: modin
|
|
51
52
|
Requires-Dist: snowflake-connector-python[pandas]<5.0.0,>=3.17.0; extra == "modin"
|
|
53
|
+
Requires-Dist: pandas<3.0.0; extra == "modin"
|
|
52
54
|
Requires-Dist: modin<0.38.0,>=0.36.0; extra == "modin"
|
|
53
55
|
Requires-Dist: pandas<=2.4; extra == "modin"
|
|
54
56
|
Requires-Dist: tqdm; extra == "modin"
|
|
@@ -77,6 +79,7 @@ Requires-Dist: lxml; extra == "development"
|
|
|
77
79
|
Requires-Dist: pyarrow; extra == "development"
|
|
78
80
|
Provides-Extra: modin-development
|
|
79
81
|
Requires-Dist: snowflake-connector-python[pandas]<5.0.0,>=3.17.0; extra == "modin-development"
|
|
82
|
+
Requires-Dist: pandas<3.0.0; extra == "modin-development"
|
|
80
83
|
Requires-Dist: modin<0.38.0,>=0.36.0; extra == "modin-development"
|
|
81
84
|
Requires-Dist: pandas<=2.4; extra == "modin-development"
|
|
82
85
|
Requires-Dist: tqdm; extra == "modin-development"
|
|
@@ -149,9 +152,9 @@ If you don't have a Snowflake account yet, you can [sign up for a 30-day free tr
|
|
|
149
152
|
|
|
150
153
|
### Create a Python virtual environment
|
|
151
154
|
You can use [miniconda][miniconda], [anaconda][anaconda], or [virtualenv][virtualenv]
|
|
152
|
-
to create a Python 3.
|
|
155
|
+
to create a Python 3.10, 3.11, 3.12 or 3.13 virtual environment.
|
|
153
156
|
|
|
154
|
-
For Snowpark pandas, only Python 3.
|
|
157
|
+
For Snowpark pandas, only Python 3.10 or 3.11 is supported.
|
|
155
158
|
|
|
156
159
|
To have the best experience when using it with UDFs, [creating a local conda environment with the Snowflake channel][use snowflake channel] is recommended.
|
|
157
160
|
|
|
@@ -18,9 +18,9 @@ If you don't have a Snowflake account yet, you can [sign up for a 30-day free tr
|
|
|
18
18
|
|
|
19
19
|
### Create a Python virtual environment
|
|
20
20
|
You can use [miniconda][miniconda], [anaconda][anaconda], or [virtualenv][virtualenv]
|
|
21
|
-
to create a Python 3.
|
|
21
|
+
to create a Python 3.10, 3.11, 3.12 or 3.13 virtual environment.
|
|
22
22
|
|
|
23
|
-
For Snowpark pandas, only Python 3.
|
|
23
|
+
For Snowpark pandas, only Python 3.10 or 3.11 is supported.
|
|
24
24
|
|
|
25
25
|
To have the best experience when using it with UDFs, [creating a local conda environment with the Snowflake channel][use snowflake channel] is recommended.
|
|
26
26
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = [
|
|
3
|
+
"setuptools",
|
|
4
|
+
# py>=3.14: protoc-wheel-0 has no cp314 wheel on PyPI, so it cannot be installed
|
|
5
|
+
# in pip's build isolation venv. setup.py falls back to shutil.which("protoc").
|
|
6
|
+
"protoc-wheel-0==21.1; python_version < '3.14'", # Protocol buffer compiler for Snowpark IR
|
|
7
|
+
# py>=3.14: pin <=3.6.0 so the build isolation venv does not install mypy-protobuf 5.x,
|
|
8
|
+
# whose extensions_pb2.py was generated with protobuf 6.x gencode and fails at import
|
|
9
|
+
# time when the isolated venv resolves protobuf 5.x (Snowflake internal channel).
|
|
10
|
+
"mypy-protobuf<=3.6.0; python_version >= '3.14'",
|
|
11
|
+
"mypy-protobuf; python_version < '3.14'", # used in generating typed Python code from protobuf for Snowpark IR
|
|
12
|
+
]
|
|
13
|
+
build-backend = "setuptools.build_meta"
|
|
@@ -28,17 +28,23 @@ INSTALL_REQ_LIST = [
|
|
|
28
28
|
"pyyaml",
|
|
29
29
|
"cloudpickle>=1.6.0,<=3.1.1,!=2.1.0,!=2.2.0",
|
|
30
30
|
# `protoc` < 3.20 is not able to generate protobuf code compatible with protobuf >= 3.20.
|
|
31
|
-
"protobuf>=3.20, <6.34", # Snowpark IR
|
|
31
|
+
"protobuf>=3.20, <6.34; python_version < '3.14'", # Snowpark IR
|
|
32
|
+
# py314: protoc-wheel-0 has no cp314 wheel; setup.py uses libprotobuf's protoc from PATH.
|
|
33
|
+
# The pre-generated ast_pb2.py in the tarball has no ValidateProtobufRuntimeVersion call
|
|
34
|
+
# (built with protoc 3.21), so 5.29.0+ is sufficient. Conda recipes may regenerate with
|
|
35
|
+
# a different protoc version and override this constraint via their run deps.
|
|
36
|
+
"protobuf>=5.29.0,<6.34; python_version >= '3.14'", # Snowpark IR
|
|
32
37
|
"python-dateutil", # Snowpark IR
|
|
33
38
|
"tzlocal", # Snowpark IR
|
|
34
39
|
]
|
|
35
|
-
REQUIRED_PYTHON_VERSION = ">=3.
|
|
40
|
+
REQUIRED_PYTHON_VERSION = ">=3.10, <3.15"
|
|
36
41
|
|
|
37
42
|
if os.getenv("SNOWFLAKE_IS_PYTHON_RUNTIME_TEST", False):
|
|
38
|
-
REQUIRED_PYTHON_VERSION = ">=3.
|
|
43
|
+
REQUIRED_PYTHON_VERSION = ">=3.10"
|
|
39
44
|
|
|
40
45
|
PANDAS_REQUIREMENTS = [
|
|
41
46
|
f"snowflake-connector-python[pandas]{CONNECTOR_DEPENDENCY_VERSION}",
|
|
47
|
+
"pandas<3.0.0",
|
|
42
48
|
]
|
|
43
49
|
MODIN_REQUIREMENTS = [
|
|
44
50
|
*PANDAS_REQUIREMENTS,
|
|
@@ -246,7 +252,6 @@ setup(
|
|
|
246
252
|
"Operating System :: OS Independent",
|
|
247
253
|
"Programming Language :: SQL",
|
|
248
254
|
"Programming Language :: Python :: 3 :: Only",
|
|
249
|
-
"Programming Language :: Python :: 3.9",
|
|
250
255
|
"Programming Language :: Python :: 3.10",
|
|
251
256
|
"Programming Language :: Python :: 3.11",
|
|
252
257
|
"Programming Language :: Python :: 3.12",
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import json
|
|
7
7
|
import math
|
|
8
8
|
import os
|
|
9
|
-
import
|
|
9
|
+
import re
|
|
10
10
|
import tempfile
|
|
11
11
|
from typing import Any, Dict, List, Optional, Tuple, Union, Literal, Sequence
|
|
12
12
|
|
|
@@ -41,7 +41,8 @@ from snowflake.snowpark._internal.utils import (
|
|
|
41
41
|
EMPTY_STRING,
|
|
42
42
|
TempObjectType,
|
|
43
43
|
escape_quotes,
|
|
44
|
-
|
|
44
|
+
escape_quotes_and_backslashes,
|
|
45
|
+
escape_subfield_key,
|
|
45
46
|
get_temp_type_for_object,
|
|
46
47
|
is_single_quoted,
|
|
47
48
|
is_sql_select_statement,
|
|
@@ -52,13 +53,7 @@ from snowflake.snowpark._internal.utils import (
|
|
|
52
53
|
from snowflake.snowpark.row import Row
|
|
53
54
|
from snowflake.snowpark.types import DataType
|
|
54
55
|
|
|
55
|
-
|
|
56
|
-
# Python 3.9 can use both
|
|
57
|
-
# Python 3.10 needs to use collections.abc.Iterable because typing.Iterable is removed
|
|
58
|
-
if sys.version_info <= (3, 9):
|
|
59
|
-
from typing import Iterable
|
|
60
|
-
else:
|
|
61
|
-
from collections.abc import Iterable
|
|
56
|
+
from collections.abc import Iterable
|
|
62
57
|
|
|
63
58
|
LEFT_PARENTHESIS = "("
|
|
64
59
|
RIGHT_PARENTHESIS = ")"
|
|
@@ -409,7 +404,26 @@ def regexp_expression(expr: str, pattern: str, parameters: Optional[str] = None)
|
|
|
409
404
|
|
|
410
405
|
|
|
411
406
|
def collate_expression(expr: str, collation_spec: str) -> str:
|
|
412
|
-
|
|
407
|
+
# Escape the collation spec so a value containing single quotes or
|
|
408
|
+
# backslashes does not terminate the single-quoted literal early and produce
|
|
409
|
+
# invalid SQL.
|
|
410
|
+
#
|
|
411
|
+
# Preserve the historical behavior of single_quote(): a spec that is already
|
|
412
|
+
# wrapped in single quotes (e.g. "'en_US'") is treated as pre-quoted, so we
|
|
413
|
+
# strip the outer quotes, escape the interior, and re-wrap. An unquoted spec
|
|
414
|
+
# is escaped and wrapped. Specs (quoted or unquoted) with no interior quotes
|
|
415
|
+
# or backslashes therefore produce identical SQL to before.
|
|
416
|
+
if is_single_quoted(collation_spec):
|
|
417
|
+
inner = collation_spec[1:-1]
|
|
418
|
+
else:
|
|
419
|
+
inner = collation_spec
|
|
420
|
+
return (
|
|
421
|
+
expr
|
|
422
|
+
+ COLLATE
|
|
423
|
+
+ SINGLE_QUOTE
|
|
424
|
+
+ escape_quotes_and_backslashes(inner)
|
|
425
|
+
+ SINGLE_QUOTE
|
|
426
|
+
)
|
|
413
427
|
|
|
414
428
|
|
|
415
429
|
def subfield_expression(expr: str, field: Union[str, int]) -> str:
|
|
@@ -417,7 +431,12 @@ def subfield_expression(expr: str, field: Union[str, int]) -> str:
|
|
|
417
431
|
expr
|
|
418
432
|
+ LEFT_BRACKET
|
|
419
433
|
+ (
|
|
420
|
-
|
|
434
|
+
# Escape the field so a VARIANT/OBJECT key containing single quotes
|
|
435
|
+
# or backslashes does not terminate the literal early. A key whose
|
|
436
|
+
# single quotes are already doubled is preserved unchanged (minus
|
|
437
|
+
# backslash normalization) to keep the historical "double your own
|
|
438
|
+
# quotes" contract non-breaking.
|
|
439
|
+
SINGLE_QUOTE + escape_subfield_key(field) + SINGLE_QUOTE
|
|
421
440
|
if isinstance(field, str)
|
|
422
441
|
else str(field)
|
|
423
442
|
)
|
|
@@ -438,7 +457,10 @@ def flatten_expression(
|
|
|
438
457
|
+ PATH
|
|
439
458
|
+ RIGHT_ARROW
|
|
440
459
|
+ SINGLE_QUOTE
|
|
441
|
-
|
|
460
|
+
# Escape the JSON path so a value containing single quotes or
|
|
461
|
+
# backslashes does not terminate the literal early and produce invalid
|
|
462
|
+
# SQL in the FLATTEN argument list.
|
|
463
|
+
+ (escape_quotes_and_backslashes(path) if path else EMPTY_STRING)
|
|
442
464
|
+ SINGLE_QUOTE
|
|
443
465
|
+ COMMA
|
|
444
466
|
+ OUTER
|
|
@@ -968,6 +990,33 @@ def lateral_join_statement(
|
|
|
968
990
|
)
|
|
969
991
|
|
|
970
992
|
|
|
993
|
+
_SELECT_STAR_FROM_PREFIX = SELECT + STAR + NEW_LINE + FROM + LEFT_PARENTHESIS + NEW_LINE
|
|
994
|
+
_SELECT_STAR_FROM_SUFFIX = NEW_LINE + RIGHT_PARENTHESIS
|
|
995
|
+
|
|
996
|
+
|
|
997
|
+
def _unwrap_select_star_from(sql: str) -> Optional[str]:
|
|
998
|
+
"""If sql is a join-produced `SELECT * FROM (\n<join_source>\n)` (the
|
|
999
|
+
output of project_statement([], join_source)), return <join_source>.
|
|
1000
|
+
Only unwraps when the inner content starts with '(' (possibly preceded
|
|
1001
|
+
by UUID trace comments) which indicates a parenthesized join operand
|
|
1002
|
+
rather than a wrapped SELECT statement."""
|
|
1003
|
+
if sql.startswith(_SELECT_STAR_FROM_PREFIX) and sql.endswith(
|
|
1004
|
+
_SELECT_STAR_FROM_SUFFIX
|
|
1005
|
+
):
|
|
1006
|
+
inner = sql[len(_SELECT_STAR_FROM_PREFIX) : -len(_SELECT_STAR_FROM_SUFFIX)]
|
|
1007
|
+
# In trace-SQL mode, UUID comments (\n-- <uuid>\n) may precede the
|
|
1008
|
+
# opening parenthesis. Strip them before checking.
|
|
1009
|
+
check = inner.lstrip("\n")
|
|
1010
|
+
if check.startswith("--"):
|
|
1011
|
+
# Skip the comment line and any trailing newline
|
|
1012
|
+
newline_pos = check.find("\n")
|
|
1013
|
+
if newline_pos != -1:
|
|
1014
|
+
check = check[newline_pos + 1 :]
|
|
1015
|
+
if check.startswith(LEFT_PARENTHESIS) or inner.startswith(LEFT_PARENTHESIS):
|
|
1016
|
+
return inner
|
|
1017
|
+
return None
|
|
1018
|
+
|
|
1019
|
+
|
|
971
1020
|
def snowflake_supported_join_statement(
|
|
972
1021
|
left: str,
|
|
973
1022
|
right: str,
|
|
@@ -978,17 +1027,30 @@ def snowflake_supported_join_statement(
|
|
|
978
1027
|
left_uuid: Optional[str] = None,
|
|
979
1028
|
right_uuid: Optional[str] = None,
|
|
980
1029
|
directed: bool = False,
|
|
1030
|
+
left_is_join: bool = False,
|
|
981
1031
|
) -> str:
|
|
982
1032
|
LEFT_UUID = format_uuid(left_uuid)
|
|
983
1033
|
RIGHT_UUID = format_uuid(right_uuid)
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
1034
|
+
|
|
1035
|
+
# If left is the output of a previous join, flatten into a multi-way join
|
|
1036
|
+
# by unwrapping the SELECT * FROM (...) envelope and appending the new
|
|
1037
|
+
# right operand directly to the existing join source. This avoids nested
|
|
1038
|
+
# SELECT * layers that inflate query text without changing semantics.
|
|
1039
|
+
#
|
|
1040
|
+
# Though it is technically less efficient than constructing the join sub-queries
|
|
1041
|
+
# without the SELECT in the first place, the structure of our SQL processing code
|
|
1042
|
+
# needs top-level projections to be wrapped by a select to be well-formed, so we
|
|
1043
|
+
# must strip it here instead.
|
|
1044
|
+
#
|
|
1045
|
+
# We only unwrap the left side because it is simpler to deal with than unwrapping
|
|
1046
|
+
# both left and right, and left-deep chains are more common, as they're produced
|
|
1047
|
+
# by calls like df1.join(df2).join(df3) etc.
|
|
1048
|
+
unwrapped_left = _unwrap_select_star_from(left) if left_is_join else None
|
|
989
1049
|
right_alias = (
|
|
990
1050
|
"SNOWPARK_RIGHT"
|
|
991
|
-
if use_constant_subquery_alias
|
|
1051
|
+
if use_constant_subquery_alias and unwrapped_left is None
|
|
1052
|
+
# Multi-way join: right alias must be unique to avoid collisions
|
|
1053
|
+
# with aliases already present in the flattened join source.
|
|
992
1054
|
else random_name_for_temp_object(TempObjectType.TABLE)
|
|
993
1055
|
)
|
|
994
1056
|
|
|
@@ -1024,18 +1086,31 @@ def snowflake_supported_join_statement(
|
|
|
1024
1086
|
|
|
1025
1087
|
maybe_directed_sql = DIRECTED_JOIN if directed else JOIN
|
|
1026
1088
|
|
|
1089
|
+
if unwrapped_left is not None:
|
|
1090
|
+
# No need for additional parentheses around the left expression here, since it
|
|
1091
|
+
# should already be parenthesized
|
|
1092
|
+
left_expr = LEFT_UUID + unwrapped_left + NEW_LINE + LEFT_UUID
|
|
1093
|
+
else:
|
|
1094
|
+
left_alias = (
|
|
1095
|
+
"SNOWPARK_LEFT"
|
|
1096
|
+
if use_constant_subquery_alias
|
|
1097
|
+
else random_name_for_temp_object(TempObjectType.TABLE)
|
|
1098
|
+
)
|
|
1099
|
+
left_expr = (
|
|
1100
|
+
LEFT_PARENTHESIS
|
|
1101
|
+
+ NEW_LINE
|
|
1102
|
+
+ LEFT_UUID
|
|
1103
|
+
+ left
|
|
1104
|
+
+ NEW_LINE
|
|
1105
|
+
+ LEFT_UUID
|
|
1106
|
+
+ RIGHT_PARENTHESIS
|
|
1107
|
+
+ AS
|
|
1108
|
+
+ left_alias
|
|
1109
|
+
+ SPACE
|
|
1110
|
+
+ NEW_LINE
|
|
1111
|
+
)
|
|
1027
1112
|
source = (
|
|
1028
|
-
|
|
1029
|
-
+ NEW_LINE
|
|
1030
|
-
+ LEFT_UUID
|
|
1031
|
-
+ left
|
|
1032
|
-
+ NEW_LINE
|
|
1033
|
-
+ LEFT_UUID
|
|
1034
|
-
+ RIGHT_PARENTHESIS
|
|
1035
|
-
+ AS
|
|
1036
|
-
+ left_alias
|
|
1037
|
-
+ SPACE
|
|
1038
|
-
+ NEW_LINE
|
|
1113
|
+
left_expr
|
|
1039
1114
|
+ join_sql
|
|
1040
1115
|
+ maybe_directed_sql
|
|
1041
1116
|
+ NEW_LINE
|
|
@@ -1067,6 +1142,7 @@ def join_statement(
|
|
|
1067
1142
|
left_uuid: Optional[str] = None,
|
|
1068
1143
|
right_uuid: Optional[str] = None,
|
|
1069
1144
|
directed: bool = False,
|
|
1145
|
+
left_is_join: bool = False,
|
|
1070
1146
|
) -> str:
|
|
1071
1147
|
if isinstance(join_type, (LeftSemi, LeftAnti)):
|
|
1072
1148
|
return left_semi_or_anti_join_statement(
|
|
@@ -1094,12 +1170,18 @@ def join_statement(
|
|
|
1094
1170
|
left_uuid=left_uuid,
|
|
1095
1171
|
right_uuid=right_uuid,
|
|
1096
1172
|
directed=directed,
|
|
1173
|
+
left_is_join=left_is_join,
|
|
1097
1174
|
)
|
|
1098
1175
|
|
|
1099
1176
|
|
|
1100
1177
|
def get_comment_sql(comment: Optional[str]) -> str:
|
|
1101
1178
|
return (
|
|
1102
|
-
COMMENT + EQUALS + SINGLE_QUOTE
|
|
1179
|
+
COMMENT + EQUALS + SINGLE_QUOTE
|
|
1180
|
+
# Escape backslashes and single quotes so a comment containing those
|
|
1181
|
+
# characters does not terminate the single-quoted literal early and
|
|
1182
|
+
# produce invalid SQL. A comment with no backslash/quote is emitted
|
|
1183
|
+
# unchanged.
|
|
1184
|
+
+ escape_quotes_and_backslashes(comment) + SINGLE_QUOTE
|
|
1103
1185
|
if comment
|
|
1104
1186
|
else EMPTY_STRING
|
|
1105
1187
|
)
|
|
@@ -1323,13 +1405,11 @@ def infer_schema_statement(
|
|
|
1323
1405
|
+ LEFT_PARENTHESIS
|
|
1324
1406
|
+ LOCATION
|
|
1325
1407
|
+ RIGHT_ARROW
|
|
1326
|
-
+ (path
|
|
1408
|
+
+ single_quote(path)
|
|
1327
1409
|
+ COMMA
|
|
1328
1410
|
+ FILE_FORMAT
|
|
1329
1411
|
+ RIGHT_ARROW
|
|
1330
|
-
+
|
|
1331
|
-
+ file_format_name
|
|
1332
|
-
+ SINGLE_QUOTE
|
|
1412
|
+
+ single_quote(file_format_name)
|
|
1333
1413
|
+ (
|
|
1334
1414
|
", "
|
|
1335
1415
|
+ ", ".join(
|
|
@@ -1358,7 +1438,14 @@ def file_operation_statement(
|
|
|
1358
1438
|
return f"{REMOVE}{stage_location}{get_options_statement(options)}"
|
|
1359
1439
|
if command.lower() == "copy_files":
|
|
1360
1440
|
# For COPY FILES, file_name stores the value of the source stage location or subquery (from a DataFrame)
|
|
1361
|
-
|
|
1441
|
+
# Quote stage_location; file_name may be a subquery that must not be quoted
|
|
1442
|
+
quoted_target = single_quote(stage_location)
|
|
1443
|
+
# If file_name is a subquery (starts with '('), don't quote it
|
|
1444
|
+
if file_name.strip().startswith("("):
|
|
1445
|
+
source = file_name
|
|
1446
|
+
else:
|
|
1447
|
+
source = single_quote(file_name)
|
|
1448
|
+
return f"{COPY_FILES}{INTO}{quoted_target}{FROM}{source}{get_options_statement(options)}"
|
|
1362
1449
|
raise ValueError(f"Unsupported file operation type {command}")
|
|
1363
1450
|
|
|
1364
1451
|
|
|
@@ -1878,7 +1965,7 @@ def copy_into_location(
|
|
|
1878
1965
|
return (
|
|
1879
1966
|
COPY
|
|
1880
1967
|
+ INTO
|
|
1881
|
-
+ stage_location
|
|
1968
|
+
+ escape_location_literal(stage_location)
|
|
1882
1969
|
+ FROM
|
|
1883
1970
|
+ LEFT_PARENTHESIS
|
|
1884
1971
|
+ query
|
|
@@ -2086,12 +2173,47 @@ def table(content: str) -> str:
|
|
|
2086
2173
|
|
|
2087
2174
|
|
|
2088
2175
|
def single_quote(value: str) -> str:
|
|
2089
|
-
if
|
|
2176
|
+
if is_single_quoted(value):
|
|
2090
2177
|
return value
|
|
2091
2178
|
else:
|
|
2179
|
+
# Double any embedded single quotes so the value stays a single literal
|
|
2180
|
+
value = value.replace("'", "''")
|
|
2092
2181
|
return SINGLE_QUOTE + value + SINGLE_QUOTE
|
|
2093
2182
|
|
|
2094
2183
|
|
|
2184
|
+
# Matches a complete, well-formed single-quoted SQL literal. The three body
|
|
2185
|
+
# alternatives each start with a different character (non-quote/non-backslash,
|
|
2186
|
+
# ', \), so every input character fits exactly one branch -- the engine never
|
|
2187
|
+
# backtracks, giving linear-time matching even on adversarial input.
|
|
2188
|
+
# Matches: "'@stage/o''clock/'" (interior quote is doubled -> one literal)
|
|
2189
|
+
# No match: "'@x' UNION SELECT --'" (bare interior quote ends the literal early)
|
|
2190
|
+
_WELL_FORMED_SINGLE_QUOTED_LITERAL = re.compile(
|
|
2191
|
+
r"""
|
|
2192
|
+
' # opening single quote
|
|
2193
|
+
( # body: zero or more of...
|
|
2194
|
+
[^'\\] # any char that is neither a quote nor a backslash
|
|
2195
|
+
| '' # or a doubled (escaped) quote
|
|
2196
|
+
| \\. # or a backslash followed by any char (backslash escape)
|
|
2197
|
+
)*
|
|
2198
|
+
' # closing single quote
|
|
2199
|
+
""",
|
|
2200
|
+
re.VERBOSE | re.DOTALL,
|
|
2201
|
+
)
|
|
2202
|
+
|
|
2203
|
+
|
|
2204
|
+
def escape_location_literal(value: str) -> str:
|
|
2205
|
+
"""Return ``value`` as a single, well-formed single-quoted SQL literal.
|
|
2206
|
+
|
|
2207
|
+
Unlike :func:`single_quote`, a value that merely starts and ends with a
|
|
2208
|
+
single quote but contains unescaped interior quotes is treated as unquoted
|
|
2209
|
+
and fully escaped. This prevents a caller-controlled location from breaking
|
|
2210
|
+
out of the string literal in the generated ``COPY INTO`` statement.
|
|
2211
|
+
"""
|
|
2212
|
+
if _WELL_FORMED_SINGLE_QUOTED_LITERAL.fullmatch(value):
|
|
2213
|
+
return value
|
|
2214
|
+
return SINGLE_QUOTE + value.replace("'", "''") + SINGLE_QUOTE
|
|
2215
|
+
|
|
2216
|
+
|
|
2095
2217
|
def quote_name_without_upper_casing(name: str) -> str:
|
|
2096
2218
|
return DOUBLE_QUOTE + escape_quotes(name) + DOUBLE_QUOTE
|
|
2097
2219
|
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
# Copyright (c) 2012-2025 Snowflake Computing Inc. All rights reserved.
|
|
3
3
|
#
|
|
4
4
|
|
|
5
|
-
import sys
|
|
6
5
|
import uuid
|
|
7
6
|
import re
|
|
8
7
|
from abc import ABC, abstractmethod
|
|
@@ -90,13 +89,7 @@ from snowflake.snowpark._internal.utils import (
|
|
|
90
89
|
)
|
|
91
90
|
import snowflake.snowpark.context as context
|
|
92
91
|
|
|
93
|
-
|
|
94
|
-
# Python 3.9 can use both
|
|
95
|
-
# Python 3.10 needs to use collections.abc.Iterable because typing.Iterable is removed
|
|
96
|
-
if sys.version_info <= (3, 9):
|
|
97
|
-
from typing import Iterable
|
|
98
|
-
else:
|
|
99
|
-
from collections.abc import Iterable
|
|
92
|
+
from collections.abc import Iterable
|
|
100
93
|
|
|
101
94
|
SET_UNION = analyzer_utils.UNION
|
|
102
95
|
SET_UNION_ALL = analyzer_utils.UNION_ALL
|
|
@@ -276,6 +269,7 @@ class Selectable(LogicalPlan, ABC):
|
|
|
276
269
|
self.pre_actions: Optional[List["Query"]] = None
|
|
277
270
|
self.post_actions: Optional[List["Query"]] = None
|
|
278
271
|
self.flatten_disabled: bool = False
|
|
272
|
+
self.protect_dropped_new_columns: bool = False
|
|
279
273
|
self._column_states: Optional[ColumnStateDict] = None
|
|
280
274
|
self._snowflake_plan: Optional[SnowflakePlan] = None
|
|
281
275
|
self.expr_to_alias = (
|
|
@@ -451,6 +445,19 @@ class Selectable(LogicalPlan, ABC):
|
|
|
451
445
|
# Add the last df ast id to the snowflake plan as the most recent
|
|
452
446
|
# dataframe operation to create this plan.
|
|
453
447
|
self._snowflake_plan.df_ast_ids = self.df_ast_ids
|
|
448
|
+
# Propagate join output flag through passthrough SelectStatements
|
|
449
|
+
# so chained joins can flatten into multi-way joins.
|
|
450
|
+
# Only SelectStatement has has_clause/has_projection; other
|
|
451
|
+
# Selectable subclasses (SelectSQL, SetStatement, etc.) skip this.
|
|
452
|
+
if (
|
|
453
|
+
isinstance(self, SelectStatement)
|
|
454
|
+
and not self.has_clause
|
|
455
|
+
and not self.has_projection
|
|
456
|
+
and isinstance(self.from_, SelectSnowflakePlan)
|
|
457
|
+
):
|
|
458
|
+
self._snowflake_plan._is_join_output = (
|
|
459
|
+
self.from_._snowflake_plan._is_join_output
|
|
460
|
+
)
|
|
454
461
|
return self._snowflake_plan
|
|
455
462
|
|
|
456
463
|
@property
|
|
@@ -597,7 +604,11 @@ class SelectableEntity(Selectable):
|
|
|
597
604
|
# Metadata/Attributes for the plan
|
|
598
605
|
self._attributes: Optional[List[Attribute]] = None
|
|
599
606
|
self.table_reference = self.entity.name
|
|
600
|
-
if self.entity.
|
|
607
|
+
if self.entity.iceberg_changes_config is not None:
|
|
608
|
+
self.table_reference += (
|
|
609
|
+
self.entity.iceberg_changes_config.generate_sql_clause()
|
|
610
|
+
)
|
|
611
|
+
elif self.entity.time_travel_config is not None:
|
|
601
612
|
self.table_reference += self.entity.time_travel_config.generate_sql_clause()
|
|
602
613
|
|
|
603
614
|
def __deepcopy__(self, memodict={}) -> "SelectableEntity": # noqa: B006
|
|
@@ -963,7 +974,7 @@ class SelectStatement(Selectable):
|
|
|
963
974
|
new._snowflake_plan = None
|
|
964
975
|
new.flatten_disabled = False # by default a SelectStatement can be flattened.
|
|
965
976
|
new._api_calls = self._api_calls.copy() if self._api_calls is not None else None
|
|
966
|
-
new.df_aliased_col_name_to_real_col_name = (
|
|
977
|
+
new.df_aliased_col_name_to_real_col_name = deepcopy(
|
|
967
978
|
self.df_aliased_col_name_to_real_col_name
|
|
968
979
|
)
|
|
969
980
|
new._merge_projection_complexity_with_subquery = (
|
|
@@ -1493,7 +1504,7 @@ class SelectStatement(Selectable):
|
|
|
1493
1504
|
can_be_flattened = False
|
|
1494
1505
|
else:
|
|
1495
1506
|
can_be_flattened = can_select_statement_be_flattened(
|
|
1496
|
-
self.column_states, new_column_states
|
|
1507
|
+
self.column_states, new_column_states, self.protect_dropped_new_columns
|
|
1497
1508
|
)
|
|
1498
1509
|
|
|
1499
1510
|
if can_be_flattened:
|
|
@@ -2190,7 +2201,9 @@ def parse_column_name(
|
|
|
2190
2201
|
|
|
2191
2202
|
|
|
2192
2203
|
def can_select_statement_be_flattened(
|
|
2193
|
-
subquery_column_states: ColumnStateDict,
|
|
2204
|
+
subquery_column_states: ColumnStateDict,
|
|
2205
|
+
new_column_states: ColumnStateDict,
|
|
2206
|
+
protect_dropped_new_columns: bool = False,
|
|
2194
2207
|
) -> bool:
|
|
2195
2208
|
for col, state in new_column_states.items():
|
|
2196
2209
|
dependent_columns = state.dependent_columns
|
|
@@ -2213,7 +2226,13 @@ def can_select_statement_be_flattened(
|
|
|
2213
2226
|
state.change_state == ColumnChangeState.DROPPED
|
|
2214
2227
|
and (subquery_state := subquery_column_states.get(col))
|
|
2215
2228
|
and subquery_state.change_state == ColumnChangeState.NEW
|
|
2216
|
-
and
|
|
2229
|
+
and (
|
|
2230
|
+
subquery_state.is_referenced_by_same_level_column
|
|
2231
|
+
# If the subquery was explicitly marked (e.g. by the SCOS withColumn
|
|
2232
|
+
# path), preserve it so that future filter/sort clauses can still
|
|
2233
|
+
# reference the dropped NEW column.
|
|
2234
|
+
or protect_dropped_new_columns
|
|
2235
|
+
)
|
|
2217
2236
|
):
|
|
2218
2237
|
return False
|
|
2219
2238
|
return True
|