Skip to content

Commit 499c000

Browse files
committed
attempt 1
1 parent 0b84cbf commit 499c000

12 files changed

+93
-58
lines changed

pydough/conversion/hybrid_translator.py

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,22 +1118,26 @@ def make_hybrid_expr(
11181118
return HybridBackRefExpr(expr_name, expr.back_levels, expr.pydough_type)
11191119
case Reference():
11201120
if hybrid.ancestral_mapping.get(expr.term_name, 0) > 0:
1121-
collection = expr.collection
1122-
while (
1123-
isinstance(collection, PartitionChild)
1124-
and expr.term_name in collection.child_access.ancestral_mapping
1125-
):
1126-
collection = collection.child_access
1127-
return self.make_hybrid_expr(
1128-
hybrid,
1129-
BackReferenceExpression(
1130-
collection,
1131-
expr.term_name,
1132-
hybrid.ancestral_mapping[expr.term_name],
1133-
),
1134-
child_ref_mapping,
1135-
inside_agg,
1121+
# HA: FIXME: raise error for now.
1122+
raise NotImplementedError(
1123+
"Unable to resolve collection context for Reference. "
11361124
)
1125+
# collection = expr.collection
1126+
# while (
1127+
# isinstance(collection, PartitionChild)
1128+
# and expr.term_name in collection.child_access.ancestral_mapping
1129+
# ):
1130+
# collection = collection.child_access
1131+
# return self.make_hybrid_expr(
1132+
# hybrid,
1133+
# BackReferenceExpression(
1134+
# collection,
1135+
# expr.term_name,
1136+
# hybrid.ancestral_mapping[expr.term_name],
1137+
# ),
1138+
# child_ref_mapping,
1139+
# inside_agg,
1140+
# )
11371141
expr_name = hybrid.pipeline[-1].renamings.get(
11381142
expr.term_name, expr.term_name
11391143
)

pydough/conversion/relational_converter.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
WindowCallExpression,
5050
)
5151
from pydough.types import BooleanType, NumericType, UnknownType
52+
from pydough.types.pydough_type import PyDoughType
5253

5354
from .agg_removal import remove_redundant_aggs
5455
from .agg_split import split_partial_aggregates
@@ -1304,16 +1305,27 @@ def preprocess_root(
13041305
"""
13051306
Transforms the final PyDough collection by appending it with an extra
13061307
CALCULATE containing all of the columns that are output.
1308+
Args:
1309+
`node`: the PyDough QDAG collection node to be translated.
1310+
`output_cols`: a list of tuples in the form `(alias, column)`
1311+
describing every column that should be in the output, in the order
1312+
they should appear, and the alias they should be given. If None, uses
1313+
the most recent CALCULATE in the node to determine the columns.
1314+
Returns:
1315+
The PyDoughCollectionQDAG with an additional CALCULATE at the end
1316+
that contains all of the columns that should be in the output.
13071317
"""
13081318
# Fetch all of the expressions that should be kept in the final output
13091319
final_terms: list[tuple[str, PyDoughExpressionQDAG]] = []
13101320
if output_cols is None:
13111321
for name in node.calc_terms:
1312-
final_terms.append((name, Reference(node, name)))
1322+
name_typ: PyDoughType = node.get_expr(name).pydough_type
1323+
final_terms.append((name, Reference(name, name_typ)))
13131324
final_terms.sort(key=lambda term: node.get_expression_position(term[0]))
13141325
else:
13151326
for _, column in output_cols:
1316-
final_terms.append((column, Reference(node, column)))
1327+
column_typ: PyDoughType = node.get_expr(column).pydough_type
1328+
final_terms.append((column, Reference(column, column_typ)))
13171329
children: list[PyDoughCollectionQDAG] = []
13181330
final_calc: Calculate = Calculate(node, children).with_terms(final_terms)
13191331
return final_calc

pydough/qdag/README.md

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@ table_collection = builder.build_child_access("Nations", global_context_node)
6565

6666
# Build a reference node
6767
# Equivalent PyDough code: `TPCH.Nations.name`
68-
reference_node = builder.build_reference(table_collection, "name")
68+
ref_name = "name"
69+
pydough_type = table_collection.get_expr(ref_name).pydough_type
70+
reference_node = builder.build_reference(ref_name, pydough_type)
6971

7072
# Build an expression function call node
7173
# Equivalent PyDough code: `LOWER(TPCH.Nations.name)`
@@ -99,7 +101,10 @@ regions_collection = builder.build_child_access("Regions", global_context_node)
99101
# Access nations sub-collection
100102
nations_sub_collection = builder.build_child_access("nations", regions_collection)
101103
# Create WHERE(key == 4) condition
102-
key_ref = builder.build_reference(nations_sub_collection, "key")
104+
105+
ref_name = "key"
106+
pydough_type = nations_sub_collection.get_expr(ref_name).pydough_type
107+
key_ref = builder.build_reference(ref_name, pydough_type)
103108
literal_4 = builder.build_literal(4, NumericType())
104109
condition = builder.build_expression_function_call("EQU", [key_ref, literal_4])
105110
# Build WHERE node with condition
@@ -108,7 +113,9 @@ where_node = where_node.with_condition(condition)
108113
# Create SINGULAR node from filtered result
109114
singular_node = builder.build_singular(where_node)
110115
# Build reference node for name
111-
reference_node = builder.build_reference(singular_node, "name")
116+
ref_name = "name"
117+
pydough_type = singular_node.get_expr(ref_name).pydough_type
118+
reference_node = builder.build_reference(ref_name, pydough_type)
112119
# Build CALCULATE node with calculated term
113120
calculate_node = builder.build_calc(regions_collection, [nations_sub_collection])
114121
calculate_node = calculate_node.with_terms([("n_4_nation", reference_node)])
@@ -130,7 +137,9 @@ top_k_node = top_k_node.with_collation([collation_expression])
130137
# Build a PARTITION BY node
131138
# Equivalent PyDough code: `TPCH.PARTITION(Parts, name="p", by=part_type)`
132139
part_collection = builder.build_child_access("Parts", global_context_node)
133-
partition_key = builder.build_reference(part_collection, "part_type")
140+
ref_name = "part_type"
141+
pydough_type = part_collection.get_expr(ref_name).pydough_type
142+
partition_key = builder.build_reference(ref_name, pydough_type)
134143
partition_by_node = builder.build_partition(part_collection, child_collection, "p")
135144
partition_by_node = partition_by_node.with_keys([partition_key])
136145

pydough/qdag/collections/augmenting_child_operator.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ def get_term(self, term_name: str) -> PyDoughQDAG:
8484
if isinstance(term, ChildAccess):
8585
term = term.clone_with_parent(self)
8686
elif isinstance(term, PyDoughExpressionQDAG):
87-
term = Reference(self.preceding_context, term_name)
87+
typ = self.preceding_context.get_expr(term_name).pydough_type
88+
term = Reference(term_name, typ)
8889
return term
8990

9091
@cache

pydough/qdag/collections/collection_access.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ def get_term(self, term_name: str) -> PyDoughQDAG:
129129
else:
130130
assert context.ancestor_context is not None
131131
context = context.ancestor_context
132-
return Reference(context, term_name)
132+
return Reference(term_name, context.get_expr(term_name).pydough_type)
133133

134134
if term_name not in self.all_terms:
135135
raise PyDoughQDAGException(self.name_mismatch_error(term_name))

pydough/qdag/collections/partition_child.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ def get_term(self, term_name: str):
102102
else:
103103
assert context.ancestor_context is not None
104104
context = context.ancestor_context
105-
return Reference(context, term_name)
105+
return Reference(term_name, context.get_expr(term_name).pydough_type)
106106

107107
elif term_name not in self.all_terms:
108108
raise PyDoughQDAGException(self.name_mismatch_error(term_name))

pydough/qdag/expressions/back_reference_expression.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,21 @@ def __init__(
3838
)
3939
self._ancestor = ancestor
4040
self._expression = self._ancestor.get_expr(term_name)
41+
self._term_type = self._expression.pydough_type
42+
43+
@property
44+
def collection(self) -> PyDoughCollectionQDAG:
45+
"""
46+
The collection that the Reference term comes from.
47+
"""
48+
return self._collection
49+
50+
@property
51+
def expression(self) -> PyDoughExpressionQDAG:
52+
"""
53+
The expression that the ChildReferenceExpression refers to.
54+
"""
55+
return self._expression
4156

4257
@property
4358
def back_levels(self) -> int:

pydough/qdag/expressions/child_reference_expression.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,26 @@ def __init__(
2929
self._child_idx: int = child_idx
3030
self._term_name: str = term_name
3131
self._expression: PyDoughExpressionQDAG = self._collection.get_expr(term_name)
32+
self._term_type = self._expression.pydough_type
3233
if not self.expression.is_singular(collection.starting_predecessor):
3334
raise PyDoughQDAGException(
3435
f"Cannot reference plural expression {self.expression} from {self.collection}"
3536
)
3637

38+
@property
39+
def collection(self) -> PyDoughCollectionQDAG:
40+
"""
41+
The collection that the Reference term comes from.
42+
"""
43+
return self._collection
44+
45+
@property
46+
def expression(self) -> PyDoughExpressionQDAG:
47+
"""
48+
The expression that the ChildReferenceExpression refers to.
49+
"""
50+
return self._expression
51+
3752
@property
3853
def child_idx(self) -> int:
3954
"""

pydough/qdag/expressions/reference.py

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77

88

99
from pydough.qdag.abstract_pydough_qdag import PyDoughQDAG
10-
from pydough.qdag.collections.collection_qdag import PyDoughCollectionQDAG
11-
from pydough.qdag.errors import PyDoughQDAGException
1210
from pydough.types import PyDoughType
1311

1412
from .expression_qdag import PyDoughExpressionQDAG
@@ -20,21 +18,9 @@ class Reference(PyDoughExpressionQDAG):
2018
a preceding collection.
2119
"""
2220

23-
def __init__(self, collection: PyDoughCollectionQDAG, term_name: str):
24-
self._collection: PyDoughCollectionQDAG = collection
21+
def __init__(self, term_name: str, term_type: PyDoughType):
2522
self._term_name: str = term_name
26-
self._expression: PyDoughExpressionQDAG = collection.get_expr(term_name)
27-
if not self.expression.is_singular(collection.starting_predecessor):
28-
raise PyDoughQDAGException(
29-
f"Cannot reference plural expression {self.expression} from {self.collection}"
30-
)
31-
32-
@property
33-
def collection(self) -> PyDoughCollectionQDAG:
34-
"""
35-
The collection that the Reference term comes from.
36-
"""
37-
return self._collection
23+
self._term_type: PyDoughType = term_type
3824

3925
@property
4026
def term_name(self) -> str:
@@ -43,20 +29,13 @@ def term_name(self) -> str:
4329
"""
4430
return self._term_name
4531

46-
@property
47-
def expression(self) -> PyDoughExpressionQDAG:
48-
"""
49-
The original expression that the reference refers to.
50-
"""
51-
return self._expression
52-
5332
@property
5433
def pydough_type(self) -> PyDoughType:
55-
return self.expression.pydough_type
34+
return self._term_type
5635

5736
@property
5837
def is_aggregation(self) -> bool:
59-
return self.expression.is_aggregation
38+
return False
6039

6140
def is_singular(self, context: PyDoughQDAG) -> bool:
6241
# References are already known to be singular via their construction.
@@ -72,5 +51,5 @@ def equals(self, other: object) -> bool:
7251
return (
7352
isinstance(other, Reference)
7453
and self.term_name == other.term_name
75-
and self.collection.equals(other.collection)
54+
and self.pydough_type == other.pydough_type
7655
)

pydough/qdag/node_builder.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,15 +155,13 @@ def build_window_call(
155155
window_operator, qualified_args, collation_args, levels, kwargs
156156
)
157157

158-
def build_reference(
159-
self, collection: PyDoughCollectionQDAG, name: str
160-
) -> Reference:
158+
def build_reference(self, name: str, typ: PyDoughType) -> Reference:
161159
"""
162-
Creates a new reference to an expression from a preceding collection.
160+
Creates a new reference to an expression in the collection.
163161
164162
Args:
165-
`collection`: the collection that the reference comes from.
166163
`name`: the name of the expression being referenced.
164+
`typ`: the PyDough type of the expression being referenced.
167165
168166
Returns:
169167
The newly created PyDough Reference.
@@ -172,7 +170,7 @@ def build_reference(
172170
`PyDoughQDAGException`: if `name` does not refer to an expression in
173171
the collection.
174172
"""
175-
return Reference(collection, name)
173+
return Reference(name, typ)
176174

177175
def build_child_reference_expression(
178176
self,

0 commit comments

Comments
 (0)