From b3b5afec637fc58004aa471ad75a35b513637035 Mon Sep 17 00:00:00 2001 From: Salvo 'LtWorf' Tomaselli Date: Tue, 9 Jun 2020 15:56:16 +0200 Subject: [PATCH] Some convenience methods --- relational/optimizations.py | 12 ++++++------ relational/parser.py | 23 +++++++++++++++++++++-- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/relational/optimizations.py b/relational/optimizations.py index 362cd16..63b6810 100644 --- a/relational/optimizations.py +++ b/relational/optimizations.py @@ -223,8 +223,8 @@ def swap_union_renames(n: parser.Node) -> Tuple[parser.Node, int]: ρ a➡b(R ∪ Q). Does the same with subtraction and intersection''' if n.name in (DIFFERENCE, UNION, INTERSECTION) and n.left.name == RENAME and n.right.name == RENAME: - l_vars = n.left.rename_dict() - r_vars = n.right.rename_dict() + l_vars = n.left.get_rename_prop() + r_vars = n.right.get_rename_prop() if r_vars == l_vars: child = parser.Binary(n.name, n.left.child, n.right.child) return parser.Unary(RENAME, n.left.prop, child), 1 @@ -240,7 +240,7 @@ def futile_renames(n: parser.Node) -> Tuple[parser.Node, int]: or removes the operation entirely if they all get removed ''' if n.name == RENAME: - renames = n.rename_dict() + renames = n.get_rename_prop() changes = False for k, v in renames.items(): if k == v: @@ -250,7 +250,7 @@ def futile_renames(n: parser.Node) -> Tuple[parser.Node, int]: return n.child, 1 elif changes: # Changing the node in place, no need to return to cause a recursive step - n.prop = ','.join(f'{k}{ARROW}{v}' for k, v in renames.items()) + n.set_rename_prop(renames) return n, 0 @@ -286,8 +286,8 @@ def subsequent_renames(n: parser.Node) -> Tuple[parser.Node, int]: if len(renames) == 0: # Nothing to rename, removing the rename op return n, 1 - elif changes: - n.prop = ','.join(f'{k}{ARROW}{v}' for k, v in renames.items()) + else: + n.set_rename_prop(renames) return n, 1 return n, 0 diff --git a/relational/parser.py b/relational/parser.py index 593272e..a5d6d34 100644 --- a/relational/parser.py +++ b/relational/parser.py @@ -233,13 +233,23 @@ class Unary(Node): if self.name == PROJECTION: prop = '\"%s\"' % prop.replace(' ', '').replace(',', '\",\"') elif self.name == RENAME: - prop = repr(self.rename_dict()) + prop = repr(self.get_rename_prop()) else: # Selection prop = repr(prop) return '%s.%s(%s)' % (self.child._toPython(), op_functions[self.name], prop) - def rename_dict(self) -> Dict[str, str]: + def get_projection_prop(self) -> List[str]: + if self.name != PROJECTION: + raise ValueError('This is only supported on projection nodes') + return [i.strip() for i in self.prop.split(',')] + + def set_projection_prop(self, p: List[str]) -> None: + if self.name != PROJECTION: + raise ValueError('This is only supported on projection nodes') + self.prop = ','.join(p) + + def get_rename_prop(self) -> Dict[str, str]: ''' Returns the dictionary that the rename operation wants ''' @@ -251,6 +261,15 @@ class Unary(Node): r[q[0].strip()] = q[1].strip() return r + def set_rename_prop(self, renames: Dict[str, str]) -> None: + ''' + Sets the prop field based on the dictionary for renames + ''' + if self.name != RENAME: + raise ValueError('This is only supported on rename nodes') + self.prop = ','.join(f'{k}{ARROW}{v}' for k, v in renames.items()) + + def parse_tokens(expression: List[Union[list, str]]) -> Node: