snowflake-snowpark-python 1.52.0__tar.gz → 1.53.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (243) hide show
  1. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/CHANGELOG.md +25 -0
  2. {snowflake_snowpark_python-1.52.0/src/snowflake_snowpark_python.egg-info → snowflake_snowpark_python-1.53.0}/PKG-INFO +6 -2
  3. snowflake_snowpark_python-1.53.0/pyproject.toml +13 -0
  4. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/setup.py +7 -1
  5. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/analyzer_utils.py +158 -29
  6. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/select_statement.py +30 -4
  7. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/snowflake_plan.py +15 -3
  8. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/snowflake_plan_node.py +3 -1
  9. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/base_dialect.py +8 -4
  10. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/databricks_dialect.py +8 -8
  11. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/mysql_dialect.py +8 -8
  12. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/oracledb_dialect.py +8 -8
  13. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/postgresql_dialect.py +16 -11
  14. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/sqlserver_dialect.py +4 -4
  15. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/type_utils.py +120 -3
  16. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/utils.py +204 -10
  17. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/dataframe_reader.py +143 -10
  18. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/functions.py +129 -18
  19. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/lineage.py +9 -2
  20. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/session.py +11 -4
  21. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/table.py +37 -4
  22. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/version.py +1 -1
  23. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0/src/snowflake_snowpark_python.egg-info}/PKG-INFO +6 -2
  24. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake_snowpark_python.egg-info/requires.txt +9 -1
  25. snowflake_snowpark_python-1.52.0/pyproject.toml +0 -7
  26. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/LICENSE.txt +0 -0
  27. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/MANIFEST.in +0 -0
  28. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/README.md +0 -0
  29. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/setup.cfg +0 -0
  30. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/__init__.py +0 -0
  31. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_functions/__init__.py +0 -0
  32. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_functions/general_functions.py +0 -0
  33. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_functions/scalar_functions.py +0 -0
  34. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/__init__.py +0 -0
  35. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/__init__.py +0 -0
  36. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/analyzer.py +0 -0
  37. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/binary_expression.py +0 -0
  38. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/binary_plan_node.py +0 -0
  39. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/datatype_mapper.py +0 -0
  40. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/expression.py +0 -0
  41. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/grouping_set.py +0 -0
  42. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/metadata_utils.py +0 -0
  43. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/query_plan_analysis_utils.py +0 -0
  44. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/schema_utils.py +0 -0
  45. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/sort_expression.py +0 -0
  46. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/table_function.py +0 -0
  47. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/table_merge_expression.py +0 -0
  48. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/unary_expression.py +0 -0
  49. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/unary_plan_node.py +0 -0
  50. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/analyzer/window_expression.py +0 -0
  51. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/ast/__init__.py +0 -0
  52. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/ast/batch.py +0 -0
  53. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/ast/builder.py +0 -0
  54. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/ast/utils.py +0 -0
  55. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/code_generation.py +0 -0
  56. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/compiler/__init__.py +0 -0
  57. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/compiler/cte_utils.py +0 -0
  58. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/compiler/large_query_breakdown.py +0 -0
  59. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/compiler/plan_compiler.py +0 -0
  60. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/compiler/query_generator.py +0 -0
  61. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/compiler/repeated_subquery_elimination.py +0 -0
  62. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/compiler/telemetry_constants.py +0 -0
  63. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/compiler/utils.py +0 -0
  64. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/__init__.py +0 -0
  65. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/datasource_partitioner.py +0 -0
  66. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/datasource_reader.py +0 -0
  67. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/datasource_typing.py +0 -0
  68. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/__init__.py +0 -0
  69. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/dbms_dialects/sqlite3_dialect.py +0 -0
  70. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/drivers/__init__.py +0 -0
  71. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/drivers/base_driver.py +0 -0
  72. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/drivers/databricks_driver.py +0 -0
  73. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/drivers/oracledb_driver.py +0 -0
  74. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/drivers/psycopg2_driver.py +0 -0
  75. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/drivers/pymsql_driver.py +0 -0
  76. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/drivers/pyodbc_driver.py +0 -0
  77. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/drivers/sqlite_driver.py +0 -0
  78. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/jdbc.py +0 -0
  79. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/data_source/utils.py +0 -0
  80. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/debug_utils.py +0 -0
  81. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/error_message.py +0 -0
  82. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/event_table_telemetry.py +0 -0
  83. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/open_telemetry.py +0 -0
  84. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/packaging_utils.py +0 -0
  85. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/proto/generated/__init__.py +0 -0
  86. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/proto/generated/ast_pb2.py +0 -0
  87. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/proto/generated/ast_pb2.pyi +0 -0
  88. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/select_projection_complexity_utils.py +0 -0
  89. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/server_connection.py +0 -0
  90. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/snowpark_profiler.py +0 -0
  91. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/telemetry.py +0 -0
  92. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/temp_table_auto_cleaner.py +0 -0
  93. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/udf_utils.py +0 -0
  94. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/xml_reader.py +0 -0
  95. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/xml_schema_inference.py +0 -0
  96. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/_internal/xpath_handlers.py +0 -0
  97. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/async_job.py +0 -0
  98. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/catalog.py +0 -0
  99. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/column.py +0 -0
  100. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/context.py +0 -0
  101. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/dataframe.py +0 -0
  102. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/dataframe_ai_functions.py +0 -0
  103. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/dataframe_analytics_functions.py +0 -0
  104. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/dataframe_na_functions.py +0 -0
  105. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/dataframe_profiler.py +0 -0
  106. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/dataframe_stat_functions.py +0 -0
  107. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/dataframe_writer.py +0 -0
  108. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/exceptions.py +0 -0
  109. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/file_operation.py +0 -0
  110. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/files.py +0 -0
  111. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/__init__.py +0 -0
  112. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_analyzer.py +0 -0
  113. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_connection.py +0 -0
  114. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_constants.py +0 -0
  115. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_functions.py +0 -0
  116. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_nop_analyzer.py +0 -0
  117. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_nop_connection.py +0 -0
  118. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_nop_plan.py +0 -0
  119. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_options.py +0 -0
  120. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_pandas_util.py +0 -0
  121. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_plan.py +0 -0
  122. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_plan_builder.py +0 -0
  123. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_select_statement.py +0 -0
  124. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_snowflake_data_type.py +0 -0
  125. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_snowflake_to_pandas_converter.py +0 -0
  126. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_stage_registry.py +0 -0
  127. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_stored_procedure.py +0 -0
  128. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_telemetry.py +0 -0
  129. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_udaf.py +0 -0
  130. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_udf.py +0 -0
  131. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_udf_utils.py +0 -0
  132. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_udtf.py +0 -0
  133. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_util.py +0 -0
  134. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/_window_utils.py +0 -0
  135. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/mock/exceptions.py +0 -0
  136. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/__init__.py +0 -0
  137. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/config/__init__.py +0 -0
  138. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/config/__main__.py +0 -0
  139. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/config/envvars.py +0 -0
  140. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/config/pubsub.py +0 -0
  141. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/conftest.py +0 -0
  142. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/__init__.py +0 -0
  143. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/__init__.py +0 -0
  144. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/aggregation_utils.py +0 -0
  145. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/align_utils.py +0 -0
  146. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/apply_utils.py +0 -0
  147. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/binary_op_utils.py +0 -0
  148. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/concat_utils.py +0 -0
  149. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/cumulative_utils.py +0 -0
  150. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/cut_utils.py +0 -0
  151. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/frame.py +0 -0
  152. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/generator_utils.py +0 -0
  153. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/get_dummies_utils.py +0 -0
  154. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/groupby_utils.py +0 -0
  155. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/indexing_utils.py +0 -0
  156. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/io_utils.py +0 -0
  157. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/isin_utils.py +0 -0
  158. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/join_utils.py +0 -0
  159. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/ordered_dataframe.py +0 -0
  160. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/pivot_utils.py +0 -0
  161. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/resample_utils.py +0 -0
  162. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/row_count_estimation.py +0 -0
  163. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/session.py +0 -0
  164. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/snowpark_pandas_types.py +0 -0
  165. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/statement_params_constants.py +0 -0
  166. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/telemetry.py +0 -0
  167. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/timestamp_utils.py +0 -0
  168. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/transpose_utils.py +0 -0
  169. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/type_utils.py +0 -0
  170. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/unpivot_utils.py +0 -0
  171. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/utils.py +0 -0
  172. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/where_utils.py +0 -0
  173. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_internal/window_utils.py +0 -0
  174. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/_typing.py +0 -0
  175. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/compiler/__init__.py +0 -0
  176. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/compiler/doc_utils.py +0 -0
  177. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/compiler/ray_utils.py +0 -0
  178. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/compiler/snowflake_query_compiler.py +0 -0
  179. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/docstrings/__init__.py +0 -0
  180. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/docstrings/base.py +0 -0
  181. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/docstrings/dataframe.py +0 -0
  182. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/docstrings/datetime_index.py +0 -0
  183. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/docstrings/general.py +0 -0
  184. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/docstrings/groupby.py +0 -0
  185. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/docstrings/index.py +0 -0
  186. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/docstrings/io.py +0 -0
  187. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/docstrings/resample.py +0 -0
  188. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/docstrings/series.py +0 -0
  189. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/docstrings/series_utils.py +0 -0
  190. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/docstrings/shared_docs.py +0 -0
  191. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/docstrings/timedelta_index.py +0 -0
  192. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/docstrings/window.py +0 -0
  193. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/__init__.py +0 -0
  194. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/base_overrides.py +0 -0
  195. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/dataframe_extensions.py +0 -0
  196. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/dataframe_groupby_overrides.py +0 -0
  197. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/dataframe_overrides.py +0 -0
  198. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/datetime_index.py +0 -0
  199. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/general_overrides.py +0 -0
  200. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/index.py +0 -0
  201. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/indexing_overrides.py +0 -0
  202. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/io_overrides.py +0 -0
  203. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/pd_extensions.py +0 -0
  204. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/resample_overrides.py +0 -0
  205. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/resampler_groupby_overrides.py +0 -0
  206. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/rolling_groupby_overrides.py +0 -0
  207. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/series_extensions.py +0 -0
  208. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/series_groupby_overrides.py +0 -0
  209. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/series_overrides.py +0 -0
  210. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/snow_partition_iterator.py +0 -0
  211. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/timedelta_index.py +0 -0
  212. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/utils.py +0 -0
  213. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/extensions/window_overrides.py +0 -0
  214. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/io/__init__.py +0 -0
  215. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/io/factories.py +0 -0
  216. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/io/snow_io.py +0 -0
  217. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/utils/__init__.py +0 -0
  218. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/utils/error_message.py +0 -0
  219. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/utils/exceptions.py +0 -0
  220. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/utils/frontend_constants.py +0 -0
  221. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/utils/numpy_to_pandas.py +0 -0
  222. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/plugin/utils/warning_message.py +0 -0
  223. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/modin/utils.py +0 -0
  224. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/py.typed +0 -0
  225. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/query_history.py +0 -0
  226. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/relational_grouped_dataframe.py +0 -0
  227. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/row.py +0 -0
  228. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/secrets.py +0 -0
  229. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/stored_procedure.py +0 -0
  230. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/stored_procedure_profiler.py +0 -0
  231. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/table_function.py +0 -0
  232. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/testing.py +0 -0
  233. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/types.py +0 -0
  234. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/udaf.py +0 -0
  235. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/udf.py +0 -0
  236. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/udf_profiler.py +0 -0
  237. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/udtf.py +0 -0
  238. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake/snowpark/window.py +0 -0
  239. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake_snowpark_python.egg-info/SOURCES.txt +0 -0
  240. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake_snowpark_python.egg-info/dependency_links.txt +0 -0
  241. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake_snowpark_python.egg-info/namespace_packages.txt +0 -0
  242. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake_snowpark_python.egg-info/not-zip-safe +0 -0
  243. {snowflake_snowpark_python-1.52.0 → snowflake_snowpark_python-1.53.0}/src/snowflake_snowpark_python.egg-info/top_level.txt +0 -0
@@ -1,5 +1,29 @@
1
1
  # Release History
2
2
 
3
+ ## 1.53.0 (2026-07-09)
4
+
5
+ ### Snowpark Python API Updates
6
+
7
+ #### New Features
8
+
9
+ - Added the `udf_init_once` decorator in `snowflake.snowpark.functions` for marking functions to be executed once during pre-fork initialization on Snowflake workers, matching the server-side `_snowflake.udf_init_once` API.
10
+
11
+ #### Bug Fixes
12
+
13
+ - Fixed a bug where stage paths and file format names that contain single quotes were not consistently escaped when generating SQL, which could produce malformed statements. This affects `INFER_SCHEMA` (used by `DataFrameReader.csv`/`json`/`parquet`/`orc`/`avro`) and `COPY FILES` (used by `FileOperation.copy_files`).
14
+ - Fixed a bug where single quotes and backslashes in stage/file paths were not correctly escaped when generating `COPY INTO` / `PUT` / `GET` SQL, which could produce malformed statements. This affects `DataFrame.write.csv`/`copy_into_location` and the Snowpark-pandas `DataFrame.to_csv` stage path.
15
+ - Fixed a bug where column names containing quote characters returned by an external database were not correctly escaped when generating the `SELECT` query for `DataFrameReader.dbapi`, which could produce malformed SQL. Embedded quote characters in identifiers are now doubled (backticks for Databricks/MySQL, double quotes for Oracle/PostgreSQL/SQL Server).
16
+ - Fixed a bug where the destination passed to `DataFrameWriter.copy_into_location` (and `csv`/`json`/`parquet`/`save`) was embedded into the generated `COPY INTO` statement without quoting, which could produce malformed SQL for locations containing single quotes. The location is now consistently quoted and escaped, and a string that merely starts and ends with a single quote but contains unescaped interior quotes is no longer treated as an already-quoted literal; it is fully escaped so it stays a single SQL string literal.
17
+ - Fixed a bug where UDF default argument values reconstructed from a source file in `register_from_file` were evaluated with `eval()`; they are now evaluated only against the documented set of supported default-value types, and unsupported expressions are ignored.
18
+ - Fixed a bug where `object_name`, `object_domain`, or `object_version` values containing single quotes or backslashes in `session.lineage.trace()` caused incorrect SQL generation. These values are now properly escaped before being embedded in the `SYSTEM$DGQL` call.
19
+ - Fixed a bug where single quotes and backslashes in `comment` (`create_or_replace_view` / dynamic table / `save_as_table`), collation specs (`Column.collate`), VARIANT/OBJECT subfield keys (`Column[...]`), and `DataFrame`/`Session.flatten` paths were not correctly escaped when generating SQL, which could produce malformed statements. Backslash sequences (e.g. `\t`, `\n`) in these values are now applied literally rather than interpreted.
20
+ - Fixed a bug where string values in the AI functions (`ai_extract`, `ai_classify`, `ai_similarity`, `ai_parse_document`, `ai_transcribe`, `ai_complete`) configuration and `response_format` were not correctly escaped when generating the SQL object literal, which could produce malformed statements when a value contained single quotes or backslashes (for example, an apostrophe in a natural-language question).
21
+
22
+ #### Dependency Updates
23
+
24
+ - Lifted `protobuf` restriction for Python 3.14 from `==5.29.3` to `>=5.29.3,<6.34`.
25
+ - Capped `pandas` to `<3.0.0` for the `[pandas]` install extra, as Snowpark Python pandas-related features may not be fully compatible with pandas 3.0 or later.
26
+
3
27
  ## 1.52.0 (2026-06-10)
4
28
 
5
29
  ### Snowpark Python API Updates
@@ -17,6 +41,7 @@
17
41
  #### Improvements
18
42
 
19
43
  - Improved CTE optimization to deduplicate identical subtrees in self-joins, which were previously emitted as repeated subqueries.
44
+ - Reduced the size of generated query text for repeated join operations.
20
45
 
21
46
  #### Deprecations
22
47
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: snowflake-snowpark-python
3
- Version: 1.52.0
3
+ Version: 1.53.0
4
4
  Summary: Snowflake Snowpark for Python
5
5
  Home-page: https://www.snowflake.com/
6
6
  Author: Snowflake, Inc
@@ -41,13 +41,16 @@ Requires-Dist: snowflake-connector-python<5.0.0,>=3.17.0
41
41
  Requires-Dist: typing-extensions<5.0.0,>=4.1.0
42
42
  Requires-Dist: pyyaml
43
43
  Requires-Dist: cloudpickle!=2.1.0,!=2.2.0,<=3.1.1,>=1.6.0
44
- Requires-Dist: protobuf<6.34,>=3.20
44
+ Requires-Dist: protobuf<6.34,>=3.20; python_version < "3.14"
45
+ Requires-Dist: protobuf<6.34,>=5.29.0; python_version >= "3.14"
45
46
  Requires-Dist: python-dateutil
46
47
  Requires-Dist: tzlocal
47
48
  Provides-Extra: pandas
48
49
  Requires-Dist: snowflake-connector-python[pandas]<5.0.0,>=3.17.0; extra == "pandas"
50
+ Requires-Dist: pandas<3.0.0; extra == "pandas"
49
51
  Provides-Extra: modin
50
52
  Requires-Dist: snowflake-connector-python[pandas]<5.0.0,>=3.17.0; extra == "modin"
53
+ Requires-Dist: pandas<3.0.0; extra == "modin"
51
54
  Requires-Dist: modin<0.38.0,>=0.36.0; extra == "modin"
52
55
  Requires-Dist: pandas<=2.4; extra == "modin"
53
56
  Requires-Dist: tqdm; extra == "modin"
@@ -76,6 +79,7 @@ Requires-Dist: lxml; extra == "development"
76
79
  Requires-Dist: pyarrow; extra == "development"
77
80
  Provides-Extra: modin-development
78
81
  Requires-Dist: snowflake-connector-python[pandas]<5.0.0,>=3.17.0; extra == "modin-development"
82
+ Requires-Dist: pandas<3.0.0; extra == "modin-development"
79
83
  Requires-Dist: modin<0.38.0,>=0.36.0; extra == "modin-development"
80
84
  Requires-Dist: pandas<=2.4; extra == "modin-development"
81
85
  Requires-Dist: tqdm; extra == "modin-development"
@@ -0,0 +1,13 @@
1
+ [build-system]
2
+ requires = [
3
+ "setuptools",
4
+ # py>=3.14: protoc-wheel-0 has no cp314 wheel on PyPI, so it cannot be installed
5
+ # in pip's build isolation venv. setup.py falls back to shutil.which("protoc").
6
+ "protoc-wheel-0==21.1; python_version < '3.14'", # Protocol buffer compiler for Snowpark IR
7
+ # py>=3.14: pin <=3.6.0 so the build isolation venv does not install mypy-protobuf 5.x,
8
+ # whose extensions_pb2.py was generated with protobuf 6.x gencode and fails at import
9
+ # time when the isolated venv resolves protobuf 5.x (Snowflake internal channel).
10
+ "mypy-protobuf<=3.6.0; python_version >= '3.14'",
11
+ "mypy-protobuf; python_version < '3.14'", # used in generating typed Python code from protobuf for Snowpark IR
12
+ ]
13
+ build-backend = "setuptools.build_meta"
@@ -28,7 +28,12 @@ INSTALL_REQ_LIST = [
28
28
  "pyyaml",
29
29
  "cloudpickle>=1.6.0,<=3.1.1,!=2.1.0,!=2.2.0",
30
30
  # `protoc` < 3.20 is not able to generate protobuf code compatible with protobuf >= 3.20.
31
- "protobuf>=3.20, <6.34", # Snowpark IR
31
+ "protobuf>=3.20, <6.34; python_version < '3.14'", # Snowpark IR
32
+ # py314: protoc-wheel-0 has no cp314 wheel; setup.py uses libprotobuf's protoc from PATH.
33
+ # The pre-generated ast_pb2.py in the tarball has no ValidateProtobufRuntimeVersion call
34
+ # (built with protoc 3.21), so 5.29.0+ is sufficient. Conda recipes may regenerate with
35
+ # a different protoc version and override this constraint via their run deps.
36
+ "protobuf>=5.29.0,<6.34; python_version >= '3.14'", # Snowpark IR
32
37
  "python-dateutil", # Snowpark IR
33
38
  "tzlocal", # Snowpark IR
34
39
  ]
@@ -39,6 +44,7 @@ if os.getenv("SNOWFLAKE_IS_PYTHON_RUNTIME_TEST", False):
39
44
 
40
45
  PANDAS_REQUIREMENTS = [
41
46
  f"snowflake-connector-python[pandas]{CONNECTOR_DEPENDENCY_VERSION}",
47
+ "pandas<3.0.0",
42
48
  ]
43
49
  MODIN_REQUIREMENTS = [
44
50
  *PANDAS_REQUIREMENTS,
@@ -6,6 +6,7 @@
6
6
  import json
7
7
  import math
8
8
  import os
9
+ import re
9
10
  import tempfile
10
11
  from typing import Any, Dict, List, Optional, Tuple, Union, Literal, Sequence
11
12
 
@@ -40,7 +41,8 @@ from snowflake.snowpark._internal.utils import (
40
41
  EMPTY_STRING,
41
42
  TempObjectType,
42
43
  escape_quotes,
43
- escape_single_quotes,
44
+ escape_quotes_and_backslashes,
45
+ escape_subfield_key,
44
46
  get_temp_type_for_object,
45
47
  is_single_quoted,
46
48
  is_sql_select_statement,
@@ -402,7 +404,26 @@ def regexp_expression(expr: str, pattern: str, parameters: Optional[str] = None)
402
404
 
403
405
 
404
406
  def collate_expression(expr: str, collation_spec: str) -> str:
405
- return expr + COLLATE + single_quote(collation_spec)
407
+ # Escape the collation spec so a value containing single quotes or
408
+ # backslashes does not terminate the single-quoted literal early and produce
409
+ # invalid SQL.
410
+ #
411
+ # Preserve the historical behavior of single_quote(): a spec that is already
412
+ # wrapped in single quotes (e.g. "'en_US'") is treated as pre-quoted, so we
413
+ # strip the outer quotes, escape the interior, and re-wrap. An unquoted spec
414
+ # is escaped and wrapped. Specs (quoted or unquoted) with no interior quotes
415
+ # or backslashes therefore produce identical SQL to before.
416
+ if is_single_quoted(collation_spec):
417
+ inner = collation_spec[1:-1]
418
+ else:
419
+ inner = collation_spec
420
+ return (
421
+ expr
422
+ + COLLATE
423
+ + SINGLE_QUOTE
424
+ + escape_quotes_and_backslashes(inner)
425
+ + SINGLE_QUOTE
426
+ )
406
427
 
407
428
 
408
429
  def subfield_expression(expr: str, field: Union[str, int]) -> str:
@@ -410,7 +431,12 @@ def subfield_expression(expr: str, field: Union[str, int]) -> str:
410
431
  expr
411
432
  + LEFT_BRACKET
412
433
  + (
413
- SINGLE_QUOTE + field + SINGLE_QUOTE
434
+ # Escape the field so a VARIANT/OBJECT key containing single quotes
435
+ # or backslashes does not terminate the literal early. A key whose
436
+ # single quotes are already doubled is preserved unchanged (minus
437
+ # backslash normalization) to keep the historical "double your own
438
+ # quotes" contract non-breaking.
439
+ SINGLE_QUOTE + escape_subfield_key(field) + SINGLE_QUOTE
414
440
  if isinstance(field, str)
415
441
  else str(field)
416
442
  )
@@ -431,7 +457,10 @@ def flatten_expression(
431
457
  + PATH
432
458
  + RIGHT_ARROW
433
459
  + SINGLE_QUOTE
434
- + (path or EMPTY_STRING)
460
+ # Escape the JSON path so a value containing single quotes or
461
+ # backslashes does not terminate the literal early and produce invalid
462
+ # SQL in the FLATTEN argument list.
463
+ + (escape_quotes_and_backslashes(path) if path else EMPTY_STRING)
435
464
  + SINGLE_QUOTE
436
465
  + COMMA
437
466
  + OUTER
@@ -961,6 +990,33 @@ def lateral_join_statement(
961
990
  )
962
991
 
963
992
 
993
+ _SELECT_STAR_FROM_PREFIX = SELECT + STAR + NEW_LINE + FROM + LEFT_PARENTHESIS + NEW_LINE
994
+ _SELECT_STAR_FROM_SUFFIX = NEW_LINE + RIGHT_PARENTHESIS
995
+
996
+
997
+ def _unwrap_select_star_from(sql: str) -> Optional[str]:
998
+ """If sql is a join-produced `SELECT * FROM (\n<join_source>\n)` (the
999
+ output of project_statement([], join_source)), return <join_source>.
1000
+ Only unwraps when the inner content starts with '(' (possibly preceded
1001
+ by UUID trace comments) which indicates a parenthesized join operand
1002
+ rather than a wrapped SELECT statement."""
1003
+ if sql.startswith(_SELECT_STAR_FROM_PREFIX) and sql.endswith(
1004
+ _SELECT_STAR_FROM_SUFFIX
1005
+ ):
1006
+ inner = sql[len(_SELECT_STAR_FROM_PREFIX) : -len(_SELECT_STAR_FROM_SUFFIX)]
1007
+ # In trace-SQL mode, UUID comments (\n-- <uuid>\n) may precede the
1008
+ # opening parenthesis. Strip them before checking.
1009
+ check = inner.lstrip("\n")
1010
+ if check.startswith("--"):
1011
+ # Skip the comment line and any trailing newline
1012
+ newline_pos = check.find("\n")
1013
+ if newline_pos != -1:
1014
+ check = check[newline_pos + 1 :]
1015
+ if check.startswith(LEFT_PARENTHESIS) or inner.startswith(LEFT_PARENTHESIS):
1016
+ return inner
1017
+ return None
1018
+
1019
+
964
1020
  def snowflake_supported_join_statement(
965
1021
  left: str,
966
1022
  right: str,
@@ -971,17 +1027,30 @@ def snowflake_supported_join_statement(
971
1027
  left_uuid: Optional[str] = None,
972
1028
  right_uuid: Optional[str] = None,
973
1029
  directed: bool = False,
1030
+ left_is_join: bool = False,
974
1031
  ) -> str:
975
1032
  LEFT_UUID = format_uuid(left_uuid)
976
1033
  RIGHT_UUID = format_uuid(right_uuid)
977
- left_alias = (
978
- "SNOWPARK_LEFT"
979
- if use_constant_subquery_alias
980
- else random_name_for_temp_object(TempObjectType.TABLE)
981
- )
1034
+
1035
+ # If left is the output of a previous join, flatten into a multi-way join
1036
+ # by unwrapping the SELECT * FROM (...) envelope and appending the new
1037
+ # right operand directly to the existing join source. This avoids nested
1038
+ # SELECT * layers that inflate query text without changing semantics.
1039
+ #
1040
+ # Though it is technically less efficient than constructing the join sub-queries
1041
+ # without the SELECT in the first place, the structure of our SQL processing code
1042
+ # needs top-level projections to be wrapped by a select to be well-formed, so we
1043
+ # must strip it here instead.
1044
+ #
1045
+ # We only unwrap the left side because it is simpler to deal with than unwrapping
1046
+ # both left and right, and left-deep chains are more common, as they're produced
1047
+ # by calls like df1.join(df2).join(df3) etc.
1048
+ unwrapped_left = _unwrap_select_star_from(left) if left_is_join else None
982
1049
  right_alias = (
983
1050
  "SNOWPARK_RIGHT"
984
- if use_constant_subquery_alias
1051
+ if use_constant_subquery_alias and unwrapped_left is None
1052
+ # Multi-way join: right alias must be unique to avoid collisions
1053
+ # with aliases already present in the flattened join source.
985
1054
  else random_name_for_temp_object(TempObjectType.TABLE)
986
1055
  )
987
1056
 
@@ -1017,18 +1086,31 @@ def snowflake_supported_join_statement(
1017
1086
 
1018
1087
  maybe_directed_sql = DIRECTED_JOIN if directed else JOIN
1019
1088
 
1089
+ if unwrapped_left is not None:
1090
+ # No need for additional parentheses around the left expression here, since it
1091
+ # should already be parenthesized
1092
+ left_expr = LEFT_UUID + unwrapped_left + NEW_LINE + LEFT_UUID
1093
+ else:
1094
+ left_alias = (
1095
+ "SNOWPARK_LEFT"
1096
+ if use_constant_subquery_alias
1097
+ else random_name_for_temp_object(TempObjectType.TABLE)
1098
+ )
1099
+ left_expr = (
1100
+ LEFT_PARENTHESIS
1101
+ + NEW_LINE
1102
+ + LEFT_UUID
1103
+ + left
1104
+ + NEW_LINE
1105
+ + LEFT_UUID
1106
+ + RIGHT_PARENTHESIS
1107
+ + AS
1108
+ + left_alias
1109
+ + SPACE
1110
+ + NEW_LINE
1111
+ )
1020
1112
  source = (
1021
- LEFT_PARENTHESIS
1022
- + NEW_LINE
1023
- + LEFT_UUID
1024
- + left
1025
- + NEW_LINE
1026
- + LEFT_UUID
1027
- + RIGHT_PARENTHESIS
1028
- + AS
1029
- + left_alias
1030
- + SPACE
1031
- + NEW_LINE
1113
+ left_expr
1032
1114
  + join_sql
1033
1115
  + maybe_directed_sql
1034
1116
  + NEW_LINE
@@ -1060,6 +1142,7 @@ def join_statement(
1060
1142
  left_uuid: Optional[str] = None,
1061
1143
  right_uuid: Optional[str] = None,
1062
1144
  directed: bool = False,
1145
+ left_is_join: bool = False,
1063
1146
  ) -> str:
1064
1147
  if isinstance(join_type, (LeftSemi, LeftAnti)):
1065
1148
  return left_semi_or_anti_join_statement(
@@ -1087,12 +1170,18 @@ def join_statement(
1087
1170
  left_uuid=left_uuid,
1088
1171
  right_uuid=right_uuid,
1089
1172
  directed=directed,
1173
+ left_is_join=left_is_join,
1090
1174
  )
1091
1175
 
1092
1176
 
1093
1177
  def get_comment_sql(comment: Optional[str]) -> str:
1094
1178
  return (
1095
- COMMENT + EQUALS + SINGLE_QUOTE + escape_single_quotes(comment) + SINGLE_QUOTE
1179
+ COMMENT + EQUALS + SINGLE_QUOTE
1180
+ # Escape backslashes and single quotes so a comment containing those
1181
+ # characters does not terminate the single-quoted literal early and
1182
+ # produce invalid SQL. A comment with no backslash/quote is emitted
1183
+ # unchanged.
1184
+ + escape_quotes_and_backslashes(comment) + SINGLE_QUOTE
1096
1185
  if comment
1097
1186
  else EMPTY_STRING
1098
1187
  )
@@ -1316,13 +1405,11 @@ def infer_schema_statement(
1316
1405
  + LEFT_PARENTHESIS
1317
1406
  + LOCATION
1318
1407
  + RIGHT_ARROW
1319
- + (path if is_single_quoted(path) else SINGLE_QUOTE + path + SINGLE_QUOTE)
1408
+ + single_quote(path)
1320
1409
  + COMMA
1321
1410
  + FILE_FORMAT
1322
1411
  + RIGHT_ARROW
1323
- + SINGLE_QUOTE
1324
- + file_format_name
1325
- + SINGLE_QUOTE
1412
+ + single_quote(file_format_name)
1326
1413
  + (
1327
1414
  ", "
1328
1415
  + ", ".join(
@@ -1351,7 +1438,14 @@ def file_operation_statement(
1351
1438
  return f"{REMOVE}{stage_location}{get_options_statement(options)}"
1352
1439
  if command.lower() == "copy_files":
1353
1440
  # For COPY FILES, file_name stores the value of the source stage location or subquery (from a DataFrame)
1354
- return f"{COPY_FILES}{INTO}{stage_location}{FROM}{file_name}{get_options_statement(options)}"
1441
+ # Quote stage_location; file_name may be a subquery that must not be quoted
1442
+ quoted_target = single_quote(stage_location)
1443
+ # If file_name is a subquery (starts with '('), don't quote it
1444
+ if file_name.strip().startswith("("):
1445
+ source = file_name
1446
+ else:
1447
+ source = single_quote(file_name)
1448
+ return f"{COPY_FILES}{INTO}{quoted_target}{FROM}{source}{get_options_statement(options)}"
1355
1449
  raise ValueError(f"Unsupported file operation type {command}")
1356
1450
 
1357
1451
 
@@ -1871,7 +1965,7 @@ def copy_into_location(
1871
1965
  return (
1872
1966
  COPY
1873
1967
  + INTO
1874
- + stage_location
1968
+ + escape_location_literal(stage_location)
1875
1969
  + FROM
1876
1970
  + LEFT_PARENTHESIS
1877
1971
  + query
@@ -2079,12 +2173,47 @@ def table(content: str) -> str:
2079
2173
 
2080
2174
 
2081
2175
  def single_quote(value: str) -> str:
2082
- if value.startswith(SINGLE_QUOTE) and value.endswith(SINGLE_QUOTE):
2176
+ if is_single_quoted(value):
2083
2177
  return value
2084
2178
  else:
2179
+ # Double any embedded single quotes so the value stays a single literal
2180
+ value = value.replace("'", "''")
2085
2181
  return SINGLE_QUOTE + value + SINGLE_QUOTE
2086
2182
 
2087
2183
 
2184
+ # Matches a complete, well-formed single-quoted SQL literal. The three body
2185
+ # alternatives each start with a different character (non-quote/non-backslash,
2186
+ # ', \), so every input character fits exactly one branch -- the engine never
2187
+ # backtracks, giving linear-time matching even on adversarial input.
2188
+ # Matches: "'@stage/o''clock/'" (interior quote is doubled -> one literal)
2189
+ # No match: "'@x' UNION SELECT --'" (bare interior quote ends the literal early)
2190
+ _WELL_FORMED_SINGLE_QUOTED_LITERAL = re.compile(
2191
+ r"""
2192
+ ' # opening single quote
2193
+ ( # body: zero or more of...
2194
+ [^'\\] # any char that is neither a quote nor a backslash
2195
+ | '' # or a doubled (escaped) quote
2196
+ | \\. # or a backslash followed by any char (backslash escape)
2197
+ )*
2198
+ ' # closing single quote
2199
+ """,
2200
+ re.VERBOSE | re.DOTALL,
2201
+ )
2202
+
2203
+
2204
+ def escape_location_literal(value: str) -> str:
2205
+ """Return ``value`` as a single, well-formed single-quoted SQL literal.
2206
+
2207
+ Unlike :func:`single_quote`, a value that merely starts and ends with a
2208
+ single quote but contains unescaped interior quotes is treated as unquoted
2209
+ and fully escaped. This prevents a caller-controlled location from breaking
2210
+ out of the string literal in the generated ``COPY INTO`` statement.
2211
+ """
2212
+ if _WELL_FORMED_SINGLE_QUOTED_LITERAL.fullmatch(value):
2213
+ return value
2214
+ return SINGLE_QUOTE + value.replace("'", "''") + SINGLE_QUOTE
2215
+
2216
+
2088
2217
  def quote_name_without_upper_casing(name: str) -> str:
2089
2218
  return DOUBLE_QUOTE + escape_quotes(name) + DOUBLE_QUOTE
2090
2219
 
@@ -269,6 +269,7 @@ class Selectable(LogicalPlan, ABC):
269
269
  self.pre_actions: Optional[List["Query"]] = None
270
270
  self.post_actions: Optional[List["Query"]] = None
271
271
  self.flatten_disabled: bool = False
272
+ self.protect_dropped_new_columns: bool = False
272
273
  self._column_states: Optional[ColumnStateDict] = None
273
274
  self._snowflake_plan: Optional[SnowflakePlan] = None
274
275
  self.expr_to_alias = (
@@ -444,6 +445,19 @@ class Selectable(LogicalPlan, ABC):
444
445
  # Add the last df ast id to the snowflake plan as the most recent
445
446
  # dataframe operation to create this plan.
446
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
+ )
447
461
  return self._snowflake_plan
448
462
 
449
463
  @property
@@ -590,7 +604,11 @@ class SelectableEntity(Selectable):
590
604
  # Metadata/Attributes for the plan
591
605
  self._attributes: Optional[List[Attribute]] = None
592
606
  self.table_reference = self.entity.name
593
- if self.entity.time_travel_config is not None:
607
+ if self.entity.iceberg_changes_config is not None:
608
+ self.table_reference += (
609
+ self.entity.iceberg_changes_config.generate_sql_clause()
610
+ )
611
+ elif self.entity.time_travel_config is not None:
594
612
  self.table_reference += self.entity.time_travel_config.generate_sql_clause()
595
613
 
596
614
  def __deepcopy__(self, memodict={}) -> "SelectableEntity": # noqa: B006
@@ -1486,7 +1504,7 @@ class SelectStatement(Selectable):
1486
1504
  can_be_flattened = False
1487
1505
  else:
1488
1506
  can_be_flattened = can_select_statement_be_flattened(
1489
- self.column_states, new_column_states
1507
+ self.column_states, new_column_states, self.protect_dropped_new_columns
1490
1508
  )
1491
1509
 
1492
1510
  if can_be_flattened:
@@ -2183,7 +2201,9 @@ def parse_column_name(
2183
2201
 
2184
2202
 
2185
2203
  def can_select_statement_be_flattened(
2186
- subquery_column_states: ColumnStateDict, new_column_states: ColumnStateDict
2204
+ subquery_column_states: ColumnStateDict,
2205
+ new_column_states: ColumnStateDict,
2206
+ protect_dropped_new_columns: bool = False,
2187
2207
  ) -> bool:
2188
2208
  for col, state in new_column_states.items():
2189
2209
  dependent_columns = state.dependent_columns
@@ -2206,7 +2226,13 @@ def can_select_statement_be_flattened(
2206
2226
  state.change_state == ColumnChangeState.DROPPED
2207
2227
  and (subquery_state := subquery_column_states.get(col))
2208
2228
  and subquery_state.change_state == ColumnChangeState.NEW
2209
- and subquery_state.is_referenced_by_same_level_column
2229
+ and (
2230
+ subquery_state.is_referenced_by_same_level_column
2231
+ # If the subquery was explicitly marked (e.g. by the SCOS withColumn
2232
+ # path), preserve it so that future filter/sort clauses can still
2233
+ # reference the dropped NEW column.
2234
+ or protect_dropped_new_columns
2235
+ )
2210
2236
  ):
2211
2237
  return False
2212
2238
  return True
@@ -458,6 +458,7 @@ 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
461
462
  # We need to copy this list since we don't want to change it for the
462
463
  # previous SnowflakePlan objects
463
464
  self.api_calls = api_calls.copy() if api_calls else []
@@ -769,6 +770,7 @@ class SnowflakePlan(LogicalPlan):
769
770
  referenced_ctes=self.referenced_ctes,
770
771
  )
771
772
  plan.df_ast_ids = self.df_ast_ids
773
+ plan._is_join_output = self._is_join_output
772
774
  return plan
773
775
 
774
776
  def __deepcopy__(self, memodict={}) -> "SnowflakePlan": # noqa: B006
@@ -808,6 +810,7 @@ class SnowflakePlan(LogicalPlan):
808
810
  if copied_source_plan:
809
811
  copied_source_plan._is_valid_for_replacement = True
810
812
  copied_plan.df_ast_ids = self.df_ast_ids
813
+ copied_plan._is_join_output = self._is_join_output
811
814
 
812
815
  return copied_plan
813
816
 
@@ -1065,8 +1068,13 @@ class SnowflakePlanBuilder:
1065
1068
 
1066
1069
  def table(self, table_name: str, source_plan: LogicalPlan) -> SnowflakePlan:
1067
1070
  table_reference = table_name
1068
- if isinstance(source_plan, SnowflakeTable) and source_plan.time_travel_config:
1069
- table_reference += source_plan.time_travel_config.generate_sql_clause()
1071
+ if isinstance(source_plan, SnowflakeTable):
1072
+ if source_plan.iceberg_changes_config:
1073
+ table_reference += (
1074
+ source_plan.iceberg_changes_config.generate_sql_clause()
1075
+ )
1076
+ elif source_plan.time_travel_config:
1077
+ table_reference += source_plan.time_travel_config.generate_sql_clause()
1070
1078
 
1071
1079
  return self.query(project_statement([], table_reference), source_plan)
1072
1080
 
@@ -1231,7 +1239,8 @@ class SnowflakePlanBuilder:
1231
1239
  use_constant_subquery_alias: bool,
1232
1240
  directed: bool = False,
1233
1241
  ):
1234
- return self.build_binary(
1242
+ left_is_join = left._is_join_output
1243
+ result = self.build_binary(
1235
1244
  lambda x, y: join_statement(
1236
1245
  x,
1237
1246
  y,
@@ -1248,11 +1257,14 @@ class SnowflakePlanBuilder:
1248
1257
  else None
1249
1258
  ),
1250
1259
  directed=directed,
1260
+ left_is_join=left_is_join,
1251
1261
  ),
1252
1262
  left,
1253
1263
  right,
1254
1264
  source_plan,
1255
1265
  )
1266
+ result._is_join_output = True
1267
+ return result
1256
1268
 
1257
1269
  def save_as_table(
1258
1270
  self,
@@ -7,7 +7,7 @@ from collections.abc import Iterable
7
7
  from enum import Enum
8
8
  from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple
9
9
 
10
- from snowflake.snowpark._internal.utils import TimeTravelConfig
10
+ from snowflake.snowpark._internal.utils import IcebergChangesConfig, TimeTravelConfig
11
11
 
12
12
  from snowflake.snowpark._internal.analyzer.expression import Attribute, Expression
13
13
  from snowflake.snowpark._internal.analyzer.query_plan_analysis_utils import (
@@ -97,10 +97,12 @@ class SnowflakeTable(LeafNode):
97
97
  session: "Session",
98
98
  is_temp_table_for_cleanup: bool = False,
99
99
  time_travel_config: Optional[TimeTravelConfig] = None,
100
+ iceberg_changes_config: Optional[IcebergChangesConfig] = None,
100
101
  ) -> None:
101
102
  super().__init__()
102
103
  self.name = name
103
104
  self.time_travel_config = time_travel_config
105
+ self.iceberg_changes_config = iceberg_changes_config
104
106
  # When `is_temp_table_for_cleanup` is True, it's a temp table
105
107
  # generated by Snowpark (currently only df.cache_result) under the hood
106
108
  # and users are not aware of it.
@@ -10,6 +10,11 @@ QUERY_TEMPLATE = "SELECT {cols} FROM {table_or_query} {query_input_alias}"
10
10
 
11
11
 
12
12
  class BaseDialect:
13
+ @staticmethod
14
+ def _quote_backtick(name: str) -> str:
15
+ """Escape a backtick-quoted identifier: double any embedded backticks."""
16
+ return "`" + name.replace("`", "``") + "`"
17
+
13
18
  @staticmethod
14
19
  def generate_select_query(
15
20
  table_or_query: str,
@@ -20,12 +25,11 @@ class BaseDialect:
20
25
  ) -> str:
21
26
  cols = []
22
27
  for raw_field in raw_schema:
28
+ quoted_name = BaseDialect._quote_backtick(raw_field[0])
23
29
  if is_query:
24
- cols.append(
25
- f"""{query_input_alias}.`{raw_field[0]}` AS {raw_field[0]}"""
26
- )
30
+ cols.append(f"""{query_input_alias}.{quoted_name} AS {quoted_name}""")
27
31
  else:
28
- cols.append(raw_field[0])
32
+ cols.append(quoted_name)
29
33
 
30
34
  return QUERY_TEMPLATE.format(
31
35
  cols=", ".join(cols),
@@ -21,21 +21,21 @@ class DatabricksDialect(BaseDialect):
21
21
  ) -> str:
22
22
  cols = []
23
23
  for field, raw_field in zip(schema.fields, raw_schema):
24
+ quoted_name = self._quote_backtick(raw_field[0])
24
25
  field_name = (
25
- f"{query_input_alias}.`{raw_field[0]}`"
26
- if is_query
27
- else f"`{raw_field[0]}`"
26
+ f"{query_input_alias}.{quoted_name}" if is_query else quoted_name
28
27
  )
28
+ alias = quoted_name
29
29
  # databricks-sql-connector returns list of tuples for MapType
30
30
  # here we push down to-dict conversion to Databricks
31
31
  if isinstance(field.datatype, MapType):
32
- cols.append(f"""TO_JSON({field_name}) AS {raw_field[0]}""")
32
+ cols.append(f"""TO_JSON({field_name}) AS {alias}""")
33
33
  elif isinstance(field.datatype, BinaryType):
34
- cols.append(f"""HEX({field_name}) AS {raw_field[0]}""")
34
+ cols.append(f"""HEX({field_name}) AS {alias}""")
35
35
  else:
36
- cols.append(
37
- f"{field_name} AS {raw_field[0]}"
38
- ) if is_query else cols.append(field_name)
36
+ cols.append(f"{field_name} AS {alias}") if is_query else cols.append(
37
+ field_name
38
+ )
39
39
  return QUERY_TEMPLATE.format(
40
40
  cols=", ".join(cols),
41
41
  table_or_query=f"({table_or_query})" if is_query else table_or_query,
@@ -24,22 +24,22 @@ class MysqlDialect(BaseDialect):
24
24
  ) -> str:
25
25
  cols = []
26
26
  for field, raw_field in zip(schema.fields, raw_schema):
27
+ quoted_name = self._quote_backtick(raw_field[0])
27
28
  field_name = (
28
- f"{query_input_alias}.`{raw_field[0]}`"
29
- if is_query
30
- else f"`{raw_field[0]}`"
29
+ f"{query_input_alias}.{quoted_name}" if is_query else quoted_name
31
30
  )
31
+ alias = quoted_name
32
32
  if isinstance(field.datatype, TimeType):
33
- cols.append(f"""CAST({field_name} AS CHAR) AS {raw_field[0]}""")
33
+ cols.append(f"""CAST({field_name} AS CHAR) AS {alias}""")
34
34
  elif (
35
35
  isinstance(field.datatype, BinaryType)
36
36
  or raw_field[1] == PymysqlTypeCode.BIT
37
37
  ):
38
- cols.append(f"""HEX({field_name}) AS {raw_field[0]}""")
38
+ cols.append(f"""HEX({field_name}) AS {alias}""")
39
39
  else:
40
- cols.append(
41
- f"{field_name} AS {raw_field[0]}"
42
- ) if is_query else cols.append(field_name)
40
+ cols.append(f"{field_name} AS {alias}") if is_query else cols.append(
41
+ field_name
42
+ )
43
43
 
44
44
  return QUERY_TEMPLATE.format(
45
45
  cols=", ".join(cols),