Enable one optimization
Due to the fact that the nodes are different classes, this required some refactor.
This commit is contained in:
parent
3e524278e8
commit
0dcd639c9d
@ -30,6 +30,7 @@
|
||||
|
||||
from io import StringIO
|
||||
from tokenize import generate_tokens
|
||||
from typing import Tuple
|
||||
|
||||
|
||||
from relational import parser
|
||||
@ -98,36 +99,7 @@ def replace_node(replace, replacement):
|
||||
replace.left = replacement.left
|
||||
|
||||
|
||||
def recoursive_scan(function, node, rels=None):
|
||||
'''Does a recoursive optimization on the tree.
|
||||
|
||||
This function will recoursively execute the function given
|
||||
as "function" parameter starting from node to all the tree.
|
||||
if rels is provided it will be passed as argument to the function.
|
||||
Otherwise the function will be called just on the node.
|
||||
|
||||
Result value: function is supposed to return the amount of changes
|
||||
it has performed on the tree.
|
||||
The various result will be added up and this final value will be the
|
||||
returned value.'''
|
||||
changes = 0
|
||||
# recoursive scan
|
||||
if node.kind == parser.UNARY:
|
||||
if rels != None:
|
||||
changes += function(node.child, rels)
|
||||
else:
|
||||
changes += function(node.child)
|
||||
elif node.kind == parser.BINARY:
|
||||
if rels != None:
|
||||
changes += function(node.right, rels)
|
||||
changes += function(node.left, rels)
|
||||
else:
|
||||
changes += function(node.right)
|
||||
changes += function(node.left)
|
||||
return changes
|
||||
|
||||
|
||||
def duplicated_select(n: parser.Node) -> int:
|
||||
def duplicated_select(n: parser.Node) -> Tuple[parser.Node, int]:
|
||||
'''This function locates and deletes things like
|
||||
σ a ( σ a(C)) and the ones like σ a ( σ b(C))
|
||||
replacing the 1st one with a single select and
|
||||
@ -135,19 +107,22 @@ def duplicated_select(n: parser.Node) -> int:
|
||||
in and
|
||||
'''
|
||||
changes = 0
|
||||
if n.name == SELECTION and n.child.name == SELECTION:
|
||||
while n.name == SELECTION and n.child.name == SELECTION:
|
||||
changes += 1
|
||||
prop = n.prop
|
||||
|
||||
if n.prop != n.child.prop: # Nested but different, joining them
|
||||
n.prop = n.prop + " and " + n.child.prop
|
||||
prop = n.prop + " and " + n.child.prop
|
||||
|
||||
# This adds parenthesis if they are needed
|
||||
if n.child.prop.startswith('(') or n.prop.startswith('('):
|
||||
n.prop = '(%s)' % n.prop
|
||||
|
||||
n.child = n.child.child
|
||||
changes = 1
|
||||
changes += duplicated_select(n)
|
||||
|
||||
return changes + recoursive_scan(duplicated_select, n)
|
||||
prop = '(%s)' % prop
|
||||
n = parser.Unary(
|
||||
SELECTION,
|
||||
prop,
|
||||
n.child.child,
|
||||
)
|
||||
return n, changes
|
||||
|
||||
|
||||
def futile_union_intersection_subtraction(n: parser.Node) -> int:
|
||||
@ -706,10 +681,10 @@ def useless_projection(n, rels) -> int:
|
||||
changes = 1
|
||||
replace_node(n, n.child)
|
||||
|
||||
return changes + recoursive_scan(useless_projection, n, rels)
|
||||
return changes + recursive_scan(useless_projection, n, rels)
|
||||
|
||||
general_optimizations = [
|
||||
#duplicated_select,
|
||||
duplicated_select,
|
||||
#down_to_unions_subtractions_intersections,
|
||||
#duplicated_projection,
|
||||
#selection_inside_projection,
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Relational
|
||||
# Copyright (C) 2008-2016 Salvo "LtWorf" Tomaselli
|
||||
# Copyright (C) 2008-2020 Salvo "LtWorf" Tomaselli
|
||||
#
|
||||
# Relational is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -22,10 +22,10 @@
|
||||
# relational query, or it can be a parse tree for a relational expression (ie: class parser.node).
|
||||
# The functions will always return a string with the optimized query, but if a parse tree was provided,
|
||||
# the parse tree itself will be modified accordingly.
|
||||
from typing import Union, Optional, Dict, Any
|
||||
from typing import Union, Optional, Dict, Any, Tuple
|
||||
|
||||
from relational import optimizations
|
||||
from relational.parser import Node, RELATION, UNARY, BINARY, op_functions, tokenize, tree
|
||||
from relational.parser import Node, Variable, Unary, Binary, op_functions, tokenize, tree
|
||||
from relational import querysplit
|
||||
from relational.maintenance import UserInterface
|
||||
|
||||
@ -88,10 +88,10 @@ def optimize_all(expression: Union[str, Node], rels: ContextDict, specific: bool
|
||||
total += res
|
||||
if general:
|
||||
for i in optimizations.general_optimizations:
|
||||
res = i(n) # Performs the optimization
|
||||
if res != 0 and dbg:
|
||||
n, c = recursive_scan(i, n, None)
|
||||
if c != 0 and dbg:
|
||||
debug.append(str(n))
|
||||
total += res
|
||||
total += c
|
||||
if tostr:
|
||||
return str(n)
|
||||
else:
|
||||
@ -117,3 +117,35 @@ def general_optimize(expression):
|
||||
|
||||
Return value: this will return an optimized version of the expression'''
|
||||
return optimize_all(expression, None, specific=False, general=True)
|
||||
|
||||
|
||||
def recursive_scan(function, node, rels) -> Tuple[Node, int]:
|
||||
'''Does a recursive optimization on the tree.
|
||||
|
||||
This function will recursively execute the function given
|
||||
as "function" parameter starting from node to all the tree.
|
||||
if rels is provided it will be passed as argument to the function.
|
||||
Otherwise the function will be called just on the node.
|
||||
|
||||
Result value: function is supposed to return the amount of changes
|
||||
it has performed on the tree.
|
||||
The various result will be added up and this final value will be the
|
||||
returned value.'''
|
||||
|
||||
args = []
|
||||
if rels:
|
||||
args.append(rels)
|
||||
|
||||
changes = 0
|
||||
node, c = function(node, *args)
|
||||
changes += c
|
||||
|
||||
if isinstance(node, Unary):
|
||||
node.child, c = recursive_scan(function, node.child, rels)
|
||||
changes += c
|
||||
elif isinstance(node, Binary):
|
||||
node.left, c = recursive_scan(function, node.left, rels)
|
||||
changes += c
|
||||
node.right, c = recursive_scan(function, node.right, rels)
|
||||
changes += c
|
||||
return node, changes
|
||||
|
Loading…
x
Reference in New Issue
Block a user