def down_to_unions_subtractions_intersections(n): '''This funcion locates things like σ i==2 (c ᑌ d), where the union can be a subtraction and an intersection and replaces them with σ i==2 (c) ᑌ σ i==2(d). ''' changes = 0 _o = (UNION, DIFFERENCE, INTERSECTION) if n.name == SELECTION and n.child.name in _o: left = parser.node() left.prop = n.prop left.name = n.name left.child = n.child.left left.kind = parser.UNARY right = parser.node() right.prop = n.prop right.name = n.name right.child = n.child.right right.kind = parser.UNARY n.name = n.child.name n.left = left n.right = right n.child = None n.prop = None n.kind = parser.BINARY changes += 1 return changes + recoursive_scan(down_to_unions_subtractions_intersections, n)
def down_to_unions_subtractions_intersections(n): '''This funcion locates things like σ i==2 (c ᑌ d), where the union can be a subtraction and an intersection and replaces them with σ i==2 (c) ᑌ σ i==2(d). ''' changes = 0 _o = (UNION, DIFFERENCE, INTERSECTION) if n.name == SELECTION and n.child.name in _o: left = parser.node() left.prop = n.prop left.name = n.name left.child = n.child.left left.kind = parser.UNARY right = parser.node() right.prop = n.prop right.name = n.name right.child = n.child.right right.kind = parser.UNARY n.name = n.child.name n.left = left n.right = right n.child = None n.prop = None n.kind = parser.BINARY changes += 1 return changes + recoursive_scan(down_to_unions_subtractions_intersections, n)
def select_union_intersect_subtract(n): '''This function locates things like σ i(a) ᑌ σ q(a) and replaces them with σ (i OR q) (a) Removing a O(n²) operation like the union''' changes = 0 if n.name in (UNION, INTERSECTION, DIFFERENCE) and n.left.name == SELECTION and n.right.name == SELECTION and n.left.child == n.right.child: cahnges = 1 d = {UNION: 'or', INTERSECTION: 'and', DIFFERENCE: 'and not'} op = d[n.name] newnode = parser.node() if n.left.prop.startswith('(') or n.right.prop.startswith('('): t_str = '(' if n.left.prop.startswith('('): t_str += '(%s)' else: t_str += '%s' t_str += ' %s ' if n.right.prop.startswith('('): t_str += '(%s)' else: t_str += '%s' t_str += ')' newnode.prop = t_str % (n.left.prop, op, n.right.prop) else: newnode.prop = '%s %s %s' % (n.left.prop, op, n.right.prop) newnode.name = SELECTION newnode.child = n.left.child newnode.kind = parser.UNARY replace_node(n, newnode) return changes + recoursive_scan(select_union_intersect_subtract, n)
def select_union_intersect_subtract(n): '''This function locates things like σ i(a) ᑌ σ q(a) and replaces them with σ (i OR q) (a) Removing a O(n²) operation like the union''' changes = 0 if n.name in ( UNION, INTERSECTION, DIFFERENCE ) and n.left.name == SELECTION and n.right.name == SELECTION and n.left.child == n.right.child: cahnges = 1 d = {UNION: 'or', INTERSECTION: 'and', DIFFERENCE: 'and not'} op = d[n.name] newnode = parser.node() newnode.prop = '((%s) %s (%s))' % (n.left.prop, op, n.right.prop) newnode.name = SELECTION newnode.child = n.left.child newnode.kind = parser.UNARY replace_node(n, newnode) return changes + recoursive_scan(select_union_intersect_subtract, n)
def swap_union_renames(n): '''This function locates things like ρ a➡b(R) ᑌ ρ a➡b(Q) and replaces them with ρ a➡b(R ᑌ Q). Does the same with subtraction and intersection''' changes = 0 if n.name in (DIFFERENCE, UNION, INTERSECTION ) and n.left.name == n.right.name and n.left.name == RENAME: l_vars = {} for i in n.left.prop.split(','): q = i.split(ARROW) l_vars[q[0].strip()] = q[1].strip() r_vars = {} for i in n.right.prop.split(','): q = i.split(ARROW) r_vars[q[0].strip()] = q[1].strip() if r_vars == l_vars: changes = 1 #Copying self, but child will be child of renames q = parser.node() q.name = n.name q.kind = parser.BINARY q.left = n.left.child q.right = n.right.child n.name = RENAME n.kind = parser.UNARY n.child = q n.prop = n.left.prop n.left = n.right = None return changes + recoursive_scan(swap_union_renames, n)
def swap_union_renames(n): '''This function locates things like ρ a➡b(R) ᑌ ρ a➡b(Q) and replaces them with ρ a➡b(R ᑌ Q). Does the same with subtraction and intersection''' changes = 0 if n.name in (DIFFERENCE, UNION, INTERSECTION) and n.left.name == n.right.name and n.left.name == RENAME: l_vars = {} for i in n.left.prop.split(','): q = i.split(ARROW) l_vars[q[0].strip()] = q[1].strip() r_vars = {} for i in n.right.prop.split(','): q = i.split(ARROW) r_vars[q[0].strip()] = q[1].strip() if r_vars == l_vars: changes = 1 # Copying self, but child will be child of renames q = parser.node() q.name = n.name q.kind = parser.BINARY q.left = n.left.child q.right = n.right.child n.name = RENAME n.kind = parser.UNARY n.child = q n.prop = n.left.prop n.left = n.right = None return changes + recoursive_scan(swap_union_renames, n)
def selection_and_product(n, rels): '''This function locates things like σ k (R*Q) and converts them into σ l (σ j (R) * σ i (Q)). Where j contains only attributes belonging to R, i contains attributes belonging to Q and l contains attributes belonging to both''' changes = 0 if n.name == SELECTION and n.child.name in (PRODUCT, JOIN, JOIN_LEFT, JOIN_RIGHT, JOIN_FULL): l_attr = n.child.left.result_format(rels) r_attr = n.child.right.result_format(rels) tokens = tokenize_select(n.prop) groups = [] temp = [] for i in tokens: if i == 'and' and i.level == 0: groups.append(temp) temp = [] else: temp.append(i) if len(temp) != 0: groups.append(temp) temp = [] left = [] right = [] both = [] for i in groups: l_fields = False # has fields in left? r_fields = False # has fields in left? for j in set(i).difference(sel_op): j = j.split('.')[0] if j in l_attr: # Field in left l_fields = True if j in r_attr: # Field in right r_fields = True if l_fields and r_fields: # Fields in both both.append(i) elif l_fields: left.append(i) elif r_fields: right.append(i) else: # Unknown.. adding in both both.append(i) # Preparing left selection if len(left) > 0: changes = 1 l_node = parser.node() l_node.name = SELECTION l_node.kind = parser.UNARY l_node.child = n.child.left l_node.prop = '' n.child.left = l_node while len(left) > 0: c = left.pop(0) for i in c: l_node.prop += i + ' ' if len(left) > 0: l_node.prop += ' and ' if '(' in l_node.prop: l_node.prop = '(%s)' % l_node.prop # Preparing right selection if len(right) > 0: changes = 1 r_node = parser.node() r_node.name = SELECTION r_node.prop = '' r_node.kind = parser.UNARY r_node.child = n.child.right n.child.right = r_node while len(right) > 0: c = right.pop(0) for i in c: r_node.prop += i + ' ' if len(right) > 0: r_node.prop += ' and ' if '(' in r_node.prop: r_node.prop = '(%s)' % r_node.prop # Changing main selection n.prop = '' if len(both) != 0: while len(both) > 0: c = both.pop(0) for i in c: n.prop += i + ' ' if len(both) > 0: n.prop += ' and ' if '(' in n.prop: n.prop = '(%s)' % n.prop else: # No need for general select replace_node(n, n.child) return changes + recoursive_scan(selection_and_product, n, rels)
def selection_and_product(n, rels): '''This function locates things like σ k (R*Q) and converts them into σ l (σ j (R) * σ i (Q)). Where j contains only attributes belonging to R, i contains attributes belonging to Q and l contains attributes belonging to both''' changes = 0 if n.name == SELECTION and n.child.name in (PRODUCT, JOIN, JOIN_LEFT, JOIN_RIGHT, JOIN_FULL): l_attr = n.child.left.result_format(rels) r_attr = n.child.right.result_format(rels) tokens = tokenize_select(n.prop) groups = [] temp = [] for i in tokens: if i == 'and' and i.level == 0: groups.append(temp) temp = [] else: temp.append(i) if len(temp) != 0: groups.append(temp) temp = [] left = [] right = [] both = [] for i in groups: l_fields = False #has fields in left? r_fields = False #has fields in left? for j in set(i).difference(sel_op): j = j.split('.')[0] if j in l_attr: #Field in left l_fields = True if j in r_attr: #Field in right r_fields = True if l_fields and r_fields: #Fields in both both.append(i) elif l_fields: left.append(i) elif r_fields: right.append(i) else: #Unknown.. adding in both both.append(i) #Preparing left selection if len(left) > 0: changes = 1 l_node = parser.node() l_node.name = SELECTION l_node.kind = parser.UNARY l_node.child = n.child.left l_node.prop = '' n.child.left = l_node while len(left) > 0: c = left.pop(0) for i in c: l_node.prop += i + ' ' if len(left) > 0: l_node.prop += ' and ' if '(' in l_node.prop: l_node.prop = '(%s)' % l_node.prop #Preparing right selection if len(right) > 0: changes = 1 r_node = parser.node() r_node.name = SELECTION r_node.prop = '' r_node.kind = parser.UNARY r_node.child = n.child.right n.child.right = r_node while len(right) > 0: c = right.pop(0) for i in c: r_node.prop += i + ' ' if len(right) > 0: r_node.prop += ' and ' if '(' in r_node.prop: r_node.prop = '(%s)' % r_node.prop #Changing main selection n.prop = '' if len(both) != 0: while len(both) > 0: c = both.pop(0) for i in c: n.prop += i + ' ' if len(both) > 0: n.prop += ' and ' if '(' in n.prop: n.prop = '(%s)' % n.prop else: #No need for general select replace_node(n, n.child) return changes + recoursive_scan(selection_and_product, n, rels)