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 io import StringIO
|
||||||
from tokenize import generate_tokens
|
from tokenize import generate_tokens
|
||||||
|
from typing import Tuple
|
||||||
|
|
||||||
|
|
||||||
from relational import parser
|
from relational import parser
|
||||||
@ -98,36 +99,7 @@ def replace_node(replace, replacement):
|
|||||||
replace.left = replacement.left
|
replace.left = replacement.left
|
||||||
|
|
||||||
|
|
||||||
def recoursive_scan(function, node, rels=None):
|
def duplicated_select(n: parser.Node) -> Tuple[parser.Node, int]:
|
||||||
'''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:
|
|
||||||
'''This function locates and deletes things like
|
'''This function locates and deletes things like
|
||||||
σ a ( σ a(C)) and the ones like σ a ( σ b(C))
|
σ a ( σ a(C)) and the ones like σ a ( σ b(C))
|
||||||
replacing the 1st one with a single select and
|
replacing the 1st one with a single select and
|
||||||
@ -135,19 +107,22 @@ def duplicated_select(n: parser.Node) -> int:
|
|||||||
in and
|
in and
|
||||||
'''
|
'''
|
||||||
changes = 0
|
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
|
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
|
# This adds parenthesis if they are needed
|
||||||
if n.child.prop.startswith('(') or n.prop.startswith('('):
|
if n.child.prop.startswith('(') or n.prop.startswith('('):
|
||||||
n.prop = '(%s)' % n.prop
|
prop = '(%s)' % prop
|
||||||
|
n = parser.Unary(
|
||||||
n.child = n.child.child
|
SELECTION,
|
||||||
changes = 1
|
prop,
|
||||||
changes += duplicated_select(n)
|
n.child.child,
|
||||||
|
)
|
||||||
return changes + recoursive_scan(duplicated_select, n)
|
return n, changes
|
||||||
|
|
||||||
|
|
||||||
def futile_union_intersection_subtraction(n: parser.Node) -> int:
|
def futile_union_intersection_subtraction(n: parser.Node) -> int:
|
||||||
@ -706,10 +681,10 @@ def useless_projection(n, rels) -> int:
|
|||||||
changes = 1
|
changes = 1
|
||||||
replace_node(n, n.child)
|
replace_node(n, n.child)
|
||||||
|
|
||||||
return changes + recoursive_scan(useless_projection, n, rels)
|
return changes + recursive_scan(useless_projection, n, rels)
|
||||||
|
|
||||||
general_optimizations = [
|
general_optimizations = [
|
||||||
#duplicated_select,
|
duplicated_select,
|
||||||
#down_to_unions_subtractions_intersections,
|
#down_to_unions_subtractions_intersections,
|
||||||
#duplicated_projection,
|
#duplicated_projection,
|
||||||
#selection_inside_projection,
|
#selection_inside_projection,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# Relational
|
# 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
|
# Relational is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# 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).
|
# 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 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.
|
# 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 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 import querysplit
|
||||||
from relational.maintenance import UserInterface
|
from relational.maintenance import UserInterface
|
||||||
|
|
||||||
@ -88,10 +88,10 @@ def optimize_all(expression: Union[str, Node], rels: ContextDict, specific: bool
|
|||||||
total += res
|
total += res
|
||||||
if general:
|
if general:
|
||||||
for i in optimizations.general_optimizations:
|
for i in optimizations.general_optimizations:
|
||||||
res = i(n) # Performs the optimization
|
n, c = recursive_scan(i, n, None)
|
||||||
if res != 0 and dbg:
|
if c != 0 and dbg:
|
||||||
debug.append(str(n))
|
debug.append(str(n))
|
||||||
total += res
|
total += c
|
||||||
if tostr:
|
if tostr:
|
||||||
return str(n)
|
return str(n)
|
||||||
else:
|
else:
|
||||||
@ -117,3 +117,35 @@ def general_optimize(expression):
|
|||||||
|
|
||||||
Return value: this will return an optimized version of the expression'''
|
Return value: this will return an optimized version of the expression'''
|
||||||
return optimize_all(expression, None, specific=False, general=True)
|
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