From 3b3888e9be75662b71468a79ba65f47da7819877 Mon Sep 17 00:00:00 2001 From: Salvo 'LtWorf' Tomaselli Date: Sun, 3 Jan 2016 10:07:23 +0100 Subject: [PATCH] New optimization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Turns π a,b,c(A) ∪ π a,b,c(B) into π a,b,c(A ∪ B) if A and B are union compatible Works with union, intersection and difference. --- CHANGELOG | 2 +- relational/optimizations.py | 40 ++++++++++++++++++++++++++++++++++-- test/union_projection.query | 1 + test/union_projection.result | 8 ++++++++ 4 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 test/union_projection.query create mode 100644 test/union_projection.result diff --git a/CHANGELOG b/CHANGELOG index 3ac9898..83c65bb 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,7 +2,7 @@ - Added again make install target - Ctrl+C in the terminal will terminate the GUI - UI indicates ongoing processing with a label -- Added new optimization +- Added new optimizations - Added shortcuts within the UI - History can be navigated with up/down arrows - Single line edit mode allows for the resulting relation to be written diff --git a/relational/optimizations.py b/relational/optimizations.py index 489fee0..5eb2320 100644 --- a/relational/optimizations.py +++ b/relational/optimizations.py @@ -544,6 +544,39 @@ def union_and_product(n): changes = 1 return changes + recoursive_scan(union_and_product, n) +def projection_and_union(n, rels): + ''' + Turns + π a,b,c(A) ∪ π a,b,c(B) + + into + π a,b,c(A ∪ B) + + if A and B are union compatible + ''' + changes = 0 + if n.name in {UNION, INTERSECTION, DIFFERENCE} and \ + n.left.name == PROJECTION and \ + n.right.name == PROJECTION and \ + set(n.left.result_format(rels)) == set(n.right.result_format(rels)) and \ + set(n.left.child.result_format(rels)) == set(n.right.child.result_format(rels)): + newchild = parser.Node() + + newchild.kind = parser.BINARY + newchild.name = n.name + newchild.left = n.left.child + newchild.right = n.right.child + + newnode = parser.Node() + newnode.child = newchild + newnode.kind = parser.UNARY + newnode.name = PROJECTION + newnode.prop = n.right.prop + replace_node(n, newnode) + changes = 1 + return changes + recoursive_scan(projection_and_union, n, rels) + + def selection_and_product(n, rels): '''This function locates things like σ k (R*Q) and converts them into @@ -653,9 +686,12 @@ general_optimizations = [ swap_union_renames, swap_rename_projection, select_union_intersect_subtract, - union_and_product + union_and_product, +] +specific_optimizations = [ + selection_and_product, + projection_and_union, ] -specific_optimizations = [selection_and_product] if __name__ == "__main__": print (tokenize_select("skill == 'C' and id % 2 == 0")) diff --git a/test/union_projection.query b/test/union_projection.query new file mode 100644 index 0000000..251af9e --- /dev/null +++ b/test/union_projection.query @@ -0,0 +1 @@ +πname,skill(σ skill == 'Perl' (people⋈skills)) ∪ πname,skill(σ skill == 'C' (people⋈skills)) diff --git a/test/union_projection.result b/test/union_projection.result new file mode 100644 index 0000000..7e0ab5d --- /dev/null +++ b/test/union_projection.result @@ -0,0 +1,8 @@ +name,skill +jack,C +eve,Perl +duncan,Perl +duncan,C +john,C +alia,C +eve,C