|
30 | 30 | encode_node_id_with_query, |
31 | 31 | find_duplicate_subtrees, |
32 | 32 | ) |
| 33 | +from snowflake.snowpark._internal.compiler.repeated_subquery_elimination import ( |
| 34 | + RepeatedSubqueryElimination, |
| 35 | +) |
33 | 36 |
|
34 | 37 |
|
35 | 38 | def create_test_case1(): |
@@ -172,6 +175,43 @@ def stringify_dict(d: dict) -> str: |
172 | 175 | ) |
173 | 176 |
|
174 | 177 |
|
| 178 | +def test_has_alias_conflict(): |
| 179 | + # encode_query_id hashes expr_to_alias by alias values only, so two nodes can |
| 180 | + # share a CTE while carrying different expr_id keys. _has_alias_conflict guards |
| 181 | + # the only unsafe case: the same expr_id mapping to a *different* alias, where |
| 182 | + # merging would silently drop an entry and corrupt parent column resolution. |
| 183 | + has_conflict = RepeatedSubqueryElimination._has_alias_conflict |
| 184 | + |
| 185 | + node = SimpleNamespace(expr_to_alias={"uuid1": "ALIAS1"}) |
| 186 | + |
| 187 | + # No existing CTE yet (first occurrence) -> nothing to conflict with. |
| 188 | + assert has_conflict(node, None) is False |
| 189 | + |
| 190 | + # Same expr_id mapped to the same alias -> safe to merge. |
| 191 | + existing_same = SimpleNamespace(expr_to_alias={"uuid1": "ALIAS1"}) |
| 192 | + assert has_conflict(node, existing_same) is False |
| 193 | + |
| 194 | + # Disjoint expr_id keys (the normal self-join case: same alias values, fresh |
| 195 | + # UUIDs) -> no conflict, the entries simply coexist after merge. |
| 196 | + existing_disjoint = SimpleNamespace(expr_to_alias={"uuid2": "ALIAS1"}) |
| 197 | + assert has_conflict(node, existing_disjoint) is False |
| 198 | + |
| 199 | + # Same expr_id mapped to a *different* alias -> conflict, must not share CTE. |
| 200 | + existing_conflict = SimpleNamespace(expr_to_alias={"uuid1": "ALIAS2"}) |
| 201 | + assert has_conflict(node, existing_conflict) is True |
| 202 | + |
| 203 | + # A conflict on any one key is enough, even when other keys agree. |
| 204 | + node_multi = SimpleNamespace(expr_to_alias={"uuid1": "ALIAS1", "uuid2": "ALIAS2"}) |
| 205 | + existing_partial_conflict = SimpleNamespace( |
| 206 | + expr_to_alias={"uuid1": "ALIAS1", "uuid2": "DIFFERENT"} |
| 207 | + ) |
| 208 | + assert has_conflict(node_multi, existing_partial_conflict) is True |
| 209 | + |
| 210 | + # Node without any expr_to_alias entries can never conflict. |
| 211 | + node_empty = SimpleNamespace(expr_to_alias={}) |
| 212 | + assert has_conflict(node_empty, existing_conflict) is False |
| 213 | + |
| 214 | + |
175 | 215 | def test_select_statement_contains_data_generation(mock_session, mock_analyzer): |
176 | 216 | """SelectStatement.contains_data_generation should detect zero-arg |
177 | 217 | nondeterministic functions in projection, where, and order_by.""" |
|
0 commit comments