snowflake-snowpark-python 1.54.0__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.54.0 → snowflake_snowpark_python-1.55.0}/CHANGELOG.md +28 -0
- {snowflake_snowpark_python-1.54.0/src/snowflake_snowpark_python.egg-info → snowflake_snowpark_python-1.55.0}/PKG-INFO +3 -1
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/setup.py +1 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/analyzer_utils.py +29 -2
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/datatype_mapper.py +44 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/select_statement.py +4 -2
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/snowflake_plan.py +6 -2
- snowflake_snowpark_python-1.55.0/src/snowflake/snowpark/_internal/polars_backend.py +135 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/proto/generated/ast_pb2.pyi +2 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/type_utils.py +6 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/udf_utils.py +15 -3
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/utils.py +23 -15
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/dataframe.py +115 -1
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/dataframe_ai_functions.py +66 -1
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/dataframe_writer.py +10 -9
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/functions.py +61 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_functions.py +6 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/compiler/snowflake_query_compiler.py +10 -3
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/session.py +0 -1
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/types.py +2 -2
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/version.py +1 -1
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0/src/snowflake_snowpark_python.egg-info}/PKG-INFO +3 -1
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake_snowpark_python.egg-info/SOURCES.txt +1 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake_snowpark_python.egg-info/requires.txt +2 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/LICENSE.txt +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/MANIFEST.in +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/README.md +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/pyproject.toml +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/setup.cfg +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/__init__.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_functions/__init__.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_functions/general_functions.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_functions/scalar_functions.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/__init__.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/__init__.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/analyzer.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/binary_expression.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/binary_plan_node.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/expression.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/grouping_set.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/metadata_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/query_plan_analysis_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/schema_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/snowflake_plan_node.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/sort_expression.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/table_function.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/table_merge_expression.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/unary_expression.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/unary_plan_node.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/analyzer/window_expression.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/ast/__init__.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/ast/batch.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/ast/builder.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/ast/utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/code_generation.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/compiler/__init__.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/compiler/cte_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/compiler/large_query_breakdown.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/compiler/plan_compiler.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/compiler/query_generator.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/compiler/repeated_subquery_elimination.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/compiler/telemetry_constants.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/compiler/utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/__init__.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/datasource_partitioner.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/datasource_reader.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/datasource_typing.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/__init__.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/base_dialect.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/databricks_dialect.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/mysql_dialect.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/oracledb_dialect.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/postgresql_dialect.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/sqlite3_dialect.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/sqlserver_dialect.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/drivers/__init__.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/drivers/base_driver.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/drivers/databricks_driver.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/drivers/oracledb_driver.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/drivers/psycopg2_driver.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/drivers/pymsql_driver.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/drivers/pyodbc_driver.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/drivers/sqlite_driver.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/jdbc.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/data_source/utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/debug_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/error_message.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/event_table_telemetry.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/open_telemetry.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/packaging_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/proto/generated/__init__.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/proto/generated/ast_pb2.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/select_projection_complexity_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/server_connection.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/snowpark_profiler.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/telemetry.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/temp_table_auto_cleaner.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/xml_reader.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/xml_schema_inference.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/_internal/xpath_handlers.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/async_job.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/catalog.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/column.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/context.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/dataframe_analytics_functions.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/dataframe_na_functions.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/dataframe_profiler.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/dataframe_reader.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/dataframe_stat_functions.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/exceptions.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/file_operation.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/files.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/lineage.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/__init__.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_analyzer.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_connection.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_constants.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_nop_analyzer.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_nop_connection.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_nop_plan.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_options.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_pandas_util.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_plan.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_plan_builder.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_select_statement.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_snowflake_data_type.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_snowflake_to_pandas_converter.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_stage_registry.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_stored_procedure.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_telemetry.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_udaf.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_udf.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_udf_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_udtf.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_util.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/_window_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/mock/exceptions.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/__init__.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/config/__init__.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/config/__main__.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/config/envvars.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/config/pubsub.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/conftest.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/__init__.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/__init__.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/aggregation_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/align_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/apply_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/binary_op_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/concat_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/cumulative_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/cut_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/frame.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/generator_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/get_dummies_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/groupby_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/indexing_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/io_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/isin_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/join_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/ordered_dataframe.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/pivot_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/resample_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/row_count_estimation.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/session.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/snowpark_pandas_types.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/statement_params_constants.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/telemetry.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/timestamp_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/transpose_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/type_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/unpivot_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/where_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_internal/window_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/_typing.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/compiler/__init__.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/compiler/doc_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/compiler/ray_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/docstrings/__init__.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/docstrings/base.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/docstrings/dataframe.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/docstrings/datetime_index.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/docstrings/general.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/docstrings/groupby.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/docstrings/index.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/docstrings/io.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/docstrings/resample.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/docstrings/series.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/docstrings/series_utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/docstrings/shared_docs.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/docstrings/timedelta_index.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/docstrings/window.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/__init__.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/base_overrides.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/dataframe_extensions.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/dataframe_groupby_overrides.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/dataframe_overrides.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/datetime_index.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/general_overrides.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/index.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/indexing_overrides.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/io_overrides.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/pd_extensions.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/resample_overrides.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/resampler_groupby_overrides.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/rolling_groupby_overrides.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/series_extensions.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/series_groupby_overrides.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/series_overrides.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/snow_partition_iterator.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/timedelta_index.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/extensions/window_overrides.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/io/__init__.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/io/factories.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/io/snow_io.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/utils/__init__.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/utils/error_message.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/utils/exceptions.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/utils/frontend_constants.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/utils/numpy_to_pandas.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/plugin/utils/warning_message.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/modin/utils.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/py.typed +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/query_history.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/relational_grouped_dataframe.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/row.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/secrets.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/stored_procedure.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/stored_procedure_profiler.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/table.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/table_function.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/testing.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/udaf.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/udf.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/udf_profiler.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/udtf.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake/snowpark/window.py +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake_snowpark_python.egg-info/dependency_links.txt +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake_snowpark_python.egg-info/namespace_packages.txt +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake_snowpark_python.egg-info/not-zip-safe +0 -0
- {snowflake_snowpark_python-1.54.0 → snowflake_snowpark_python-1.55.0}/src/snowflake_snowpark_python.egg-info/top_level.txt +0 -0
|
@@ -1,5 +1,33 @@
|
|
|
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
|
+
|
|
3
31
|
## 1.54.0 (2026-07-29)
|
|
4
32
|
|
|
5
33
|
### Snowpark Python API updates
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: snowflake-snowpark-python
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.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
|
|
@@ -1168,13 +1193,14 @@ def create_table_statement(
|
|
|
1168
1193
|
options_statement = get_options_statement(options)
|
|
1169
1194
|
|
|
1170
1195
|
partition_by_clause = iceberg_partition_clause(partition_exprs)
|
|
1196
|
+
table_properties_clause = iceberg_table_properties_clause(iceberg_config)
|
|
1171
1197
|
|
|
1172
1198
|
return (
|
|
1173
1199
|
f"{CREATE}{(OR + REPLACE) if replace else EMPTY_STRING}"
|
|
1174
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()} "
|
|
1175
1201
|
f"{ICEBERG if iceberg_options else EMPTY_STRING}{TABLE}{table_name}{(IF + NOT + EXISTS) if not replace and not error else EMPTY_STRING}"
|
|
1176
1202
|
f"{LEFT_PARENTHESIS}{schema}{RIGHT_PARENTHESIS}{partition_by_clause}{cluster_by_clause}"
|
|
1177
|
-
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}"
|
|
1178
1204
|
)
|
|
1179
1205
|
|
|
1180
1206
|
|
|
@@ -1259,13 +1285,14 @@ def create_table_as_select_statement(
|
|
|
1259
1285
|
options_statement = get_options_statement(options)
|
|
1260
1286
|
|
|
1261
1287
|
partition_by_clause = iceberg_partition_clause(partition_exprs)
|
|
1288
|
+
table_properties_clause = iceberg_table_properties_clause(iceberg_config)
|
|
1262
1289
|
|
|
1263
1290
|
return (
|
|
1264
1291
|
f"{CREATE}{OR + REPLACE if replace else EMPTY_STRING}"
|
|
1265
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()} "
|
|
1266
1293
|
f"{ICEBERG if iceberg_options else EMPTY_STRING}{TABLE}"
|
|
1267
1294
|
f"{IF + NOT + EXISTS if not replace and not error else EMPTY_STRING} "
|
|
1268
|
-
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}"
|
|
1269
1296
|
f"{COPY_GRANTS if copy_grants else EMPTY_STRING}{comment_sql} {AS}{project_statement([], child)}"
|
|
1270
1297
|
)
|
|
1271
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
|
|
|
@@ -592,8 +592,10 @@ class SelectableEntity(Selectable):
|
|
|
592
592
|
self._attributes: Optional[List[Attribute]] = None
|
|
593
593
|
self.table_reference = self.entity.name
|
|
594
594
|
if self.entity.iceberg_changes_config is not None:
|
|
595
|
-
self.table_reference
|
|
596
|
-
self.entity.iceberg_changes_config.
|
|
595
|
+
self.table_reference = (
|
|
596
|
+
self.entity.iceberg_changes_config.generate_table_reference(
|
|
597
|
+
self.entity.name
|
|
598
|
+
)
|
|
597
599
|
)
|
|
598
600
|
elif self.entity.time_travel_config is not None:
|
|
599
601
|
self.table_reference += self.entity.time_travel_config.generate_sql_clause()
|
|
@@ -1067,8 +1067,10 @@ class SnowflakePlanBuilder:
|
|
|
1067
1067
|
table_reference = table_name
|
|
1068
1068
|
if isinstance(source_plan, SnowflakeTable):
|
|
1069
1069
|
if source_plan.iceberg_changes_config:
|
|
1070
|
-
table_reference
|
|
1071
|
-
source_plan.iceberg_changes_config.
|
|
1070
|
+
table_reference = (
|
|
1071
|
+
source_plan.iceberg_changes_config.generate_table_reference(
|
|
1072
|
+
table_name
|
|
1073
|
+
)
|
|
1072
1074
|
)
|
|
1073
1075
|
elif source_plan.time_travel_config:
|
|
1074
1076
|
table_reference += source_plan.time_travel_config.generate_sql_clause()
|
|
@@ -1316,6 +1318,8 @@ class SnowflakePlanBuilder:
|
|
|
1316
1318
|
catalog_sync: optionally sets the catalog integration configured for Polaris Catalog
|
|
1317
1319
|
storage_serialization_policy: specifies the storage serialization policy for the table
|
|
1318
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.
|
|
1319
1323
|
table_exists: whether the table already exists in the database.
|
|
1320
1324
|
Only used for APPEND and TRUNCATE mode.
|
|
1321
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]
|
|
@@ -11413,6 +11413,7 @@ class WritePandas(_message.Message):
|
|
|
11413
11413
|
auto_create_table: _builtins.bool
|
|
11414
11414
|
compression: _builtins.str
|
|
11415
11415
|
create_temp_table: _builtins.bool
|
|
11416
|
+
"""Deprecated: use table_type instead."""
|
|
11416
11417
|
on_error: _builtins.str
|
|
11417
11418
|
overwrite: _builtins.bool
|
|
11418
11419
|
parallel: _builtins.int
|
|
@@ -11616,6 +11617,7 @@ class WriteTable(_message.Message):
|
|
|
11616
11617
|
column_order: _builtins.str
|
|
11617
11618
|
copy_grants: _builtins.bool
|
|
11618
11619
|
create_temp_table: _builtins.bool
|
|
11620
|
+
"""Deprecated: use table_type instead."""
|
|
11619
11621
|
table_type: _builtins.str
|
|
11620
11622
|
@_builtins.property
|
|
11621
11623
|
def change_tracking(self) -> _wrappers_pb2.BoolValue: ...
|
|
@@ -822,6 +822,10 @@ def python_type_str_to_object(
|
|
|
822
822
|
return datetime.time
|
|
823
823
|
elif tp_str == "datetime":
|
|
824
824
|
return datetime.datetime
|
|
825
|
+
elif tp_str == "timedelta":
|
|
826
|
+
return datetime.timedelta
|
|
827
|
+
elif tp_str == "YearMonthInterval":
|
|
828
|
+
return YearMonthInterval
|
|
825
829
|
# This check is to handle special case when stored procs are registered using
|
|
826
830
|
# register_from_file where type hints are read as strings and we don't know if
|
|
827
831
|
# the DataFrame is a snowflake.snowpark.DataFrame or not. Here, the assumption
|
|
@@ -851,6 +855,8 @@ def python_type_to_snow_type(
|
|
|
851
855
|
|
|
852
856
|
if tp is decimal.Decimal:
|
|
853
857
|
return DecimalType(38, 18), False
|
|
858
|
+
elif tp is datetime.timedelta:
|
|
859
|
+
return DayTimeIntervalType(), False
|
|
854
860
|
elif tp in PYTHON_TO_SNOW_TYPE_MAPPINGS:
|
|
855
861
|
return PYTHON_TO_SNOW_TYPE_MAPPINGS[tp](), False
|
|
856
862
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
# Copyright (c) 2012-2025 Snowflake Computing Inc. All rights reserved.
|
|
3
3
|
#
|
|
4
4
|
import collections.abc
|
|
5
|
+
import datetime
|
|
5
6
|
import inspect
|
|
6
7
|
import io
|
|
7
8
|
import os
|
|
@@ -31,7 +32,11 @@ from packaging.requirements import Requirement
|
|
|
31
32
|
import snowflake.snowpark
|
|
32
33
|
from snowflake.connector.options import installed_pandas, pandas
|
|
33
34
|
from snowflake.snowpark._internal import code_generation, type_utils
|
|
34
|
-
from snowflake.snowpark._internal.analyzer.datatype_mapper import
|
|
35
|
+
from snowflake.snowpark._internal.analyzer.datatype_mapper import (
|
|
36
|
+
to_sql,
|
|
37
|
+
to_sql_for_default_arg,
|
|
38
|
+
to_sql_no_cast,
|
|
39
|
+
)
|
|
35
40
|
from snowflake.snowpark._internal.telemetry import TelemetryField
|
|
36
41
|
from snowflake.snowpark._internal.type_utils import (
|
|
37
42
|
NoneType,
|
|
@@ -57,7 +62,12 @@ from snowflake.snowpark._internal.utils import (
|
|
|
57
62
|
validate_object_name,
|
|
58
63
|
warning,
|
|
59
64
|
)
|
|
60
|
-
from snowflake.snowpark.types import
|
|
65
|
+
from snowflake.snowpark.types import (
|
|
66
|
+
DataType,
|
|
67
|
+
DayTimeIntervalType,
|
|
68
|
+
StructField,
|
|
69
|
+
StructType,
|
|
70
|
+
)
|
|
61
71
|
from snowflake.snowpark.version import VERSION
|
|
62
72
|
from snowflake.snowpark.context import (
|
|
63
73
|
_ANACONDA_SHARED_REPOSITORY,
|
|
@@ -442,7 +452,7 @@ def get_opt_arg_defaults(
|
|
|
442
452
|
|
|
443
453
|
if num_optional_args != 0:
|
|
444
454
|
default_values_to_sql_str = [
|
|
445
|
-
|
|
455
|
+
to_sql_for_default_arg(value, datatype)
|
|
446
456
|
for value, datatype in zip(default_values, input_types_for_default_args)
|
|
447
457
|
]
|
|
448
458
|
else:
|
|
@@ -1728,6 +1738,8 @@ def generate_call_python_sp_sql(
|
|
|
1728
1738
|
sql_args.append(session._analyzer.analyze(arg._expression, {}))
|
|
1729
1739
|
elif "system$" in sproc_name.lower():
|
|
1730
1740
|
sql_args.append(to_sql_no_cast(arg, infer_type(arg)))
|
|
1741
|
+
elif isinstance(arg, datetime.timedelta):
|
|
1742
|
+
sql_args.append(to_sql(arg, DayTimeIntervalType()))
|
|
1731
1743
|
else:
|
|
1732
1744
|
sql_args.append(to_sql(arg, infer_type(arg)))
|
|
1733
1745
|
return f"CALL {sproc_name}({', '.join(sql_args)})"
|
|
@@ -2255,7 +2255,7 @@ class TimeTravelConfig(NamedTuple):
|
|
|
2255
2255
|
|
|
2256
2256
|
|
|
2257
2257
|
class IcebergChangesConfig(NamedTuple):
|
|
2258
|
-
"""Configuration for Iceberg incremental reads via
|
|
2258
|
+
"""Configuration for Iceberg incremental reads via ``SPARK_INCREMENTAL_READ``.
|
|
2259
2259
|
|
|
2260
2260
|
Spark Iceberg exposes incremental reads through::
|
|
2261
2261
|
|
|
@@ -2266,14 +2266,12 @@ class IcebergChangesConfig(NamedTuple):
|
|
|
2266
2266
|
|
|
2267
2267
|
Snowflake translates this to::
|
|
2268
2268
|
|
|
2269
|
-
SELECT * FROM
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
[ END (VERSION => S2) ]
|
|
2269
|
+
SELECT * FROM TABLE(
|
|
2270
|
+
SPARK_INCREMENTAL_READ('<table>', S1 [, S2])
|
|
2271
|
+
)
|
|
2273
2272
|
|
|
2274
|
-
When ``end_version`` is omitted,
|
|
2275
|
-
|
|
2276
|
-
generic ``CHANGES`` queries).
|
|
2273
|
+
When ``end_version`` is omitted, the third argument is omitted and
|
|
2274
|
+
Snowflake reads append-only changes through the current snapshot.
|
|
2277
2275
|
"""
|
|
2278
2276
|
|
|
2279
2277
|
start_version: int
|
|
@@ -2327,14 +2325,24 @@ class IcebergChangesConfig(NamedTuple):
|
|
|
2327
2325
|
start_version=start, end_version=end, information=info
|
|
2328
2326
|
)
|
|
2329
2327
|
|
|
2330
|
-
def
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
)
|
|
2328
|
+
def generate_table_reference(self, table_name: str) -> str:
|
|
2329
|
+
"""Return a ``TABLE(SPARK_INCREMENTAL_READ(...))`` source for *table_name*.
|
|
2330
|
+
|
|
2331
|
+
``SPARK_INCREMENTAL_READ`` takes the table as its first **VARCHAR**
|
|
2332
|
+
argument (not a SQL identifier), so we quote *table_name* with
|
|
2333
|
+
:func:`~snowflake.snowpark._internal.analyzer.datatype_mapper.str_to_sql`.
|
|
2334
|
+
The string is passed through unchanged from the Spark read path
|
|
2335
|
+
(``session.table(...)`` / ``DataFrameReader.load(...)``); callers that
|
|
2336
|
+
need a catalog-linked or multi-part name should supply the same FQN
|
|
2337
|
+
they would use in a ``CHANGES`` read (e.g. ``db.schema.table``).
|
|
2338
|
+
Snowflake resolves partial names inside the TVF using session context.
|
|
2339
|
+
"""
|
|
2340
|
+
from snowflake.snowpark._internal.analyzer.datatype_mapper import str_to_sql
|
|
2341
|
+
|
|
2342
|
+
args = f"{str_to_sql(table_name)}, {self.start_version}"
|
|
2335
2343
|
if self.end_version is not None:
|
|
2336
|
-
|
|
2337
|
-
return
|
|
2344
|
+
args += f", {self.end_version}"
|
|
2345
|
+
return f"TABLE(SPARK_INCREMENTAL_READ({args}))"
|
|
2338
2346
|
|
|
2339
2347
|
|
|
2340
2348
|
def get_line_numbers(
|
|
@@ -8,6 +8,7 @@ import datetime
|
|
|
8
8
|
import itertools
|
|
9
9
|
import random
|
|
10
10
|
import re
|
|
11
|
+
import typing
|
|
11
12
|
from collections import Counter
|
|
12
13
|
from decimal import Decimal
|
|
13
14
|
from functools import cached_property, reduce
|
|
@@ -161,6 +162,7 @@ from snowflake.snowpark._internal.utils import (
|
|
|
161
162
|
experimental,
|
|
162
163
|
generate_random_alphanumeric,
|
|
163
164
|
get_copy_into_table_options,
|
|
165
|
+
is_in_stored_procedure,
|
|
164
166
|
is_snowflake_quoted_id_case_insensitive,
|
|
165
167
|
is_snowflake_unquoted_suffix_case_insensitive,
|
|
166
168
|
is_sql_select_statement,
|
|
@@ -238,6 +240,7 @@ from collections.abc import Iterable
|
|
|
238
240
|
|
|
239
241
|
if TYPE_CHECKING:
|
|
240
242
|
import modin.pandas # pragma: no cover
|
|
243
|
+
import polars # pragma: no cover
|
|
241
244
|
from table import Table # pragma: no cover
|
|
242
245
|
|
|
243
246
|
_logger = getLogger(__name__)
|
|
@@ -1371,6 +1374,117 @@ class DataFrame:
|
|
|
1371
1374
|
**kwargs,
|
|
1372
1375
|
)
|
|
1373
1376
|
|
|
1377
|
+
@experimental(version="1.55.0")
|
|
1378
|
+
@df_collect_api_telemetry
|
|
1379
|
+
@publicapi
|
|
1380
|
+
def to_polars(
|
|
1381
|
+
self,
|
|
1382
|
+
*,
|
|
1383
|
+
transport: typing.Literal["arrow", "parquet"] = "arrow",
|
|
1384
|
+
max_workers: Optional[int] = None,
|
|
1385
|
+
statement_params: Optional[Dict[str, str]] = None,
|
|
1386
|
+
) -> "polars.DataFrame":
|
|
1387
|
+
"""
|
|
1388
|
+
Executes the query representing this DataFrame and returns the result
|
|
1389
|
+
as a `Polars DataFrame <https://docs.pola.rs/py-polars/html/reference/dataframe/index.html>`_.
|
|
1390
|
+
|
|
1391
|
+
The transport is selected by ``transport``:
|
|
1392
|
+
|
|
1393
|
+
========== ============================================
|
|
1394
|
+
transport Description
|
|
1395
|
+
========== ============================================
|
|
1396
|
+
"arrow" Arrow (default; full Snowflake type fidelity)
|
|
1397
|
+
"parquet" Parquet unload + eager parallel read
|
|
1398
|
+
========== ============================================
|
|
1399
|
+
|
|
1400
|
+
Usage Notes:
|
|
1401
|
+
- **Transport selection**:
|
|
1402
|
+
- ``"parquet"``:
|
|
1403
|
+
Recommended when the result set is large and the type-fidelity
|
|
1404
|
+
caveats are acceptable. Snowflake's ``COPY INTO`` splits the
|
|
1405
|
+
result into multiple Parquet files that are opened and read
|
|
1406
|
+
concurrently. In server-side environments such as stored
|
|
1407
|
+
procedures, each file open is a parallelizable I/O operation,
|
|
1408
|
+
so the concurrent access substantially reduces wall-clock time
|
|
1409
|
+
compared to the Arrow path. On a local client, connection
|
|
1410
|
+
bandwidth is the primary constraint, and the benefit is more
|
|
1411
|
+
modest; for small or medium result sets the ``COPY INTO``
|
|
1412
|
+
setup cost may outweigh the gain, making Arrow the more
|
|
1413
|
+
efficient choice.
|
|
1414
|
+
- ``"arrow"`` (default):
|
|
1415
|
+
Streams result batches directly from the cursor without
|
|
1416
|
+
staging to disk. Preserves full Snowflake type fidelity.
|
|
1417
|
+
Use when type accuracy is required, or when the result set is
|
|
1418
|
+
small enough that the Parquet path's ``COPY INTO`` overhead
|
|
1419
|
+
is not justified.
|
|
1420
|
+
- **Parallelism tuning**: ``max_workers`` controls the thread pool
|
|
1421
|
+
for opening and reading staged Parquet files. Only applies to
|
|
1422
|
+
the ``"parquet"`` transport; ignored for ``"arrow"``. The default
|
|
1423
|
+
(``None``) defers to
|
|
1424
|
+
:class:`~concurrent.futures.ThreadPoolExecutor`.
|
|
1425
|
+
|
|
1426
|
+
Example::
|
|
1427
|
+
|
|
1428
|
+
>>> df = session.create_dataframe([[1, 2], [3, 4]], schema=["a", "b"])
|
|
1429
|
+
>>> df.to_polars().shape # doctest: +SKIP
|
|
1430
|
+
(2, 2)
|
|
1431
|
+
|
|
1432
|
+
Args:
|
|
1433
|
+
transport: Either ``"arrow"`` (default) or ``"parquet"``. When
|
|
1434
|
+
``"parquet"``, unload the result to Parquet on the session
|
|
1435
|
+
stage and read the files back in parallel. Can be faster than
|
|
1436
|
+
the ``"arrow"`` transport for large, data-transfer-dominated
|
|
1437
|
+
workloads — especially in a stored procedure — but subject to
|
|
1438
|
+
the type-fidelity limits below.
|
|
1439
|
+
max_workers: Maximum number of threads for parallel stage-file
|
|
1440
|
+
opens and reads. Only applies to the ``"parquet"`` transport
|
|
1441
|
+
(``transport="parquet"``). Defaults to ``None``.
|
|
1442
|
+
statement_params: Dictionary of statement level parameters to be
|
|
1443
|
+
set while executing this action.
|
|
1444
|
+
|
|
1445
|
+
Note:
|
|
1446
|
+
1. Requires ``polars>=1.0``.
|
|
1447
|
+
|
|
1448
|
+
2. The ``"parquet"`` transport
|
|
1449
|
+
does not fully preserve Snowflake types because ``COPY INTO``
|
|
1450
|
+
has restrictions on Parquet unload:
|
|
1451
|
+
|
|
1452
|
+
- ``TIMESTAMP_LTZ`` and ``TIMESTAMP_TZ`` columns cause the
|
|
1453
|
+
unload to error.
|
|
1454
|
+
- ``TIMESTAMP_NTZ`` values with nanosecond precision are
|
|
1455
|
+
truncated to milliseconds.
|
|
1456
|
+
- ``FLOAT`` (double) columns are downcast to ``float32``.
|
|
1457
|
+
|
|
1458
|
+
See the `COPY INTO <location> usage notes
|
|
1459
|
+
<https://docs.snowflake.com/en/sql-reference/sql/copy-into-location#usage-notes>`_
|
|
1460
|
+
for the full unload type mapping. Use the Arrow default when
|
|
1461
|
+
full type fidelity is required.
|
|
1462
|
+
"""
|
|
1463
|
+
from snowflake.snowpark._internal.polars_backend import (
|
|
1464
|
+
arrow_eager as _arrow_eager,
|
|
1465
|
+
parquet_eager as _parquet_eager,
|
|
1466
|
+
)
|
|
1467
|
+
|
|
1468
|
+
is_sproc = is_in_stored_procedure()
|
|
1469
|
+
normalized_transport = transport.strip().lower()
|
|
1470
|
+
|
|
1471
|
+
if normalized_transport == "parquet":
|
|
1472
|
+
return _parquet_eager(
|
|
1473
|
+
self,
|
|
1474
|
+
is_sproc=is_sproc,
|
|
1475
|
+
statement_params=statement_params,
|
|
1476
|
+
max_workers=max_workers,
|
|
1477
|
+
)
|
|
1478
|
+
elif normalized_transport == "arrow":
|
|
1479
|
+
return _arrow_eager(
|
|
1480
|
+
self,
|
|
1481
|
+
statement_params=statement_params,
|
|
1482
|
+
)
|
|
1483
|
+
raise ValueError(
|
|
1484
|
+
f"Unsupported transport {transport!r} for to_polars(). "
|
|
1485
|
+
'Expected "arrow" or "parquet".'
|
|
1486
|
+
)
|
|
1487
|
+
|
|
1374
1488
|
@df_api_usage
|
|
1375
1489
|
@publicapi
|
|
1376
1490
|
def to_df(
|
|
@@ -6512,7 +6626,7 @@ class DataFrame:
|
|
|
6512
6626
|
ast_id = self._ast_id
|
|
6513
6627
|
self._ast_id = None # set the AST ID to None to prevent AST emission.
|
|
6514
6628
|
self.write.save_as_table(
|
|
6515
|
-
temp_table_name,
|
|
6629
|
+
temp_table_name, table_type="temp", _emit_ast=False
|
|
6516
6630
|
)
|
|
6517
6631
|
self._ast_id = ast_id # restore the original AST ID.
|
|
6518
6632
|
else:
|