Skip to content
This repository was archived by the owner on Apr 1, 2026. It is now read-only.

Commit 5f2ed0d

Browse files
redo id remapper
1 parent 069dd09 commit 5f2ed0d

File tree

1 file changed

+54
-42
lines changed

1 file changed

+54
-42
lines changed

bigframes/core/rewrite/identifiers.py

Lines changed: 54 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,42 @@
1313
# limitations under the License.
1414
from __future__ import annotations
1515

16-
import dataclasses
1716
import typing
1817

1918
from bigframes.core import identifiers, nodes
2019

2120

22-
# TODO: May as well just outright remove selection nodes in this process.
21+
def _create_mapping_operator(
22+
id_def_remapping_by_node: dict[
23+
nodes.BigFrameNode, dict[identifiers.ColumnId, identifiers.ColumnId]
24+
],
25+
id_ref_remapping_by_node: dict[
26+
nodes.BigFrameNode, dict[identifiers.ColumnId, identifiers.ColumnId]
27+
],
28+
):
29+
"""
30+
Builds a remapping operator that uses predefined local remappings for ids.
31+
32+
Args:
33+
id_remapping_by_node: A mapping from nodes to their local remappings.
34+
35+
Returns:
36+
A remapping operator.
37+
"""
38+
39+
def _mapping_operator(node: nodes.BigFrameNode) -> nodes.BigFrameNode:
40+
# Step 1: Get the local remapping for the current node.
41+
local_def_remaps = id_def_remapping_by_node.get(node, {})
42+
local_ref_remaps = id_ref_remapping_by_node.get(node, {})
43+
44+
node = node.remap_vars(local_def_remaps)
45+
node = node.remap_refs(local_ref_remaps)
46+
47+
return node
48+
49+
return _mapping_operator
50+
51+
2352
def remap_variables(
2453
root: nodes.BigFrameNode,
2554
id_generator: typing.Iterator[identifiers.ColumnId],
@@ -42,46 +71,29 @@ def remap_variables(
4271
A tuple of the new root node and a mapping from old to new column IDs
4372
visible to the parent node.
4473
"""
45-
# Step 1: Recursively remap children to get their new nodes and ID mappings.
46-
new_child_nodes: list[nodes.BigFrameNode] = []
47-
new_child_mappings: list[dict[identifiers.ColumnId, identifiers.ColumnId]] = []
48-
for child in root.child_nodes:
49-
new_child, child_mappings = remap_variables(child, id_generator=id_generator)
50-
new_child_nodes.append(new_child)
51-
new_child_mappings.append(child_mappings)
52-
53-
# Step 2: Transform children to use their new nodes.
54-
remapped_children: dict[nodes.BigFrameNode, nodes.BigFrameNode] = {
55-
child: new_child for child, new_child in zip(root.child_nodes, new_child_nodes)
56-
}
57-
new_root = root.transform_children(lambda node: remapped_children[node])
58-
59-
# Step 3: Transform the current node using the mappings from its children.
60-
if isinstance(new_root, nodes.InNode):
61-
new_root = typing.cast(nodes.InNode, new_root)
62-
new_root = dataclasses.replace(
63-
new_root,
64-
left_col=new_root.left_col.remap_column_refs(
65-
new_child_mappings[0], allow_partial_bindings=True
66-
),
67-
)
68-
else:
69-
downstream_mappings: dict[identifiers.ColumnId, identifiers.ColumnId] = {
70-
k: v for mapping in new_child_mappings for k, v in mapping.items()
71-
}
72-
new_root = new_root.remap_refs(downstream_mappings)
73-
74-
# Step 4: Create new IDs for columns defined by the current node.
75-
node_defined_mappings = {
76-
old_id: next(id_generator) for old_id in root.node_defined_ids
77-
}
78-
new_root = new_root.remap_vars(node_defined_mappings)
74+
# step 1: defined remappings for each individual unique node
75+
# step 2: bottom up traversal to apply remappings
7976

80-
new_root._validate()
77+
id_def_remaps: dict[
78+
nodes.BigFrameNode, dict[identifiers.ColumnId, identifiers.ColumnId]
79+
] = {}
80+
id_ref_remaps: dict[
81+
nodes.BigFrameNode, dict[identifiers.ColumnId, identifiers.ColumnId]
82+
] = {}
83+
for node in root.iter_nodes_topo(): # bottom_up
84+
local_def_remaps = {
85+
col_id: next(id_generator) for col_id in node.node_defined_ids
86+
}
87+
id_def_remaps[node] = local_def_remaps
8188

82-
# Step 5: Determine which mappings to propagate up to the parent.
83-
propagated_mappings = {
84-
old_id: new_id for old_id, new_id in zip(root.ids, new_root.ids)
85-
}
89+
local_ref_remaps = {}
90+
for child in node.child_nodes: # inherit ref and def mappings from children
91+
local_ref_remaps.update(id_def_remaps[child])
92+
if not child.defines_namespace:
93+
local_ref_remaps.update(id_ref_remaps[child])
94+
id_ref_remaps[node] = local_ref_remaps
8695

87-
return new_root, propagated_mappings
96+
return (
97+
root.top_down(_create_mapping_operator(id_def_remaps, id_ref_remaps)),
98+
id_def_remaps[root],
99+
)

0 commit comments

Comments
 (0)