Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def visit_BinOp(self, expr):
left = self.visit(expr.left)
right = self.visit(expr.right)
weak_op = is_weak_op(self._context, expr.op)
if weak_op:
combination = irast.Disjunction
else:
combination = irast.Conjunction
paths = set()
for operand in (left, right):
if isinstance(operand,
(irast.InlineFilter, irast.AtomicRefSimple)):
paths.add(operand.ref)
else:
paths.add(operand)
e = combination(paths=frozenset(paths))
merge_filters = \
self._context.current.location != 'generator' or weak_op
if merge_filters:
merge_filters = expr.op
def add_conjunction_to_disjunction(context, disjunction, conjunction):
if disjunction.paths and conjunction.paths:
return irast.Disjunction(
paths=frozenset({disjunction, conjunction}))
elif disjunction.paths:
return disjunction
elif conjunction.paths:
return irast.Disjunction(paths=frozenset({conjunction}))
else:
return irast.Disjunction()
def minimize_disjunction(paths):
variables, miniterms = miniterms_from_conjunctions(paths)
minimized = boolean.minimize(miniterms)
paths = conjunctions_from_miniterms(minimized, variables)
result = irast.Disjunction(paths=frozenset(paths))
return result
def get_multipath(self, expr:irast.Path):
if not isinstance(expr, irast.PathCombination):
expr = irast.Disjunction(paths=frozenset((expr,)))
return expr
def add_conjunctions(self, left, right):
paths = frozenset(p for p in (left, right) if p.paths)
return irast.Disjunction(paths=paths)
type=context.current.proto_schema.get('int'))
context.current.location = 'top'
# Merge selector and sorter disjunctions first
paths = [s.expr for s in graph.selector] + \
[s.expr for s in graph.sorter] + \
[s for s in graph.grouper]
union = irast.Disjunction(paths=frozenset(paths))
self.flatten_and_unify_path_combination(union, deep=True,
merge_filters=True)
# Merge the resulting disjunction with generator conjunction
if graph.generator:
paths = [graph.generator] + list(union.paths)
union = irast.Disjunction(paths=frozenset(paths))
self.flatten_and_unify_path_combination(union, deep=True,
merge_filters=True)
# Reorder aggregate expressions so that all of them appear as the
# first sub-tree in the generator expression.
#
if graph.generator:
self.reorder_aggregates(graph.generator)
graph.result_types = self.get_selector_types(graph.selector, self.proto_schema)
graph.argument_types = self.context.current.arguments
graph.context_vars = self.context.current.context_vars
self.link_subqueries(graph)
return graph
def _unify_paths(self, result, paths, mode, reverse=True, merge_filters=False):
mypaths = set(paths)
while mypaths:
path = irutils.extract_paths(mypaths.pop(), reverse)
if not path or result is path:
continue
if issubclass(mode, irast.Disjunction):
"""LOG [edgedb.graph.merge] ADDING
print(' ' * self.nest, 'ADDING', result, path, getattr(result, 'id', '??'), getattr(path, 'id', '??'), merge_filters)
self.nest += 2
self._dump(result)
self._dump(path)
"""
result = self.add_paths(result, path, merge_filters=merge_filters)
assert result
"""LOG [edgedb.graph.merge] ADDITION RESULT
self.nest -= 2
self._dump(result)
"""
else:
if left and right:
self.fixup_refs([right], left)
if merge_filters and right.filter:
left.filter = self.extend_binop(left.filter, right.filter, op=ast.ops.AND)
if merge_filters:
paths_left = set()
for dpath in right.disjunction.paths:
if isinstance(dpath, (irast.EntitySet, irast.EntityLink)):
merged = self.intersect_paths(left.conjunction, dpath, merge_filters)
if merged is not left.conjunction:
paths_left.add(dpath)
else:
paths_left.add(dpath)
right.disjunction = irast.Disjunction(paths=frozenset(paths_left))
left.disjunction = self.add_paths(left.disjunction,
right.disjunction, merge_filters)
if merge_filters and merge_op == ast.ops.OR:
left.disjunction.fixed = True
left.atomrefs.update(right.atomrefs)
left.metarefs.update(right.metarefs)
left.users.update(right.users)
left.joins.update(right.joins)
left.joins.discard(left)
if left.origin is None and right.origin is not None:
left.origin = right.origin
if merge_filters and right.filter:
left.filter = irutils.extend_binop(
left.filter, right.filter, op=ast.ops.AND)
if merge_filters:
paths_left = set()
for dpath in right.disjunction.paths:
if isinstance(dpath,
(irast.EntitySet, irast.EntityLink)):
merged = intersect_paths(context, left.conjunction,
dpath, merge_filters)
if merged is not left.conjunction:
paths_left.add(dpath)
else:
paths_left.add(dpath)
right.disjunction = irast.Disjunction(
paths=frozenset(paths_left))
left.disjunction = add_paths(
context, left.disjunction, right.disjunction, merge_filters)
if merge_filters and merge_op == ast.ops.OR:
left.disjunction.fixed = True
left.atomrefs.update(right.atomrefs)
left.users.update(right.users)
left.joins.update(right.joins)
left.joins.discard(left)
if left.origin is None and right.origin is not None:
left.origin = right.origin
def add_paths(self, left, right, merge_filters=False):
if isinstance(left, (irast.EntityLink, irast.EntitySet)):
if isinstance(right, (irast.EntityLink, irast.EntitySet)):
# Both operands are sets -- simply merge them
result = self.add_sets(left, right, merge_filters)
elif isinstance(right, irast.Disjunction):
result = self.add_to_disjunction(right, left, merge_filters)
elif isinstance(right, irast.Conjunction):
result = self.add_to_conjunction(right, left, merge_filters)
elif isinstance(left, irast.Disjunction):
if isinstance(right, (irast.EntityLink, irast.EntitySet)):
result = self.add_to_disjunction(left, right, merge_filters)
elif isinstance(right, irast.Disjunction):
result = self.add_disjunctions(left, right, merge_filters)
elif isinstance(right, irast.Conjunction):
result = self.add_conjunction_to_disjunction(left, right)
elif isinstance(left, irast.Conjunction):
if isinstance(right, (irast.EntityLink, irast.EntitySet)):
result = self.add_to_conjunction(left, right, merge_filters)
elif isinstance(right, irast.Disjunction):
result = self.add_conjunction_to_disjunction(right, left)