Skip to content
This repository was archived by the owner on Mar 21, 2021. It is now read-only.

Commit 22f2df0

Browse files
committed
Replace ExprOpAggregate with Op with sig set
1 parent 4a3704a commit 22f2df0

File tree

4 files changed

+53
-70
lines changed

4 files changed

+53
-70
lines changed

qc0/compile.py

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
RelAroundParent,
2020
Expr,
2121
ExprOp,
22-
ExprOpAggregate,
2322
ExprRecord,
2423
ExprColumn,
2524
ExprIdentity,
@@ -264,8 +263,8 @@ def build_kernel():
264263
at = from_obj.at
265264
columns = []
266265
for field in rel.fields.values():
267-
expr, from_obj = expr_to_sql(
268-
field.expr,
266+
expr, from_obj = op_to_sql(
267+
field.op,
269268
from_obj=from_obj.replace(at=at),
270269
)
271270
columns.append(expr.label(field.name))
@@ -292,11 +291,17 @@ def build_kernel():
292291
return None, from_obj
293292

294293
result_columns = [from_obj.current.columns[c.name] for c in tuple(columns)]
295-
for name, expr in rel.aggregates.items():
296-
assert isinstance(expr, ExprOpAggregate), str(expr)
294+
for name, op in rel.aggregates.items():
295+
assert op.sig is not None
297296
columns, kernel = build_kernel()
298-
value, inner_from_obj = op_to_sql(expr.op, from_obj=kernel)
299-
value = expr.sig.compile([value])
297+
298+
value, inner_from_obj = rel_to_sql(op.rel, from_obj=kernel)
299+
if op.expr is not None:
300+
value, inner_from_obj = expr_to_sql(
301+
op.expr, from_obj=inner_from_obj
302+
)
303+
304+
value = op.sig.compile([value])
300305
if kernel.current in inner_from_obj.current._from_objects:
301306
cols = columns
302307
else:
@@ -312,7 +317,7 @@ def build_kernel():
312317
inner_sel, *((c.name, c.name) for c in columns), outer=True
313318
)
314319
result_columns.append(
315-
sa.func.coalesce(inner_at.c.value, expr.sig.unit).label(name)
320+
sa.func.coalesce(inner_at.c.value, op.sig.unit).label(name)
316321
)
317322

318323
from_obj = From.make(
@@ -322,29 +327,14 @@ def build_kernel():
322327

323328

324329
def op_to_sql(op: Op, from_obj):
325-
expr, from_obj = rel_to_sql(op.rel, from_obj=from_obj)
330+
expr, inner_from_obj = rel_to_sql(op.rel, from_obj=from_obj)
326331
if op.expr is not None:
327-
expr, from_obj = expr_to_sql(op.expr, from_obj=from_obj)
328-
return expr, from_obj
329-
330-
331-
@singledispatch
332-
def expr_to_sql(expr: Expr, from_obj):
333-
raise NotImplementedError( # pragma: no cover
334-
f"expr_to_sql({type(expr).__name__})"
335-
)
336-
337-
338-
@expr_to_sql.register
339-
def ExprOp_to_sql(expr: ExprOp, from_obj):
340-
return op_to_sql(expr.op, from_obj)
332+
expr, inner_from_obj = expr_to_sql(op.expr, from_obj=inner_from_obj)
341333

334+
if op.sig is None:
335+
return expr, inner_from_obj
342336

343-
@expr_to_sql.register
344-
def ExprOpAggregate_to_sql(op: ExprOpAggregate, from_obj):
345-
expr, inner_from_obj = op_to_sql(op.op, from_obj)
346337
if inner_from_obj.limit is not None or inner_from_obj.order is not None:
347-
expr, inner_from_obj = op_to_sql(op.op, from_obj)
348338
inner_from_obj = From.make(inner_from_obj.to_select(expr).alias())
349339
value = sa.func.coalesce(
350340
op.sig.compile([inner_from_obj.at.c.value]),
@@ -363,15 +353,25 @@ def ExprOpAggregate_to_sql(op: ExprOpAggregate, from_obj):
363353
return at.c.value, from_obj
364354

365355

356+
@singledispatch
357+
def expr_to_sql(expr: Expr, from_obj):
358+
raise NotImplementedError( # pragma: no cover
359+
f"expr_to_sql({type(expr).__name__})"
360+
)
361+
362+
363+
@expr_to_sql.register
364+
def ExprOp_to_sql(expr: ExprOp, from_obj):
365+
return op_to_sql(expr.op, from_obj)
366+
367+
366368
@expr_to_sql.register
367369
def ExprRecord_to_sql(op: ExprRecord, from_obj):
368370
args = []
369371
at = from_obj.at
370372
for field in op.fields.values():
371373
args.append(sa.literal(field.name))
372-
expr, from_obj = expr_to_sql(
373-
field.expr, from_obj=from_obj.replace(at=at)
374-
)
374+
expr, from_obj = op_to_sql(field.op, from_obj=from_obj.replace(at=at))
375375
args.append(expr)
376376
return sa.func.jsonb_build_object(*args), from_obj
377377

qc0/op.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from sqlalchemy import Table, ForeignKey
1515
from sqlalchemy.sql.elements import ColumnClause
1616
from .base import Struct, undefined
17-
from .scope import Scope, Cardinality
17+
from .scope import Scope, EmptyScope, Cardinality
1818
from .syntax import Syn, Compose
1919

2020

@@ -24,6 +24,7 @@ class Op(Struct):
2424
rel: Rel
2525
expr: Optional[Expr]
2626
syn: Optional[Syn] = None
27+
sig: Any = None
2728

2829
def grow_expr(self, expr, syn=None, scope=undefined, card=undefined):
2930
card = self.card if card is undefined else card
@@ -49,6 +50,9 @@ def grow_rel(self, rel, syn=None, scope=undefined, card=undefined):
4950
)
5051
return self.replace(rel=rel, scope=scope, card=card, syn=syn)
5152

53+
def aggregate(self, sig):
54+
return self.replace(sig=sig, scope=EmptyScope(), card=Cardinality.ONE)
55+
5256
def __yaml__(self):
5357
rep = super(Op, self).__yaml__()
5458
rep.pop("scope")
@@ -119,11 +123,6 @@ class ExprOp(Expr):
119123
op: Op
120124

121125

122-
class ExprOpAggregate(Expr):
123-
op: Op
124-
sig: Any
125-
126-
127126
class ExprRecord(Expr):
128127
fields: Dict[str, Field]
129128

@@ -149,7 +148,7 @@ class ExprApply(Expr):
149148

150149
class Field(Struct):
151150
name: str
152-
expr: Expr
151+
op: Op
153152

154153

155154
class Sort(Struct):

qc0/plan.py

Lines changed: 15 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@
5252
RelAroundParent,
5353
Expr,
5454
ExprOp,
55-
ExprOpAggregate,
5655
ExprRecord,
5756
ExprColumn,
5857
ExprIdentity,
@@ -99,12 +98,10 @@ def build_op_expr(op: Op):
9998
if isinstance(op.scope, RecordScope):
10099
fields = {}
101100
for name, f in op.scope.fields.items():
102-
fop = build_op(f.syn, make_parent(op.scope.parent))
103-
if fop.card == Cardinality.SEQ:
104-
expr = ExprOpAggregate(op=fop, sig=JsonAggSig)
105-
else:
106-
expr = ExprOp(op=fop)
107-
fields[name] = Field(expr=expr, name=name)
101+
field_op = build_op(f.syn, make_parent(op.scope.parent))
102+
if field_op.card == Cardinality.SEQ:
103+
field_op = field_op.aggregate(JsonAggSig)
104+
fields[name] = Field(op=field_op, name=name)
108105
return Op(
109106
rel=op.rel,
110107
expr=ExprRecord(fields=fields),
@@ -135,14 +132,12 @@ def build_op_expr(op: Op):
135132
for name, f in op.scope.fields.items():
136133
fields[name] = Field(
137134
name=name,
138-
expr=ExprOp(
139-
Op(
140-
expr=ExprColumn(column=sa.column(name)),
141-
rel=RelParent(parent=op),
142-
card=Cardinality.ONE,
143-
scope=EmptyScope(),
144-
syn=Nav(name),
145-
)
135+
op=Op(
136+
expr=ExprColumn(column=sa.column(name)),
137+
rel=RelParent(parent=op),
138+
card=Cardinality.ONE,
139+
scope=EmptyScope(),
140+
syn=Nav(name),
146141
),
147142
)
148143
expr = ExprRecord(fields=fields)
@@ -153,7 +148,6 @@ def build_op_expr(op: Op):
153148
scope=op.scope,
154149
syn=None,
155150
)
156-
assert False, f"unable to build an expr at this scope: {op!r}"
157151
return op
158152

159153

@@ -262,12 +256,10 @@ def Nav_to_op(syn: Nav, parent: Op):
262256

263257
def wrap(op):
264258
if op.card == Cardinality.SEQ:
265-
expr = ExprOpAggregate(op=op, sig=JsonAggSig)
259+
op = op.aggregate(JsonAggSig)
266260
else:
267-
assert isinstance(op.rel, RelVoid)
268-
assert isinstance(op.expr, ExprOpAggregate)
269-
expr = op.expr
270-
name = parent.scope.add_aggregate(expr)
261+
assert op.sig is not None
262+
name = parent.scope.add_aggregate(op)
271263
return parent.grow_expr(
272264
expr=ExprColumn(column=sa.column(name)),
273265
scope=EmptyScope(),
@@ -391,9 +383,7 @@ def Apply_to_op(syn: Apply, parent: Op):
391383
if op.expr is None:
392384
if isinstance(op.scope, TableScope):
393385
op = op.grow_expr(ExprIdentity(table=op.scope.table))
394-
else:
395-
assert False, f"{syn.name}: unable to group by this"
396-
fields[name] = Field(expr=ExprOp(op), name=name)
386+
fields[name] = Field(op=op, name=name)
397387

398388
rel = RelGroup(
399389
rel=parent.rel,
@@ -407,13 +397,7 @@ def Apply_to_op(syn: Apply, parent: Op):
407397
sig = AggrSig.get(syn.name)
408398
if sig:
409399
assert parent.card >= Cardinality.SEQ, parent
410-
return Op(
411-
expr=ExprOpAggregate(op=parent, sig=sig),
412-
rel=RelVoid(),
413-
scope=EmptyScope(),
414-
card=Cardinality.ONE,
415-
syn=syn,
416-
)
400+
return parent.aggregate(sig)
417401

418402
sig = FuncSig.get(syn.name)
419403
if sig:

qc0/scope.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,10 @@ class GroupScope(Scope):
9696
fields: Dict[str, Field]
9797
aggregates: Dict[str, Any]
9898

99-
def add_aggregate(self, expr):
99+
def add_aggregate(self, op):
100100
idx = len(self.aggregates)
101101
name = f"aggr_{idx}"
102-
self.aggregates[name] = expr
102+
self.aggregates[name] = op
103103
return name
104104

105105
def __yaml__(self):

0 commit comments

Comments
 (0)