snowflake-snowpark-python 1.53.1__tar.gz → 1.55.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.53.1 → snowflake_snowpark_python-1.55.0}/CHANGELOG.md +55 -1
- {snowflake_snowpark_python-1.53.1/src/snowflake_snowpark_python.egg-info → snowflake_snowpark_python-1.55.0}/PKG-INFO +3 -1
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/setup.py +1 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/analyzer_utils.py +46 -74
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/datatype_mapper.py +44 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/expression.py +11 -2
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/select_statement.py +4 -15
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/snowflake_plan.py +7 -10
- snowflake_snowpark_python-1.55.0/src/snowflake/snowpark/_internal/polars_backend.py +135 -0
- snowflake_snowpark_python-1.55.0/src/snowflake/snowpark/_internal/proto/generated/ast_pb2.py +609 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/proto/generated/ast_pb2.pyi +218 -22
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/type_utils.py +6 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/udf_utils.py +15 -3
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/utils.py +23 -15
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/column.py +11 -2
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/dataframe.py +115 -1
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/dataframe_ai_functions.py +438 -39
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/dataframe_writer.py +10 -9
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/functions.py +623 -122
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_functions.py +6 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/compiler/snowflake_query_compiler.py +10 -3
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/relational_grouped_dataframe.py +0 -2
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/session.py +0 -1
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/types.py +2 -2
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/version.py +1 -1
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0/src/snowflake_snowpark_python.egg-info}/PKG-INFO +3 -1
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake_snowpark_python.egg-info/SOURCES.txt +1 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake_snowpark_python.egg-info/requires.txt +2 -0
- snowflake_snowpark_python-1.53.1/src/snowflake/snowpark/_internal/proto/generated/ast_pb2.py +0 -603
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/LICENSE.txt +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/MANIFEST.in +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/README.md +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/pyproject.toml +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/setup.cfg +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/__init__.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_functions/__init__.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_functions/general_functions.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_functions/scalar_functions.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/__init__.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/__init__.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/analyzer.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/binary_expression.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/binary_plan_node.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/grouping_set.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/metadata_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/query_plan_analysis_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/schema_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/snowflake_plan_node.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/sort_expression.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/table_function.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/table_merge_expression.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/unary_expression.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/unary_plan_node.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/window_expression.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/ast/__init__.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/ast/batch.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/ast/builder.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/ast/utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/code_generation.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/compiler/__init__.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/compiler/cte_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/compiler/large_query_breakdown.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/compiler/plan_compiler.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/compiler/query_generator.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/compiler/repeated_subquery_elimination.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/compiler/telemetry_constants.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/compiler/utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/__init__.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/datasource_partitioner.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/datasource_reader.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/datasource_typing.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/__init__.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/base_dialect.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/databricks_dialect.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/mysql_dialect.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/oracledb_dialect.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/postgresql_dialect.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/sqlite3_dialect.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/sqlserver_dialect.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/drivers/__init__.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/drivers/base_driver.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/drivers/databricks_driver.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/drivers/oracledb_driver.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/drivers/psycopg2_driver.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/drivers/pymsql_driver.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/drivers/pyodbc_driver.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/drivers/sqlite_driver.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/jdbc.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/debug_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/error_message.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/event_table_telemetry.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/open_telemetry.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/packaging_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/proto/generated/__init__.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/select_projection_complexity_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/server_connection.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/snowpark_profiler.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/telemetry.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/temp_table_auto_cleaner.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/xml_reader.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/xml_schema_inference.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/xpath_handlers.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/async_job.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/catalog.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/context.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/dataframe_analytics_functions.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/dataframe_na_functions.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/dataframe_profiler.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/dataframe_reader.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/dataframe_stat_functions.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/exceptions.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/file_operation.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/files.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/lineage.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/__init__.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_analyzer.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_connection.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_constants.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_nop_analyzer.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_nop_connection.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_nop_plan.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_options.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_pandas_util.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_plan.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_plan_builder.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_select_statement.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_snowflake_data_type.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_snowflake_to_pandas_converter.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_stage_registry.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_stored_procedure.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_telemetry.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_udaf.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_udf.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_udf_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_udtf.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_util.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_window_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/exceptions.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/__init__.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/config/__init__.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/config/__main__.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/config/envvars.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/config/pubsub.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/conftest.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/__init__.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/__init__.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/aggregation_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/align_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/apply_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/binary_op_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/concat_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/cumulative_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/cut_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/frame.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/generator_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/get_dummies_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/groupby_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/indexing_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/io_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/isin_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/join_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/ordered_dataframe.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/pivot_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/resample_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/row_count_estimation.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/session.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/snowpark_pandas_types.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/statement_params_constants.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/telemetry.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/timestamp_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/transpose_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/type_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/unpivot_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/where_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/window_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_typing.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/compiler/__init__.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/compiler/doc_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/compiler/ray_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/docstrings/__init__.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/docstrings/base.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/docstrings/dataframe.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/docstrings/datetime_index.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/docstrings/general.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/docstrings/groupby.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/docstrings/index.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/docstrings/io.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/docstrings/resample.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/docstrings/series.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/docstrings/series_utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/docstrings/shared_docs.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/docstrings/timedelta_index.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/docstrings/window.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/__init__.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/base_overrides.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/dataframe_extensions.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/dataframe_groupby_overrides.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/dataframe_overrides.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/datetime_index.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/general_overrides.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/index.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/indexing_overrides.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/io_overrides.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/pd_extensions.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/resample_overrides.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/resampler_groupby_overrides.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/rolling_groupby_overrides.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/series_extensions.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/series_groupby_overrides.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/series_overrides.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/snow_partition_iterator.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/timedelta_index.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/window_overrides.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/io/__init__.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/io/factories.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/io/snow_io.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/utils/__init__.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/utils/error_message.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/utils/exceptions.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/utils/frontend_constants.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/utils/numpy_to_pandas.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/utils/warning_message.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/utils.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/py.typed +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/query_history.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/row.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/secrets.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/stored_procedure.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/stored_procedure_profiler.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/table.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/table_function.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/testing.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/udaf.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/udf.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/udf_profiler.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/udtf.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/window.py +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake_snowpark_python.egg-info/dependency_links.txt +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake_snowpark_python.egg-info/namespace_packages.txt +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake_snowpark_python.egg-info/not-zip-safe +0 -0
- {snowflake_snowpark_python-1.53.1 → snowflake_snowpark_python-1.55.0}/src/snowflake_snowpark_python.egg-info/top_level.txt +0 -0
|
@@ -1,5 +1,56 @@
|
|
|
1
1
|
# Release History
|
|
2
2
|
|
|
3
|
+
## 1.55.0 (2026-09-10)
|
|
4
|
+
|
|
5
|
+
### Snowpark Python API Updates
|
|
6
|
+
|
|
7
|
+
#### New Features
|
|
8
|
+
|
|
9
|
+
- Added `DataFrame.to_polars()` to convert a Snowpark DataFrame to a Polars DataFrame. Supports an optional `transport="parquet"` mode for large data-transfer-dominated workloads.
|
|
10
|
+
- Added interval type support for Python UDFs and stored procedures. Use `datetime.timedelta` as the type annotation for day-time interval (`DayTimeIntervalType`) parameters and return values, and `YearMonthInterval` (a type annotation sentinel from `snowflake.snowpark.types`) for year-month interval (`YearMonthIntervalType`) parameters and return values.
|
|
11
|
+
- Added support for a `table_properties` key in the `iceberg_config` dictionary of `DataFrameWriter.save_as_table`, which emits a `TABLE_PROPERTIES = ('k'='v', ...)` clause on Iceberg table creation (CREATE / CTAS).
|
|
12
|
+
|
|
13
|
+
#### Bug Fixes
|
|
14
|
+
|
|
15
|
+
- Fixed registering a UDF, UDTF, or stored procedure with an integer optional argument failing with `SQL compilation error: invalid default argument expression`. Integer defaults were emitted as `DEFAULT <value> :: INT`, and a parameter default only accepts a constant expression. The redundant cast is no longer generated.
|
|
16
|
+
|
|
17
|
+
#### Documentation
|
|
18
|
+
|
|
19
|
+
- Documented the JSON Schema `response_format` shape for `ai_extract` and `DataFrame.ai.extract`.
|
|
20
|
+
|
|
21
|
+
#### Other Changes
|
|
22
|
+
|
|
23
|
+
- Test-only: fixed `test_generator_table_function` failing as `assert 0 < 0` on the `seq2(0)` + `generator(timelimit => 1)` case. `seq2(0)` passes sign=0, so it continues at 0 after 32767, and a one-second generator run usually emits far more than one 32768-value cycle, making `ORDER BY seq2(0) LIMIT 3` return `0, 0, 0`. That assertion now allows equal values; the `seq1(1)` + `rowcount` assertions stay strictly increasing.
|
|
24
|
+
|
|
25
|
+
### Snowpark pandas API Updates
|
|
26
|
+
|
|
27
|
+
#### Bug Fixes
|
|
28
|
+
|
|
29
|
+
- Fixed a bug where referencing `modin.pandas` inside a Snowpark pandas `apply()` function raised a `ModuleNotFoundError`.
|
|
30
|
+
|
|
31
|
+
## 1.54.0 (2026-07-29)
|
|
32
|
+
|
|
33
|
+
### Snowpark Python API updates
|
|
34
|
+
|
|
35
|
+
#### New Features
|
|
36
|
+
|
|
37
|
+
- Added `ai_count_tokens` function to `snowflake.snowpark.functions` to estimate token counts for AI function calls.
|
|
38
|
+
- Added `ai_multi_embed` function to `snowflake.snowpark.functions` to generate multimodal embeddings from text, images, audio, or video files.
|
|
39
|
+
- Added `ai_redact` function to `snowflake.snowpark.functions` to detect and redact personally identifiable information (PII) from text.
|
|
40
|
+
- Added `DataFrame.ai.multi_embed` method to generate multimodal embeddings via the DataFrame API.
|
|
41
|
+
- Added `DataFrame.ai.redact` method to detect and redact PII from text columns via the DataFrame API.
|
|
42
|
+
- Added `DataFrame.ai.translate` method to translate text columns between languages via the DataFrame API.
|
|
43
|
+
|
|
44
|
+
#### Improvements
|
|
45
|
+
|
|
46
|
+
- Removed the `experimental` tag from all AI SQL functions in `DataFrameAIFunctions` (`complete`, `filter`, `agg`, `classify`, `similarity`, `sentiment`, `embed`, `summarize_agg`, `transcribe`, `parse_document`, `extract`, `count_tokens`, `split_text_markdown_header`, `split_text_recursive_character`) and `RelationalGroupedDataFrame.ai_agg`.
|
|
47
|
+
- Updated `DataFrame.ai.count_tokens` to match the standalone `ai_count_tokens` function: `function_name` is now the required first parameter, and `model` is optional. Also added `options` and `return_error_details` parameters.
|
|
48
|
+
|
|
49
|
+
#### Bug Fixes
|
|
50
|
+
|
|
51
|
+
- Fixed `DataFrame.ai.count_tokens` to call the `AI_COUNT_TOKENS` SQL function instead of the deprecated `SNOWFLAKE.CORTEX.COUNT_TOKENS`. Token counts may differ slightly due to the updated tokenizer.
|
|
52
|
+
- Reverted the change introduced in 1.53.0 to eliminate unnecessary `SELECT *` from joins, which was causing performance regressions. This has no functional impact.
|
|
53
|
+
|
|
3
54
|
## 1.53.1 (2026-07-14)
|
|
4
55
|
|
|
5
56
|
No user-facing changes in this release.
|
|
@@ -23,6 +74,10 @@ No user-facing changes in this release.
|
|
|
23
74
|
- 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.
|
|
24
75
|
- 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).
|
|
25
76
|
|
|
77
|
+
#### Improvements
|
|
78
|
+
|
|
79
|
+
- Reduced the size of generated query text for repeated join operations.
|
|
80
|
+
|
|
26
81
|
#### Dependency Updates
|
|
27
82
|
|
|
28
83
|
- Lifted `protobuf` restriction for Python 3.14 from `==5.29.3` to `>=5.29.3,<6.34`.
|
|
@@ -45,7 +100,6 @@ No user-facing changes in this release.
|
|
|
45
100
|
#### Improvements
|
|
46
101
|
|
|
47
102
|
- Improved CTE optimization to deduplicate identical subtrees in self-joins, which were previously emitted as repeated subqueries.
|
|
48
|
-
- Reduced the size of generated query text for repeated join operations.
|
|
49
103
|
|
|
50
104
|
#### Deprecations
|
|
51
105
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: snowflake-snowpark-python
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.55.0
|
|
4
4
|
Summary: Snowflake Snowpark for Python
|
|
5
5
|
Home-page: https://www.snowflake.com/
|
|
6
6
|
Author: Snowflake, Inc
|
|
@@ -77,6 +77,7 @@ Requires-Dist: snowflake.core<2,>=1.0.0; extra == "development"
|
|
|
77
77
|
Requires-Dist: psutil; extra == "development"
|
|
78
78
|
Requires-Dist: lxml; extra == "development"
|
|
79
79
|
Requires-Dist: pyarrow; extra == "development"
|
|
80
|
+
Requires-Dist: polars>=1.0; extra == "development"
|
|
80
81
|
Provides-Extra: modin-development
|
|
81
82
|
Requires-Dist: snowflake-connector-python[pandas]<5.0.0,>=3.17.0; extra == "modin-development"
|
|
82
83
|
Requires-Dist: pandas<3.0.0; extra == "modin-development"
|
|
@@ -103,6 +104,7 @@ Requires-Dist: snowflake.core<2,>=1.0.0; extra == "modin-development"
|
|
|
103
104
|
Requires-Dist: psutil; extra == "modin-development"
|
|
104
105
|
Requires-Dist: lxml; extra == "modin-development"
|
|
105
106
|
Requires-Dist: pyarrow; extra == "modin-development"
|
|
107
|
+
Requires-Dist: polars>=1.0; extra == "modin-development"
|
|
106
108
|
Requires-Dist: scipy<=1.16.3; extra == "modin-development"
|
|
107
109
|
Requires-Dist: statsmodels; extra == "modin-development"
|
|
108
110
|
Requires-Dist: scikit-learn; extra == "modin-development"
|
|
@@ -73,6 +73,7 @@ DEVELOPMENT_REQUIREMENTS = [
|
|
|
73
73
|
"psutil", # testing for telemetry
|
|
74
74
|
"lxml", # used in XML reader unit tests
|
|
75
75
|
"pyarrow", # used in dataframe reader tests
|
|
76
|
+
"polars>=1.0", # used in test_df_to_polars integration tests
|
|
76
77
|
]
|
|
77
78
|
MODIN_DEVELOPMENT_REQUIREMENTS = [
|
|
78
79
|
# Snowpark pandas 3rd party library testing. Cap the scipy version because
|
|
@@ -150,6 +150,7 @@ BASE_LOCATION = " BASE_LOCATION "
|
|
|
150
150
|
TARGET_FILE_SIZE = " TARGET_FILE_SIZE "
|
|
151
151
|
CATALOG_SYNC = " CATALOG_SYNC "
|
|
152
152
|
STORAGE_SERIALIZATION_POLICY = " STORAGE_SERIALIZATION_POLICY "
|
|
153
|
+
TABLE_PROPERTIES = " TABLE_PROPERTIES"
|
|
153
154
|
REG_EXP = " REGEXP "
|
|
154
155
|
COLLATE = " COLLATE "
|
|
155
156
|
RESULT_SCAN = " RESULT_SCAN"
|
|
@@ -334,6 +335,30 @@ def iceberg_partition_clause(partition_exprs: List[str]) -> str:
|
|
|
334
335
|
)
|
|
335
336
|
|
|
336
337
|
|
|
338
|
+
def iceberg_table_properties_clause(iceberg_config: Optional[dict]) -> str:
|
|
339
|
+
"""Emit ``TABLE_PROPERTIES = ('k'='v', ...)`` from an ``iceberg_config``'s
|
|
340
|
+
``table_properties`` map (keys kept verbatim, keys/values escaped); empty
|
|
341
|
+
when absent."""
|
|
342
|
+
if not iceberg_config:
|
|
343
|
+
return EMPTY_STRING
|
|
344
|
+
normalized = {k.lower(): v for k, v in iceberg_config.items()}
|
|
345
|
+
table_properties = normalized.get("table_properties")
|
|
346
|
+
if not table_properties:
|
|
347
|
+
return EMPTY_STRING
|
|
348
|
+
|
|
349
|
+
# Escape via ``escape_quotes_and_backslashes`` (not ``single_quote``): it
|
|
350
|
+
# escapes backslashes as well as quotes and never skips escaping, so a
|
|
351
|
+
# crafted key/value cannot break out of its literal and inject extra SQL
|
|
352
|
+
# (e.g. "'x', 'injected'='surprise'" or "x\\') COPY GRANTS --").
|
|
353
|
+
def _quote(value: object) -> str:
|
|
354
|
+
return SINGLE_QUOTE + escape_quotes_and_backslashes(str(value)) + SINGLE_QUOTE
|
|
355
|
+
|
|
356
|
+
pairs = COMMA.join(f"{_quote(k)}={_quote(v)}" for k, v in table_properties.items())
|
|
357
|
+
return (
|
|
358
|
+
SPACE + TABLE_PROPERTIES + EQUALS + LEFT_PARENTHESIS + pairs + RIGHT_PARENTHESIS
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
|
|
337
362
|
def order_by_spec(col_exprs: List[str]) -> str:
|
|
338
363
|
if not col_exprs:
|
|
339
364
|
return EMPTY_STRING
|
|
@@ -990,33 +1015,6 @@ def lateral_join_statement(
|
|
|
990
1015
|
)
|
|
991
1016
|
|
|
992
1017
|
|
|
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
|
-
|
|
1020
1018
|
def snowflake_supported_join_statement(
|
|
1021
1019
|
left: str,
|
|
1022
1020
|
right: str,
|
|
@@ -1027,30 +1025,17 @@ def snowflake_supported_join_statement(
|
|
|
1027
1025
|
left_uuid: Optional[str] = None,
|
|
1028
1026
|
right_uuid: Optional[str] = None,
|
|
1029
1027
|
directed: bool = False,
|
|
1030
|
-
left_is_join: bool = False,
|
|
1031
1028
|
) -> str:
|
|
1032
1029
|
LEFT_UUID = format_uuid(left_uuid)
|
|
1033
1030
|
RIGHT_UUID = format_uuid(right_uuid)
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
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
|
|
1031
|
+
left_alias = (
|
|
1032
|
+
"SNOWPARK_LEFT"
|
|
1033
|
+
if use_constant_subquery_alias
|
|
1034
|
+
else random_name_for_temp_object(TempObjectType.TABLE)
|
|
1035
|
+
)
|
|
1049
1036
|
right_alias = (
|
|
1050
1037
|
"SNOWPARK_RIGHT"
|
|
1051
|
-
if use_constant_subquery_alias
|
|
1052
|
-
# Multi-way join: right alias must be unique to avoid collisions
|
|
1053
|
-
# with aliases already present in the flattened join source.
|
|
1038
|
+
if use_constant_subquery_alias
|
|
1054
1039
|
else random_name_for_temp_object(TempObjectType.TABLE)
|
|
1055
1040
|
)
|
|
1056
1041
|
|
|
@@ -1086,31 +1071,18 @@ def snowflake_supported_join_statement(
|
|
|
1086
1071
|
|
|
1087
1072
|
maybe_directed_sql = DIRECTED_JOIN if directed else JOIN
|
|
1088
1073
|
|
|
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
|
-
)
|
|
1112
1074
|
source = (
|
|
1113
|
-
|
|
1075
|
+
LEFT_PARENTHESIS
|
|
1076
|
+
+ NEW_LINE
|
|
1077
|
+
+ LEFT_UUID
|
|
1078
|
+
+ left
|
|
1079
|
+
+ NEW_LINE
|
|
1080
|
+
+ LEFT_UUID
|
|
1081
|
+
+ RIGHT_PARENTHESIS
|
|
1082
|
+
+ AS
|
|
1083
|
+
+ left_alias
|
|
1084
|
+
+ SPACE
|
|
1085
|
+
+ NEW_LINE
|
|
1114
1086
|
+ join_sql
|
|
1115
1087
|
+ maybe_directed_sql
|
|
1116
1088
|
+ NEW_LINE
|
|
@@ -1142,7 +1114,6 @@ def join_statement(
|
|
|
1142
1114
|
left_uuid: Optional[str] = None,
|
|
1143
1115
|
right_uuid: Optional[str] = None,
|
|
1144
1116
|
directed: bool = False,
|
|
1145
|
-
left_is_join: bool = False,
|
|
1146
1117
|
) -> str:
|
|
1147
1118
|
if isinstance(join_type, (LeftSemi, LeftAnti)):
|
|
1148
1119
|
return left_semi_or_anti_join_statement(
|
|
@@ -1170,7 +1141,6 @@ def join_statement(
|
|
|
1170
1141
|
left_uuid=left_uuid,
|
|
1171
1142
|
right_uuid=right_uuid,
|
|
1172
1143
|
directed=directed,
|
|
1173
|
-
left_is_join=left_is_join,
|
|
1174
1144
|
)
|
|
1175
1145
|
|
|
1176
1146
|
|
|
@@ -1223,13 +1193,14 @@ def create_table_statement(
|
|
|
1223
1193
|
options_statement = get_options_statement(options)
|
|
1224
1194
|
|
|
1225
1195
|
partition_by_clause = iceberg_partition_clause(partition_exprs)
|
|
1196
|
+
table_properties_clause = iceberg_table_properties_clause(iceberg_config)
|
|
1226
1197
|
|
|
1227
1198
|
return (
|
|
1228
1199
|
f"{CREATE}{(OR + REPLACE) if replace else EMPTY_STRING}"
|
|
1229
1200
|
f" {(get_temp_type_for_object(use_scoped_temp_objects, is_generated) if table_type.lower() in TEMPORARY_STRING_SET else table_type).upper()} "
|
|
1230
1201
|
f"{ICEBERG if iceberg_options else EMPTY_STRING}{TABLE}{table_name}{(IF + NOT + EXISTS) if not replace and not error else EMPTY_STRING}"
|
|
1231
1202
|
f"{LEFT_PARENTHESIS}{schema}{RIGHT_PARENTHESIS}{partition_by_clause}{cluster_by_clause}"
|
|
1232
|
-
f"{options_statement}{COPY_GRANTS if copy_grants else EMPTY_STRING}{comment_sql}"
|
|
1203
|
+
f"{options_statement}{table_properties_clause}{COPY_GRANTS if copy_grants else EMPTY_STRING}{comment_sql}"
|
|
1233
1204
|
)
|
|
1234
1205
|
|
|
1235
1206
|
|
|
@@ -1314,13 +1285,14 @@ def create_table_as_select_statement(
|
|
|
1314
1285
|
options_statement = get_options_statement(options)
|
|
1315
1286
|
|
|
1316
1287
|
partition_by_clause = iceberg_partition_clause(partition_exprs)
|
|
1288
|
+
table_properties_clause = iceberg_table_properties_clause(iceberg_config)
|
|
1317
1289
|
|
|
1318
1290
|
return (
|
|
1319
1291
|
f"{CREATE}{OR + REPLACE if replace else EMPTY_STRING}"
|
|
1320
1292
|
f" {(get_temp_type_for_object(use_scoped_temp_objects, is_generated) if table_type.lower() in TEMPORARY_STRING_SET else table_type).upper()} "
|
|
1321
1293
|
f"{ICEBERG if iceberg_options else EMPTY_STRING}{TABLE}"
|
|
1322
1294
|
f"{IF + NOT + EXISTS if not replace and not error else EMPTY_STRING} "
|
|
1323
|
-
f"{table_name}{column_definition_sql}{partition_by_clause}{cluster_by_clause}{options_statement}"
|
|
1295
|
+
f"{table_name}{column_definition_sql}{partition_by_clause}{cluster_by_clause}{options_statement}{table_properties_clause}"
|
|
1324
1296
|
f"{COPY_GRANTS if copy_grants else EMPTY_STRING}{comment_sql} {AS}{project_statement([], child)}"
|
|
1325
1297
|
)
|
|
1326
1298
|
|
|
@@ -331,6 +331,25 @@ def to_sql_no_cast(
|
|
|
331
331
|
return f"{value}"
|
|
332
332
|
|
|
333
333
|
|
|
334
|
+
def to_sql_for_default_arg(value: Any, datatype: DataType) -> str:
|
|
335
|
+
"""Convert a value with DataType to SQL usable as a parameter's DEFAULT.
|
|
336
|
+
|
|
337
|
+
Identical to :func:`to_sql` except that integral values are emitted as bare
|
|
338
|
+
literals rather than ``<value> :: INT``. A DEFAULT only accepts a constant
|
|
339
|
+
expression, and the parameter already declares its own type, so the cast is
|
|
340
|
+
redundant. Snowflake rejects it outright on some server versions with
|
|
341
|
+
``invalid default argument expression`` (SNOW-4013704).
|
|
342
|
+
"""
|
|
343
|
+
if isinstance(datatype, _IntegralType):
|
|
344
|
+
if value is None:
|
|
345
|
+
return "NULL"
|
|
346
|
+
if isinstance(value, int):
|
|
347
|
+
# bool is a subclass of int, so normalize it to 0/1 for an
|
|
348
|
+
# integral parameter rather than emitting True/False.
|
|
349
|
+
return str(int(value))
|
|
350
|
+
return to_sql(value, datatype)
|
|
351
|
+
|
|
352
|
+
|
|
334
353
|
def to_sql(
|
|
335
354
|
value: Any,
|
|
336
355
|
datatype: DataType,
|
|
@@ -501,6 +520,31 @@ def to_sql(
|
|
|
501
520
|
if isinstance(value, str) and isinstance(datatype, DayTimeIntervalType):
|
|
502
521
|
return f"{str_to_sql_for_day_time_interval(value, datatype)} :: {convert_sp_to_sf_type(datatype)}"
|
|
503
522
|
|
|
523
|
+
if isinstance(value, timedelta) and isinstance(datatype, DayTimeIntervalType):
|
|
524
|
+
# Serialize timedelta as an INTERVAL DAY TO SECOND literal.
|
|
525
|
+
# timedelta stores (days, seconds, microseconds) all non-negative after normalization.
|
|
526
|
+
sign = "-" if value < timedelta(0) else "+"
|
|
527
|
+
abs_val = abs(value)
|
|
528
|
+
d = abs_val.days
|
|
529
|
+
total_us = abs_val.seconds * 1_000_000 + abs_val.microseconds
|
|
530
|
+
h = total_us // 3_600_000_000
|
|
531
|
+
total_us %= 3_600_000_000
|
|
532
|
+
m = total_us // 60_000_000
|
|
533
|
+
total_us %= 60_000_000
|
|
534
|
+
s = total_us // 1_000_000
|
|
535
|
+
us = total_us % 1_000_000
|
|
536
|
+
interval_str = f"{sign}{d} {h:02d}:{m:02d}:{s:02d}.{us:06d}"
|
|
537
|
+
return f"INTERVAL '{interval_str}' DAY TO SECOND :: {convert_sp_to_sf_type(datatype)}"
|
|
538
|
+
|
|
539
|
+
if isinstance(value, int) and isinstance(datatype, YearMonthIntervalType):
|
|
540
|
+
# Serialize int (total months) as an INTERVAL YEAR TO MONTH literal.
|
|
541
|
+
sign = "-" if value < 0 else "+"
|
|
542
|
+
abs_months = abs(value)
|
|
543
|
+
years = abs_months // 12
|
|
544
|
+
months = abs_months % 12
|
|
545
|
+
interval_str = f"{sign}{years}-{months:02d}"
|
|
546
|
+
return f"INTERVAL '{interval_str}' YEAR TO MONTH :: {convert_sp_to_sf_type(datatype)}"
|
|
547
|
+
|
|
504
548
|
raise TypeError(f"Unsupported datatype {datatype}, value {value} by to_sql()")
|
|
505
549
|
|
|
506
550
|
|
|
@@ -295,13 +295,22 @@ class Star(Expression):
|
|
|
295
295
|
|
|
296
296
|
class UnresolvedAttribute(Expression, NamedExpression):
|
|
297
297
|
def __init__(
|
|
298
|
-
self,
|
|
298
|
+
self,
|
|
299
|
+
name: str,
|
|
300
|
+
is_sql_text: bool = False,
|
|
301
|
+
df_alias: Optional[str] = None,
|
|
302
|
+
is_constant: bool = False,
|
|
299
303
|
) -> None:
|
|
300
304
|
super().__init__()
|
|
301
305
|
self.df_alias = df_alias
|
|
302
306
|
self.name = name
|
|
303
307
|
self.is_sql_text = is_sql_text
|
|
304
|
-
|
|
308
|
+
self.is_constant = is_constant
|
|
309
|
+
if is_constant:
|
|
310
|
+
# Constant SQL text (e.g. object/array literals) does not reference
|
|
311
|
+
# any columns from the input relation.
|
|
312
|
+
self._dependent_column_names = COLUMN_DEPENDENCY_EMPTY
|
|
313
|
+
elif "$" in name:
|
|
305
314
|
# $n refers to a column by index. We don't consider column index yet.
|
|
306
315
|
# even though "$" isn't necessarily used to refer to a column by index. We're conservative here.
|
|
307
316
|
self._dependent_column_names = COLUMN_DEPENDENCY_DOLLAR
|
|
@@ -445,19 +445,6 @@ class Selectable(LogicalPlan, ABC):
|
|
|
445
445
|
# Add the last df ast id to the snowflake plan as the most recent
|
|
446
446
|
# dataframe operation to create this plan.
|
|
447
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
|
-
)
|
|
461
448
|
return self._snowflake_plan
|
|
462
449
|
|
|
463
450
|
@property
|
|
@@ -605,8 +592,10 @@ class SelectableEntity(Selectable):
|
|
|
605
592
|
self._attributes: Optional[List[Attribute]] = None
|
|
606
593
|
self.table_reference = self.entity.name
|
|
607
594
|
if self.entity.iceberg_changes_config is not None:
|
|
608
|
-
self.table_reference
|
|
609
|
-
self.entity.iceberg_changes_config.
|
|
595
|
+
self.table_reference = (
|
|
596
|
+
self.entity.iceberg_changes_config.generate_table_reference(
|
|
597
|
+
self.entity.name
|
|
598
|
+
)
|
|
610
599
|
)
|
|
611
600
|
elif self.entity.time_travel_config is not None:
|
|
612
601
|
self.table_reference += self.entity.time_travel_config.generate_sql_clause()
|
|
@@ -458,7 +458,6 @@ class SnowflakePlan(LogicalPlan):
|
|
|
458
458
|
self.session = session
|
|
459
459
|
self.source_plan = source_plan
|
|
460
460
|
self.is_ddl_on_temp_object = is_ddl_on_temp_object
|
|
461
|
-
self._is_join_output = False
|
|
462
461
|
# We need to copy this list since we don't want to change it for the
|
|
463
462
|
# previous SnowflakePlan objects
|
|
464
463
|
self.api_calls = api_calls.copy() if api_calls else []
|
|
@@ -770,7 +769,6 @@ class SnowflakePlan(LogicalPlan):
|
|
|
770
769
|
referenced_ctes=self.referenced_ctes,
|
|
771
770
|
)
|
|
772
771
|
plan.df_ast_ids = self.df_ast_ids
|
|
773
|
-
plan._is_join_output = self._is_join_output
|
|
774
772
|
return plan
|
|
775
773
|
|
|
776
774
|
def __deepcopy__(self, memodict={}) -> "SnowflakePlan": # noqa: B006
|
|
@@ -810,7 +808,6 @@ class SnowflakePlan(LogicalPlan):
|
|
|
810
808
|
if copied_source_plan:
|
|
811
809
|
copied_source_plan._is_valid_for_replacement = True
|
|
812
810
|
copied_plan.df_ast_ids = self.df_ast_ids
|
|
813
|
-
copied_plan._is_join_output = self._is_join_output
|
|
814
811
|
|
|
815
812
|
return copied_plan
|
|
816
813
|
|
|
@@ -1070,8 +1067,10 @@ class SnowflakePlanBuilder:
|
|
|
1070
1067
|
table_reference = table_name
|
|
1071
1068
|
if isinstance(source_plan, SnowflakeTable):
|
|
1072
1069
|
if source_plan.iceberg_changes_config:
|
|
1073
|
-
table_reference
|
|
1074
|
-
source_plan.iceberg_changes_config.
|
|
1070
|
+
table_reference = (
|
|
1071
|
+
source_plan.iceberg_changes_config.generate_table_reference(
|
|
1072
|
+
table_name
|
|
1073
|
+
)
|
|
1075
1074
|
)
|
|
1076
1075
|
elif source_plan.time_travel_config:
|
|
1077
1076
|
table_reference += source_plan.time_travel_config.generate_sql_clause()
|
|
@@ -1239,8 +1238,7 @@ class SnowflakePlanBuilder:
|
|
|
1239
1238
|
use_constant_subquery_alias: bool,
|
|
1240
1239
|
directed: bool = False,
|
|
1241
1240
|
):
|
|
1242
|
-
|
|
1243
|
-
result = self.build_binary(
|
|
1241
|
+
return self.build_binary(
|
|
1244
1242
|
lambda x, y: join_statement(
|
|
1245
1243
|
x,
|
|
1246
1244
|
y,
|
|
@@ -1257,14 +1255,11 @@ class SnowflakePlanBuilder:
|
|
|
1257
1255
|
else None
|
|
1258
1256
|
),
|
|
1259
1257
|
directed=directed,
|
|
1260
|
-
left_is_join=left_is_join,
|
|
1261
1258
|
),
|
|
1262
1259
|
left,
|
|
1263
1260
|
right,
|
|
1264
1261
|
source_plan,
|
|
1265
1262
|
)
|
|
1266
|
-
result._is_join_output = True
|
|
1267
|
-
return result
|
|
1268
1263
|
|
|
1269
1264
|
def save_as_table(
|
|
1270
1265
|
self,
|
|
@@ -1323,6 +1318,8 @@ class SnowflakePlanBuilder:
|
|
|
1323
1318
|
catalog_sync: optionally sets the catalog integration configured for Polaris Catalog
|
|
1324
1319
|
storage_serialization_policy: specifies the storage serialization policy for the table
|
|
1325
1320
|
iceberg_version: Overrides the version of iceberg to use. Defaults to 2 when unset.
|
|
1321
|
+
table_properties: optional mapping of Iceberg property names to values, emitted
|
|
1322
|
+
verbatim as a ``TABLE_PROPERTIES = ('k'='v', ...)`` clause on CREATE / CTAS.
|
|
1326
1323
|
table_exists: whether the table already exists in the database.
|
|
1327
1324
|
Only used for APPEND and TRUNCATE mode.
|
|
1328
1325
|
"""
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (c) 2012-2025 Snowflake Computing Inc. All rights reserved.
|
|
3
|
+
#
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import uuid
|
|
7
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
8
|
+
from typing import TYPE_CHECKING
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
import polars as pl
|
|
12
|
+
from snowflake.snowpark.dataframe import DataFrame
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _empty_frame_from_schema(
|
|
16
|
+
df: DataFrame, statement_params: dict[str, str] | None
|
|
17
|
+
) -> pl.DataFrame:
|
|
18
|
+
"""Return an empty polars DataFrame with the DataFrame's schema."""
|
|
19
|
+
import polars as pl
|
|
20
|
+
|
|
21
|
+
return pl.from_arrow(
|
|
22
|
+
df.limit(0).to_arrow(
|
|
23
|
+
statement_params=statement_params,
|
|
24
|
+
_emit_ast=False,
|
|
25
|
+
)
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _open_stage_files_parallel(
|
|
30
|
+
session,
|
|
31
|
+
paths: list[str],
|
|
32
|
+
is_sproc: bool,
|
|
33
|
+
max_workers: int | None = None,
|
|
34
|
+
) -> list:
|
|
35
|
+
"""Open stage files concurrently, reading each with ``pl.read_parquet``
|
|
36
|
+
and returning the resulting ``pl.DataFrame`` (``with`` closes the handle
|
|
37
|
+
after read).
|
|
38
|
+
|
|
39
|
+
Uses ``SnowflakeFile.open`` inside a stored procedure and
|
|
40
|
+
``session.file.get_stream`` on the client.
|
|
41
|
+
"""
|
|
42
|
+
if not paths:
|
|
43
|
+
return []
|
|
44
|
+
|
|
45
|
+
import polars as pl
|
|
46
|
+
|
|
47
|
+
if is_sproc:
|
|
48
|
+
from snowflake.snowpark.files import SnowflakeFile
|
|
49
|
+
|
|
50
|
+
def opener(p: str):
|
|
51
|
+
return SnowflakeFile.open(p, "rb", require_scoped_url=False)
|
|
52
|
+
|
|
53
|
+
else:
|
|
54
|
+
opener = session.file.get_stream
|
|
55
|
+
|
|
56
|
+
def _work(p: str):
|
|
57
|
+
with opener(p) as f:
|
|
58
|
+
return pl.read_parquet(f)
|
|
59
|
+
|
|
60
|
+
with ThreadPoolExecutor(max_workers=max_workers) as ex:
|
|
61
|
+
return list(ex.map(_work, paths))
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _copy_df_to_stage(
|
|
65
|
+
df: DataFrame,
|
|
66
|
+
sub_prefix: str,
|
|
67
|
+
statement_params: dict[str, str] | None = None,
|
|
68
|
+
) -> list[str]:
|
|
69
|
+
"""COPY INTO the session stage as Parquet and return the staged file paths.
|
|
70
|
+
|
|
71
|
+
Uses ``DataFrame.write.copy_into_location`` so plan compilation and
|
|
72
|
+
statement params go through the same path as other write actions. No
|
|
73
|
+
pre-sort is applied — callers wanting row-group elimination should
|
|
74
|
+
``.sort(...)`` before ``to_polars``.
|
|
75
|
+
"""
|
|
76
|
+
rid = uuid.uuid4().hex[:12]
|
|
77
|
+
stage = df._session.get_session_stage().rstrip("/")
|
|
78
|
+
sub = f"{stage}/{sub_prefix}/{rid}/"
|
|
79
|
+
df.write.copy_into_location(
|
|
80
|
+
sub,
|
|
81
|
+
file_format_type="parquet",
|
|
82
|
+
format_type_options={"COMPRESSION": "SNAPPY"},
|
|
83
|
+
header=True,
|
|
84
|
+
overwrite=True,
|
|
85
|
+
statement_params=statement_params,
|
|
86
|
+
)
|
|
87
|
+
rows = df._session.sql(f"LIST '{sub}'").collect(statement_params=statement_params)
|
|
88
|
+
# `sub` is fully qualified; LIST returns stage-relative names. Construct fully-qualified paths.
|
|
89
|
+
return [sub + row["name"].rsplit("/", 1)[-1] for row in rows]
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def arrow_eager(
|
|
93
|
+
df: DataFrame,
|
|
94
|
+
statement_params: dict[str, str] | None = None,
|
|
95
|
+
) -> pl.DataFrame:
|
|
96
|
+
"""Fetch the result as Arrow batches and return a polars DataFrame.
|
|
97
|
+
|
|
98
|
+
Backs the default ``to_polars()`` path (``transport="arrow"``).
|
|
99
|
+
Preserves full Snowflake type fidelity.
|
|
100
|
+
"""
|
|
101
|
+
import polars as pl
|
|
102
|
+
|
|
103
|
+
parts = [
|
|
104
|
+
pl.from_arrow(batch)
|
|
105
|
+
for batch in df.to_arrow_batches(
|
|
106
|
+
statement_params=statement_params, _emit_ast=False
|
|
107
|
+
)
|
|
108
|
+
]
|
|
109
|
+
if not parts:
|
|
110
|
+
return _empty_frame_from_schema(df, statement_params)
|
|
111
|
+
return pl.concat(parts) if len(parts) > 1 else parts[0]
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def parquet_eager(
|
|
115
|
+
df: DataFrame,
|
|
116
|
+
is_sproc: bool = False,
|
|
117
|
+
statement_params: dict[str, str] | None = None,
|
|
118
|
+
max_workers: int | None = None,
|
|
119
|
+
) -> pl.DataFrame:
|
|
120
|
+
"""COPY INTO Parquet, read the staged files in parallel, return a polars DataFrame.
|
|
121
|
+
|
|
122
|
+
Backs ``to_polars(transport="parquet")``. Subject to the Parquet type-fidelity
|
|
123
|
+
caveats documented on ``DataFrame.to_polars``.
|
|
124
|
+
"""
|
|
125
|
+
import polars as pl
|
|
126
|
+
|
|
127
|
+
paths = _copy_df_to_stage(df, "to_polars_parquet_eager", statement_params)
|
|
128
|
+
if not paths:
|
|
129
|
+
return _empty_frame_from_schema(df, statement_params)
|
|
130
|
+
frames = _open_stage_files_parallel(
|
|
131
|
+
df._session, paths, is_sproc, max_workers=max_workers
|
|
132
|
+
)
|
|
133
|
+
if not frames:
|
|
134
|
+
return _empty_frame_from_schema(df, statement_params)
|
|
135
|
+
return pl.concat(frames) if len(frames) > 1 else frames[0]
|