snowflake-snowpark-python 1.49.0__tar.gz → 1.50.1__tar.gz

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