Query splitter complete

master
Salvo 'LtWorf' Tomaselli 2016-08-16 11:15:56 +07:00
parent bd1c3a208c
commit c4e258bbf9
3 changed files with 66 additions and 4 deletions

@ -25,6 +25,7 @@
from relational import optimizations
from relational import parser
from relational import querysplit
from relational.maintenance import UserInterface
@ -57,8 +58,8 @@ def optimize_program(code, rels):
parsed = parser.tree(query)
optimizations.replace_leaves(parsed, context)
context[res] = parsed
result = optimize_all(context[last_res], rels)
return result
node = optimize_all(context[last_res], rels, tostr=False)
return querysplit.split(node, rels)
def optimize_all(expression, rels, specific=True, general=True, debug=None,tostr=True):

@ -19,6 +19,52 @@
# This module splits a query into a program.
from relational import parser
class Program:
def __init__(self, rels):
self.queries = []
self.dictionary = {} # Key is the query, value is the relation
self.vgen = vargen(rels, 'optm_')
def __str__(self):
r = ''
for q in self.queries:
r += '%s = %s' % (q[0], q[1]) + '\n'
return r.rstrip()
def append_query(self, node):
strnode = str(node)
rel = self.dictionary.get(strnode)
if rel:
return rel
qname = next(self.vgen)
self.queries.append((qname, node))
n = parser.Node()
n.kind = parser.RELATION
n.name = qname
self.dictionary[strnode] = n
return n
def _separate(node, program):
if node.kind == parser.UNARY and node.child.kind != parser.RELATION:
_separate(node.child, program)
rel = program.append_query(node.child)
node.child = rel
elif node.kind == parser.BINARY:
if node.left.kind != parser.RELATION:
_separate(node.left, program)
rel = program.append_query(node.left)
node.left = rel
if node.right.kind != parser.RELATION:
_separate(node.right, program)
rel = program.append_query(node.right)
node.right = rel
program.append_query(node)
def vargen(avoid, prefix=''):
'''
Generates temp variables.
@ -40,3 +86,14 @@ def vargen(avoid, prefix=''):
if r not in avoid:
yield r
count += 1
def split(node, rels):
'''
Split a query into a program.
The idea is that if there are duplicated subdtrees they
get executed only once.
'''
p = Program(rels)
_separate(node, p)
return str(p)

@ -15,6 +15,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# author Salvo "LtWorf" Tomaselli <tiposchi@tiscali.it>
import base64
import sys
from PyQt5 import QtCore, QtWidgets, QtGui
@ -360,10 +361,13 @@ class relForm(QtWidgets.QMainWindow):
self.settings.setValue('maingui/geometry', self.saveGeometry())
self.settings.setValue('maingui/windowState', self.saveState())
self.settings.setValue('maingui/splitter', self.ui.splitter.saveState())
self.settings.setValue('maingui/relations', self.user_interface.session_dump())
self.settings.setValue('maingui/relations', base64.b64encode(self.user_interface.session_dump()).decode())
def _restore_settings(self):
self.user_interface.session_restore(self.settings.value('maingui/relations'))
try:
self.user_interface.session_restore(base64.b64decode(self.settings.value('maingui/relations')))
except:
pass
self.updateRelations()
self.setMultiline(self.settings.value('multiline', 'false') == 'true')