Changed about and README to not point to galileo anymore
This commit is contained in:
parent
f31d0dea28
commit
556eecc118
7
README
7
README
@ -2,6 +2,9 @@ To launch the application, run
|
|||||||
|
|
||||||
./relational_gui.py
|
./relational_gui.py
|
||||||
|
|
||||||
If it needs some dependencies, check this page:
|
Language definition is here:
|
||||||
http://galileo.dmi.unict.it/wiki/relational/doku.php?id=download#install
|
https://github.com/ltworf/relational/wiki/Grammar-and-language
|
||||||
|
|
||||||
|
If it needs some dependencies:
|
||||||
|
Qt4, Python 2.7, either PyQT4 or Pyside.
|
||||||
|
|
||||||
|
20
driver.py
20
driver.py
@ -37,6 +37,7 @@ rels={}
|
|||||||
examples_path = 'samples/'
|
examples_path = 'samples/'
|
||||||
tests_path = 'test/'
|
tests_path = 'test/'
|
||||||
|
|
||||||
|
|
||||||
def readfile(fname):
|
def readfile(fname):
|
||||||
'''Reads a file as string and returns its content'''
|
'''Reads a file as string and returns its content'''
|
||||||
fd = open(fname)
|
fd = open(fname)
|
||||||
@ -60,6 +61,7 @@ def load_relations():
|
|||||||
rels[relname] = relation.relation('%s%s' % (examples_path, i))
|
rels[relname] = relation.relation('%s%s' % (examples_path, i))
|
||||||
print 'done'
|
print 'done'
|
||||||
|
|
||||||
|
|
||||||
def execute_tests():
|
def execute_tests():
|
||||||
|
|
||||||
py_bad = 0
|
py_bad = 0
|
||||||
@ -72,7 +74,6 @@ def execute_tests():
|
|||||||
ex_good = 0
|
ex_good = 0
|
||||||
ex_tot = 0
|
ex_tot = 0
|
||||||
|
|
||||||
|
|
||||||
for i in os.listdir(tests_path):
|
for i in os.listdir(tests_path):
|
||||||
if i.endswith('.query'):
|
if i.endswith('.query'):
|
||||||
q_tot += 1
|
q_tot += 1
|
||||||
@ -112,7 +113,6 @@ def execute_tests():
|
|||||||
if ex_bad > 0:
|
if ex_bad > 0:
|
||||||
print colorize("Failed tests count: %d" % ex_bad, COLOR_RED)
|
print colorize("Failed tests count: %d" % ex_bad, COLOR_RED)
|
||||||
|
|
||||||
|
|
||||||
print colorize("Total results", COLOR_CYAN)
|
print colorize("Total results", COLOR_CYAN)
|
||||||
if q_bad + py_bad + ex_bad == 0:
|
if q_bad + py_bad + ex_bad == 0:
|
||||||
print colorize("No failed tests", COLOR_GREEN)
|
print colorize("No failed tests", COLOR_GREEN)
|
||||||
@ -137,11 +137,9 @@ def run_exec_test(testname):
|
|||||||
expr = readfile('%s%s.exec' % (tests_path, testname))
|
expr = readfile('%s%s.exec' % (tests_path, testname))
|
||||||
exec(expr, glob) # Evaluating the expression
|
exec(expr, glob) # Evaluating the expression
|
||||||
|
|
||||||
|
|
||||||
expr = readfile('%s%s.result' % (tests_path, testname))
|
expr = readfile('%s%s.result' % (tests_path, testname))
|
||||||
exp_result = eval(expr, rels) # Evaluating the expression
|
exp_result = eval(expr, rels) # Evaluating the expression
|
||||||
|
|
||||||
|
|
||||||
if isinstance(exp_result, dict):
|
if isinstance(exp_result, dict):
|
||||||
fields_ok = True
|
fields_ok = True
|
||||||
|
|
||||||
@ -160,6 +158,7 @@ def run_exec_test(testname):
|
|||||||
print colorize('=====================================', COLOR_RED)
|
print colorize('=====================================', COLOR_RED)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def run_py_test(testname):
|
def run_py_test(testname):
|
||||||
'''Runs a python test, which evaluates expressions directly rather than queries'''
|
'''Runs a python test, which evaluates expressions directly rather than queries'''
|
||||||
print "Running expression python test: " + colorize(testname, COLOR_MAGENTA)
|
print "Running expression python test: " + colorize(testname, COLOR_MAGENTA)
|
||||||
@ -185,6 +184,7 @@ def run_py_test(testname):
|
|||||||
print colorize('=====================================', COLOR_RED)
|
print colorize('=====================================', COLOR_RED)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def run_test(testname):
|
def run_test(testname):
|
||||||
'''Runs a specific test executing the file
|
'''Runs a specific test executing the file
|
||||||
testname.query
|
testname.query
|
||||||
@ -194,22 +194,26 @@ def run_test(testname):
|
|||||||
optimized'''
|
optimized'''
|
||||||
print "Running test: " + colorize(testname, COLOR_MAGENTA)
|
print "Running test: " + colorize(testname, COLOR_MAGENTA)
|
||||||
|
|
||||||
query=None;expr=None;o_query=None;o_expr=None
|
query = None
|
||||||
|
expr = None
|
||||||
|
o_query = None
|
||||||
|
o_expr = None
|
||||||
result_rel = None
|
result_rel = None
|
||||||
result = None
|
result = None
|
||||||
o_result = None
|
o_result = None
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result_rel = relation.relation('%s%s.result' % (tests_path, testname))
|
result_rel = relation.relation('%s%s.result' % (tests_path, testname))
|
||||||
|
|
||||||
query=unicode(readfile('%s%s.query' % (tests_path,testname)).strip(),'utf8')
|
query = unicode(
|
||||||
|
readfile('%s%s.query' % (tests_path, testname)).strip(), 'utf8')
|
||||||
o_query = optimizer.optimize_all(query, rels)
|
o_query = optimizer.optimize_all(query, rels)
|
||||||
|
|
||||||
expr = parser.parse(query) # Converting expression to python string
|
expr = parser.parse(query) # Converting expression to python string
|
||||||
result = eval(expr, rels) # Evaluating the expression
|
result = eval(expr, rels) # Evaluating the expression
|
||||||
|
|
||||||
o_expr=parser.parse(o_query)#Converting expression to python string
|
o_expr = parser.parse(
|
||||||
|
o_query) # Converting expression to python string
|
||||||
o_result = eval(o_expr, rels) # Evaluating the expression
|
o_result = eval(o_expr, rels) # Evaluating the expression
|
||||||
|
|
||||||
c_expr = parser.tree(query).toCode() # Converting to python code
|
c_expr = parser.tree(query).toCode() # Converting to python code
|
||||||
|
@ -23,6 +23,7 @@ import httplib
|
|||||||
import urllib
|
import urllib
|
||||||
import relation
|
import relation
|
||||||
|
|
||||||
|
|
||||||
def send_survey(data):
|
def send_survey(data):
|
||||||
'''Sends the survey. Data must be a dictionary.
|
'''Sends the survey. Data must be a dictionary.
|
||||||
returns the http response'''
|
returns the http response'''
|
||||||
@ -33,14 +34,11 @@ def send_survey(data):
|
|||||||
|
|
||||||
# sends the string
|
# sends the string
|
||||||
params = urllib.urlencode({'survey': post})
|
params = urllib.urlencode({'survey': post})
|
||||||
headers = {"Content-type": "application/x-www-form-urlencoded","Accept": "text/plain"}
|
headers = {"Content-type":
|
||||||
#connection = httplib.HTTPConnection('galileo.dmi.unict.it')
|
"application/x-www-form-urlencoded", "Accept": "text/plain"}
|
||||||
#connection.request("POST","/~ltworf/survey.php",params,headers)
|
|
||||||
|
|
||||||
connection = httplib.HTTPConnection('feedback-ltworf.appspot.com')
|
connection = httplib.HTTPConnection('feedback-ltworf.appspot.com')
|
||||||
connection.request("POST", "/feedback/relational", params, headers)
|
connection.request("POST", "/feedback/relational", params, headers)
|
||||||
|
|
||||||
|
|
||||||
return connection.getresponse()
|
return connection.getresponse()
|
||||||
|
|
||||||
|
|
||||||
@ -60,6 +58,7 @@ def check_latest_version():
|
|||||||
|
|
||||||
|
|
||||||
class interface (object):
|
class interface (object):
|
||||||
|
|
||||||
'''It is used to provide services to the user interfaces, in order to
|
'''It is used to provide services to the user interfaces, in order to
|
||||||
reduce the amount of duplicated code present in different user interfaces.
|
reduce the amount of duplicated code present in different user interfaces.
|
||||||
'''
|
'''
|
||||||
|
@ -34,7 +34,9 @@ import parser
|
|||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
from tokenize import generate_tokens
|
from tokenize import generate_tokens
|
||||||
|
|
||||||
sel_op=('//=','**=','and','not','in','//','**','<<','>>','==','!=','>=','<=','+=','-=','*=','/=','%=','or','+','-','*','/','&','|','^','~','<','>','%','=','(',')',',','[',']')
|
sel_op = (
|
||||||
|
'//=', '**=', 'and', 'not', 'in', '//', '**', '<<', '>>', '==', '!=', '>=', '<=', '+=', '-=',
|
||||||
|
'*=', '/=', '%=', 'or', '+', '-', '*', '/', '&', '|', '^', '~', '<', '>', '%', '=', '(', ')', ',', '[', ']')
|
||||||
|
|
||||||
PRODUCT = parser.PRODUCT
|
PRODUCT = parser.PRODUCT
|
||||||
DIFFERENCE = parser.DIFFERENCE
|
DIFFERENCE = parser.DIFFERENCE
|
||||||
@ -64,6 +66,7 @@ def replace_node(replace,replacement):
|
|||||||
replace.right = replacement.right
|
replace.right = replacement.right
|
||||||
replace.left = replacement.left
|
replace.left = replacement.left
|
||||||
|
|
||||||
|
|
||||||
def recoursive_scan(function, node, rels=None):
|
def recoursive_scan(function, node, rels=None):
|
||||||
'''Does a recoursive optimization on the tree.
|
'''Does a recoursive optimization on the tree.
|
||||||
|
|
||||||
@ -115,6 +118,7 @@ def duplicated_select(n):
|
|||||||
|
|
||||||
return changes + recoursive_scan(duplicated_select, n)
|
return changes + recoursive_scan(duplicated_select, n)
|
||||||
|
|
||||||
|
|
||||||
def futile_union_intersection_subtraction(n):
|
def futile_union_intersection_subtraction(n):
|
||||||
'''This function locates things like r ᑌ r, and replaces them with r.
|
'''This function locates things like r ᑌ r, and replaces them with r.
|
||||||
R ᑌ R --> R
|
R ᑌ R --> R
|
||||||
@ -170,6 +174,7 @@ def futile_union_intersection_subtraction(n):
|
|||||||
|
|
||||||
return changes + recoursive_scan(futile_union_intersection_subtraction, n)
|
return changes + recoursive_scan(futile_union_intersection_subtraction, n)
|
||||||
|
|
||||||
|
|
||||||
def 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
|
'''This funcion locates things like σ i==2 (c ᑌ d), where the union
|
||||||
can be a subtraction and an intersection and replaces them with
|
can be a subtraction and an intersection and replaces them with
|
||||||
@ -200,6 +205,7 @@ def down_to_unions_subtractions_intersections(n):
|
|||||||
|
|
||||||
return changes + recoursive_scan(down_to_unions_subtractions_intersections, n)
|
return changes + recoursive_scan(down_to_unions_subtractions_intersections, n)
|
||||||
|
|
||||||
|
|
||||||
def duplicated_projection(n):
|
def duplicated_projection(n):
|
||||||
'''This function locates thing like π i ( π j (R)) and replaces
|
'''This function locates thing like π i ( π j (R)) and replaces
|
||||||
them with π i (R)'''
|
them with π i (R)'''
|
||||||
@ -211,6 +217,7 @@ def duplicated_projection(n):
|
|||||||
|
|
||||||
return changes + recoursive_scan(duplicated_projection, n)
|
return changes + recoursive_scan(duplicated_projection, n)
|
||||||
|
|
||||||
|
|
||||||
def selection_inside_projection(n):
|
def selection_inside_projection(n):
|
||||||
'''This function locates things like σ j (π k(R)) and
|
'''This function locates things like σ j (π k(R)) and
|
||||||
converts them into π k(σ j (R))'''
|
converts them into π k(σ j (R))'''
|
||||||
@ -226,6 +233,7 @@ def selection_inside_projection(n):
|
|||||||
|
|
||||||
return changes + recoursive_scan(selection_inside_projection, n)
|
return changes + recoursive_scan(selection_inside_projection, n)
|
||||||
|
|
||||||
|
|
||||||
def swap_union_renames(n):
|
def swap_union_renames(n):
|
||||||
'''This function locates things like
|
'''This function locates things like
|
||||||
ρ a➡b(R) ᑌ ρ a➡b(Q)
|
ρ a➡b(R) ᑌ ρ a➡b(Q)
|
||||||
@ -263,6 +271,7 @@ def swap_union_renames(n):
|
|||||||
|
|
||||||
return changes + recoursive_scan(swap_union_renames, n)
|
return changes + recoursive_scan(swap_union_renames, n)
|
||||||
|
|
||||||
|
|
||||||
def futile_renames(n):
|
def futile_renames(n):
|
||||||
'''This function purges renames like id->id'''
|
'''This function purges renames like id->id'''
|
||||||
changes = 0
|
changes = 0
|
||||||
@ -276,7 +285,8 @@ def futile_renames(n):
|
|||||||
for i in n.prop.split(','):
|
for i in n.prop.split(','):
|
||||||
q = i.split(ARROW)
|
q = i.split(ARROW)
|
||||||
_vars[q[0].strip()] = q[1].strip()
|
_vars[q[0].strip()] = q[1].strip()
|
||||||
#Scans dictionary to locate things like "a->b,b->c" and replace them with "a->c"
|
# Scans dictionary to locate things like "a->b,b->c" and replace them
|
||||||
|
# with "a->c"
|
||||||
for key in list(_vars.keys()):
|
for key in list(_vars.keys()):
|
||||||
try:
|
try:
|
||||||
value = _vars[key]
|
value = _vars[key]
|
||||||
@ -297,6 +307,7 @@ def futile_renames(n):
|
|||||||
|
|
||||||
return changes + recoursive_scan(futile_renames, n)
|
return changes + recoursive_scan(futile_renames, n)
|
||||||
|
|
||||||
|
|
||||||
def subsequent_renames(n):
|
def subsequent_renames(n):
|
||||||
'''This function removes redoundant subsequent renames joining them into one'''
|
'''This function removes redoundant subsequent renames joining them into one'''
|
||||||
|
|
||||||
@ -317,7 +328,8 @@ def subsequent_renames(n):
|
|||||||
for i in n.prop.split(','):
|
for i in n.prop.split(','):
|
||||||
q = i.split(ARROW)
|
q = i.split(ARROW)
|
||||||
_vars[q[0].strip()] = q[1].strip()
|
_vars[q[0].strip()] = q[1].strip()
|
||||||
#Scans dictionary to locate things like "a->b,b->c" and replace them with "a->c"
|
# Scans dictionary to locate things like "a->b,b->c" and replace them
|
||||||
|
# with "a->c"
|
||||||
for key in list(_vars.keys()):
|
for key in list(_vars.keys()):
|
||||||
try:
|
try:
|
||||||
value = _vars[key]
|
value = _vars[key]
|
||||||
@ -345,9 +357,11 @@ def subsequent_renames(n):
|
|||||||
|
|
||||||
return changes + recoursive_scan(subsequent_renames, n)
|
return changes + recoursive_scan(subsequent_renames, n)
|
||||||
|
|
||||||
|
|
||||||
class level_string(str):
|
class level_string(str):
|
||||||
level = 0
|
level = 0
|
||||||
|
|
||||||
|
|
||||||
def tokenize_select(expression):
|
def tokenize_select(expression):
|
||||||
'''This function returns the list of tokens present in a
|
'''This function returns the list of tokens present in a
|
||||||
selection. The expression can contain parenthesis.
|
selection. The expression can contain parenthesis.
|
||||||
@ -368,7 +382,6 @@ def tokenize_select(expression):
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
level = 0
|
level = 0
|
||||||
for i in range(len(l)):
|
for i in range(len(l)):
|
||||||
l[i] = level_string(l[i])
|
l[i] = level_string(l[i])
|
||||||
@ -381,6 +394,7 @@ def tokenize_select(expression):
|
|||||||
|
|
||||||
return l
|
return l
|
||||||
|
|
||||||
|
|
||||||
def swap_rename_projection(n):
|
def swap_rename_projection(n):
|
||||||
'''This function locates things like π k(ρ j(R))
|
'''This function locates things like π k(ρ j(R))
|
||||||
and replaces them with ρ j(π k(R)).
|
and replaces them with ρ j(π k(R)).
|
||||||
@ -422,9 +436,9 @@ def swap_rename_projection(n):
|
|||||||
n.child.prop += i + ','
|
n.child.prop += i + ','
|
||||||
n.child.prop = n.child.prop[:-1]
|
n.child.prop = n.child.prop[:-1]
|
||||||
|
|
||||||
|
|
||||||
return changes + recoursive_scan(swap_rename_projection, n)
|
return changes + recoursive_scan(swap_rename_projection, n)
|
||||||
|
|
||||||
|
|
||||||
def swap_rename_select(n):
|
def swap_rename_select(n):
|
||||||
'''This function locates things like σ k(ρ j(R)) and replaces
|
'''This function locates things like σ k(ρ j(R)) and replaces
|
||||||
them with ρ j(σ k(R)). Renaming the attributes used in the
|
them with ρ j(σ k(R)). Renaming the attributes used in the
|
||||||
@ -449,7 +463,8 @@ def swap_rename_select(n):
|
|||||||
if len(splitted) == 1:
|
if len(splitted) == 1:
|
||||||
_tokens[i] = _vars[_tokens[i].split('.')[0]]
|
_tokens[i] = _vars[_tokens[i].split('.')[0]]
|
||||||
else:
|
else:
|
||||||
_tokens[i]=_vars[_tokens[i].split('.')[0]]+'.'+splitted[1]
|
_tokens[i] = _vars[
|
||||||
|
_tokens[i].split('.')[0]] + '.' + splitted[1]
|
||||||
|
|
||||||
# Swapping operators
|
# Swapping operators
|
||||||
n.name = RENAME
|
n.name = RENAME
|
||||||
@ -462,6 +477,7 @@ def swap_rename_select(n):
|
|||||||
|
|
||||||
return changes + recoursive_scan(swap_rename_select, n)
|
return changes + recoursive_scan(swap_rename_select, n)
|
||||||
|
|
||||||
|
|
||||||
def select_union_intersect_subtract(n):
|
def select_union_intersect_subtract(n):
|
||||||
'''This function locates things like σ i(a) ᑌ σ q(a)
|
'''This function locates things like σ i(a) ᑌ σ q(a)
|
||||||
and replaces them with σ (i OR q) (a)
|
and replaces them with σ (i OR q) (a)
|
||||||
@ -498,6 +514,7 @@ def select_union_intersect_subtract(n):
|
|||||||
|
|
||||||
return changes + recoursive_scan(select_union_intersect_subtract, n)
|
return changes + recoursive_scan(select_union_intersect_subtract, n)
|
||||||
|
|
||||||
|
|
||||||
def selection_and_product(n, rels):
|
def selection_and_product(n, rels):
|
||||||
'''This function locates things like σ k (R*Q) and converts them into
|
'''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,
|
σ l (σ j (R) * σ i (Q)). Where j contains only attributes belonging to R,
|
||||||
@ -597,7 +614,9 @@ def selection_and_product(n,rels):
|
|||||||
|
|
||||||
return changes + recoursive_scan(selection_and_product, n, rels)
|
return changes + recoursive_scan(selection_and_product, n, rels)
|
||||||
|
|
||||||
general_optimizations=[duplicated_select,down_to_unions_subtractions_intersections,duplicated_projection,selection_inside_projection,subsequent_renames,swap_rename_select,futile_union_intersection_subtraction,swap_union_renames,swap_rename_projection,select_union_intersect_subtract]
|
general_optimizations = [
|
||||||
|
duplicated_select, down_to_unions_subtractions_intersections, duplicated_projection, selection_inside_projection,
|
||||||
|
subsequent_renames, swap_rename_select, futile_union_intersection_subtraction, swap_union_renames, swap_rename_projection, select_union_intersect_subtract]
|
||||||
specific_optimizations = [selection_and_product]
|
specific_optimizations = [selection_and_product]
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -43,6 +43,7 @@ tokenize=parser.tokenize
|
|||||||
tree = parser.tree
|
tree = parser.tree
|
||||||
# End of the stuff
|
# End of the stuff
|
||||||
|
|
||||||
|
|
||||||
def optimize_all(expression, rels, specific=True, general=True, debug=None):
|
def optimize_all(expression, rels, specific=True, general=True, debug=None):
|
||||||
'''This function performs all the available optimizations.
|
'''This function performs all the available optimizations.
|
||||||
|
|
||||||
@ -73,15 +74,18 @@ def optimize_all(expression,rels,specific=True,general=True,debug=None):
|
|||||||
if specific:
|
if specific:
|
||||||
for i in optimizations.specific_optimizations:
|
for i in optimizations.specific_optimizations:
|
||||||
res = i(n, rels) # Performs the optimization
|
res = i(n, rels) # Performs the optimization
|
||||||
if res!=0 and dbg: debug.append(n.__str__())
|
if res != 0 and dbg:
|
||||||
|
debug.append(n.__str__())
|
||||||
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
|
res = i(n) # Performs the optimization
|
||||||
if res!=0 and dbg: debug.append(n.__str__())
|
if res != 0 and dbg:
|
||||||
|
debug.append(n.__str__())
|
||||||
total += res
|
total += res
|
||||||
return n.__str__()
|
return n.__str__()
|
||||||
|
|
||||||
|
|
||||||
def specific_optimize(expression, rels):
|
def specific_optimize(expression, rels):
|
||||||
'''This function performs specific optimizations. Means that it will need to
|
'''This function performs specific optimizations. Means that it will need to
|
||||||
know the fields used by the relations.
|
know the fields used by the relations.
|
||||||
@ -92,6 +96,7 @@ def specific_optimize(expression,rels):
|
|||||||
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, rels, specific=True, general=False)
|
return optimize_all(expression, rels, specific=True, general=False)
|
||||||
|
|
||||||
|
|
||||||
def general_optimize(expression):
|
def general_optimize(expression):
|
||||||
'''This function performs general optimizations. Means that it will not need to
|
'''This function performs general optimizations. Means that it will not need to
|
||||||
know the fields used by the relations
|
know the fields used by the relations
|
||||||
@ -110,7 +115,8 @@ if __name__=="__main__":
|
|||||||
# a= tokenize(u"π a,b (a*b)")
|
# a= tokenize(u"π a,b (a*b)")
|
||||||
# a=tokenize("(a-b*c)*(b-c)")
|
# a=tokenize("(a-b*c)*(b-c)")
|
||||||
|
|
||||||
import relation,optimizations
|
import relation
|
||||||
|
import optimizations
|
||||||
|
|
||||||
'''rels={}
|
'''rels={}
|
||||||
rels["P1"]= relation.relation("/home/salvo/dev/relational/trunk/samples/people.csv")
|
rels["P1"]= relation.relation("/home/salvo/dev/relational/trunk/samples/people.csv")
|
||||||
@ -132,7 +138,8 @@ if __name__=="__main__":
|
|||||||
(π id,name,chief,age (σ chief == i and age > a ((ρ age➡a,id➡i (π id,age (people)))*people)))ᐅᐊ(σ skill == 'C' (skills))
|
(π id,name,chief,age (σ chief == i and age > a ((ρ age➡a,id➡i (π id,age (people)))*people)))ᐅᐊ(σ skill == 'C' (skills))
|
||||||
'''
|
'''
|
||||||
|
|
||||||
#print specific_optimize("σ name==skill and age>21 and id==indice and skill=='C'(P1ᐅᐊS1)",rels)
|
# print specific_optimize("σ name==skill and age>21 and id==indice and
|
||||||
|
# skill=='C'(P1ᐅᐊS1)",rels)
|
||||||
|
|
||||||
# print n
|
# print n
|
||||||
# print n.result_format(rels)
|
# print n.result_format(rels)
|
||||||
|
@ -23,6 +23,7 @@ import optimizer
|
|||||||
import multiprocessing
|
import multiprocessing
|
||||||
import parser
|
import parser
|
||||||
|
|
||||||
|
|
||||||
def execute(tree, rels):
|
def execute(tree, rels):
|
||||||
'''This funcion executes a query in parallel.
|
'''This funcion executes a query in parallel.
|
||||||
Tree is the tree describing the query (usually obtained with
|
Tree is the tree describing the query (usually obtained with
|
||||||
@ -36,6 +37,7 @@ def execute(tree,rels):
|
|||||||
p.join()
|
p.join()
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def __p_exec__(tree, rels, q):
|
def __p_exec__(tree, rels, q):
|
||||||
'''q is the queue used for communication'''
|
'''q is the queue used for communication'''
|
||||||
if tree.kind == parser.RELATION:
|
if tree.kind == parser.RELATION:
|
||||||
@ -52,10 +54,11 @@ def __p_exec__(tree,rels,q):
|
|||||||
q.put(result)
|
q.put(result)
|
||||||
elif tree.kind == parser.BINARY:
|
elif tree.kind == parser.BINARY:
|
||||||
left_q = multiprocessing.Queue()
|
left_q = multiprocessing.Queue()
|
||||||
left_p = multiprocessing.Process(target=__p_exec__, args=(tree.left,rels,left_q,))
|
left_p = multiprocessing.Process(
|
||||||
|
target=__p_exec__, args=(tree.left, rels, left_q,))
|
||||||
right_q = multiprocessing.Queue()
|
right_q = multiprocessing.Queue()
|
||||||
right_p = multiprocessing.Process(target=__p_exec__, args=(tree.right,rels,right_q,))
|
right_p = multiprocessing.Process(
|
||||||
|
target=__p_exec__, args=(tree.right, rels, right_q,))
|
||||||
|
|
||||||
# Spawn the children
|
# Spawn the children
|
||||||
left_p.start()
|
left_p.start()
|
||||||
@ -72,6 +75,8 @@ def __p_exec__(tree,rels,q):
|
|||||||
result = __p_exec_binary__(tree, left, right)
|
result = __p_exec_binary__(tree, left, right)
|
||||||
q.put(result)
|
q.put(result)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
def __p_exec_binary__(tree, left, right):
|
def __p_exec_binary__(tree, left, right):
|
||||||
if tree.name == '*':
|
if tree.name == '*':
|
||||||
return left.product(right)
|
return left.product(right)
|
||||||
@ -92,12 +97,14 @@ def __p_exec_binary__(tree,left,right):
|
|||||||
else: # tree.name=='ᐅFULLᐊ':
|
else: # tree.name=='ᐅFULLᐊ':
|
||||||
return left.outer(right)
|
return left.outer(right)
|
||||||
|
|
||||||
|
|
||||||
def __p_exec_unary__(tree, rel):
|
def __p_exec_unary__(tree, rel):
|
||||||
if tree.name == 'π': # Projection
|
if tree.name == 'π': # Projection
|
||||||
tree.prop = tree.prop.replace(' ', '').split(',')
|
tree.prop = tree.prop.replace(' ', '').split(',')
|
||||||
result = rel.projection(tree.prop)
|
result = rel.projection(tree.prop)
|
||||||
elif tree.name == "ρ": # Rename
|
elif tree.name == "ρ": # Rename
|
||||||
#tree.prop='{\"%s\"}' % tree.prop.replace(',','\",\"').replace('➡','\":\"').replace(' ','')
|
# tree.prop='{\"%s\"}' %
|
||||||
|
# tree.prop.replace(',','\",\"').replace('➡','\":\"').replace(' ','')
|
||||||
d = {}
|
d = {}
|
||||||
tree.prop = tree.prop.replace(' ', '')
|
tree.prop = tree.prop.replace(' ', '')
|
||||||
for i in tree.prop.split(','):
|
for i in tree.prop.split(','):
|
||||||
@ -108,4 +115,3 @@ def __p_exec_unary__(tree,rel):
|
|||||||
else: # Selection
|
else: # Selection
|
||||||
result = rel.selection(tree.prop)
|
result = rel.selection(tree.prop)
|
||||||
return result
|
return result
|
||||||
|
|
@ -61,18 +61,26 @@ SELECTION=u'σ'
|
|||||||
RENAME = u'ρ'
|
RENAME = u'ρ'
|
||||||
ARROW = u'➡'
|
ARROW = u'➡'
|
||||||
|
|
||||||
b_operators=(PRODUCT,DIFFERENCE,UNION,INTERSECTION,DIVISION,JOIN,JOIN_LEFT,JOIN_RIGHT,JOIN_FULL) # List of binary operators
|
b_operators = (PRODUCT, DIFFERENCE, UNION, INTERSECTION, DIVISION,
|
||||||
|
JOIN, JOIN_LEFT, JOIN_RIGHT, JOIN_FULL) # List of binary operators
|
||||||
u_operators = (PROJECTION, SELECTION, RENAME) # List of unary operators
|
u_operators = (PROJECTION, SELECTION, RENAME) # List of unary operators
|
||||||
|
|
||||||
# Associates operator with python method
|
# Associates operator with python method
|
||||||
op_functions={PRODUCT:'product',DIFFERENCE:'difference',UNION:'union',INTERSECTION:'intersection',DIVISION:'division',JOIN:'join',JOIN_LEFT:'outer_left',JOIN_RIGHT:'outer_right',JOIN_FULL:'outer',PROJECTION:'projection',SELECTION:'selection',RENAME:'rename'}
|
op_functions = {
|
||||||
|
PRODUCT: 'product', DIFFERENCE: 'difference', UNION: 'union', INTERSECTION: 'intersection', DIVISION: 'division', JOIN: 'join',
|
||||||
|
JOIN_LEFT: 'outer_left', JOIN_RIGHT: 'outer_right', JOIN_FULL: 'outer', PROJECTION: 'projection', SELECTION: 'selection', RENAME: 'rename'}
|
||||||
|
|
||||||
|
|
||||||
class TokenizerException (Exception):
|
class TokenizerException (Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ParserException (Exception):
|
class ParserException (Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class node (object):
|
class node (object):
|
||||||
|
|
||||||
'''This class is a node of a relational expression. Leaves are relations and internal nodes are operations.
|
'''This class is a node of a relational expression. Leaves are relations and internal nodes are operations.
|
||||||
|
|
||||||
The kind property says if the node is a binary operator, unary operator or relation.
|
The kind property says if the node is a binary operator, unary operator or relation.
|
||||||
@ -103,7 +111,8 @@ class node (object):
|
|||||||
self.kind = RELATION
|
self.kind = RELATION
|
||||||
self.name = expression[0]
|
self.name = expression[0]
|
||||||
if not rtypes.is_valid_relation_name(self.name):
|
if not rtypes.is_valid_relation_name(self.name):
|
||||||
raise ParserException(u"'%s' is not a valid relation name" % self.name)
|
raise ParserException(
|
||||||
|
u"'%s' is not a valid relation name" % self.name)
|
||||||
return
|
return
|
||||||
|
|
||||||
'''Expression from right to left, searching for binary operators
|
'''Expression from right to left, searching for binary operators
|
||||||
@ -122,10 +131,12 @@ class node (object):
|
|||||||
self.name = expression[i]
|
self.name = expression[i]
|
||||||
|
|
||||||
if len(expression[:i]) == 0:
|
if len(expression[:i]) == 0:
|
||||||
raise ParserException(u"Expected left operand for '%s'" % self.name)
|
raise ParserException(
|
||||||
|
u"Expected left operand for '%s'" % self.name)
|
||||||
|
|
||||||
if len(expression[i + 1:]) == 0:
|
if len(expression[i + 1:]) == 0:
|
||||||
raise ParserException(u"Expected right operand for '%s'" % self.name)
|
raise ParserException(
|
||||||
|
u"Expected right operand for '%s'" % self.name)
|
||||||
|
|
||||||
self.left = node(expression[:i])
|
self.left = node(expression[:i])
|
||||||
self.right = node(expression[i + 1:])
|
self.right = node(expression[i + 1:])
|
||||||
@ -137,7 +148,8 @@ class node (object):
|
|||||||
self.name = expression[i]
|
self.name = expression[i]
|
||||||
|
|
||||||
if len(expression) <= i + 2:
|
if len(expression) <= i + 2:
|
||||||
raise ParserException(u"Expected more tokens in '%s'"%self.name)
|
raise ParserException(
|
||||||
|
u"Expected more tokens in '%s'" % self.name)
|
||||||
|
|
||||||
self.prop = expression[1 + i].strip()
|
self.prop = expression[1 + i].strip()
|
||||||
self.child = node(expression[2 + i])
|
self.child = node(expression[2 + i])
|
||||||
@ -145,6 +157,7 @@ class node (object):
|
|||||||
return
|
return
|
||||||
raise ParserException(u"Unable to parse tokens")
|
raise ParserException(u"Unable to parse tokens")
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def toCode(self):
|
def toCode(self):
|
||||||
'''This method converts the tree into a python code object'''
|
'''This method converts the tree into a python code object'''
|
||||||
code = self.toPython()
|
code = self.toPython()
|
||||||
@ -162,7 +175,8 @@ class node (object):
|
|||||||
if self.name == PROJECTION:
|
if self.name == PROJECTION:
|
||||||
prop = '\"%s\"' % prop.replace(' ', '').replace(',', '\",\"')
|
prop = '\"%s\"' % prop.replace(' ', '').replace(',', '\",\"')
|
||||||
elif self.name == RENAME:
|
elif self.name == RENAME:
|
||||||
prop='{\"%s\"}' % prop.replace(',','\",\"').replace(ARROW,'\":\"').replace(' ','')
|
prop = '{\"%s\"}' % prop.replace(
|
||||||
|
',', '\",\"').replace(ARROW, '\":\"').replace(' ', '')
|
||||||
else: # Selection
|
else: # Selection
|
||||||
prop = '\"%s\"' % prop
|
prop = '\"%s\"' % prop
|
||||||
|
|
||||||
@ -170,6 +184,7 @@ class node (object):
|
|||||||
else:
|
else:
|
||||||
return self.name
|
return self.name
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def printtree(self, level=0):
|
def printtree(self, level=0):
|
||||||
'''returns a representation of the tree using indentation'''
|
'''returns a representation of the tree using indentation'''
|
||||||
r = ''
|
r = ''
|
||||||
@ -184,6 +199,7 @@ class node (object):
|
|||||||
r += self.child.printtree(level + 1)
|
r += self.child.printtree(level + 1)
|
||||||
|
|
||||||
return '\n' + r
|
return '\n' + r
|
||||||
|
|
||||||
def get_left_leaf(self):
|
def get_left_leaf(self):
|
||||||
'''This function returns the leftmost leaf in the tree. It is needed by some optimizations.'''
|
'''This function returns the leftmost leaf in the tree. It is needed by some optimizations.'''
|
||||||
if self.kind == RELATION:
|
if self.kind == RELATION:
|
||||||
@ -193,7 +209,6 @@ class node (object):
|
|||||||
elif self.kind == BINARY:
|
elif self.kind == BINARY:
|
||||||
return self.left.get_left_leaf()
|
return self.left.get_left_leaf()
|
||||||
|
|
||||||
|
|
||||||
def result_format(self, rels):
|
def result_format(self, rels):
|
||||||
'''This function returns a list containing the fields that the resulting relation will have.
|
'''This function returns a list containing the fields that the resulting relation will have.
|
||||||
It requires a dictionary where keys are the names of the relations and the values are
|
It requires a dictionary where keys are the names of the relations and the values are
|
||||||
@ -229,6 +244,7 @@ class node (object):
|
|||||||
return _fields
|
return _fields
|
||||||
elif self.name in (JOIN, JOIN_LEFT, JOIN_RIGHT, JOIN_FULL):
|
elif self.name in (JOIN, JOIN_LEFT, JOIN_RIGHT, JOIN_FULL):
|
||||||
return list(set(self.left.result_format(rels)).union(set(self.right.result_format(rels))))
|
return list(set(self.left.result_format(rels)).union(set(self.right.result_format(rels))))
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if not (isinstance(other, node) and self.name == other.name and self.kind == other.kind):
|
if not (isinstance(other, node) and self.name == other.name and self.kind == other.kind):
|
||||||
return False
|
return False
|
||||||
@ -258,6 +274,7 @@ class node (object):
|
|||||||
|
|
||||||
return (le + self.name + re)
|
return (le + self.name + re)
|
||||||
|
|
||||||
|
|
||||||
def _find_matching_parenthesis(expression, start=0, openpar=u'(', closepar=u')'):
|
def _find_matching_parenthesis(expression, start=0, openpar=u'(', closepar=u')'):
|
||||||
'''This function returns the position of the matching
|
'''This function returns the position of the matching
|
||||||
close parenthesis to the 1st open parenthesis found
|
close parenthesis to the 1st open parenthesis found
|
||||||
@ -271,6 +288,7 @@ def _find_matching_parenthesis(expression,start=0,openpar=u'(',closepar=u')'):
|
|||||||
if par_count == 0:
|
if par_count == 0:
|
||||||
return i # Closing parenthesis of the parameter
|
return i # Closing parenthesis of the parameter
|
||||||
|
|
||||||
|
|
||||||
def tokenize(expression):
|
def tokenize(expression):
|
||||||
'''This function converts an expression into a list where
|
'''This function converts an expression into a list where
|
||||||
every token of the expression is an item of a list. Expressions into
|
every token of the expression is an item of a list. Expressions into
|
||||||
@ -307,23 +325,29 @@ def tokenize(expression):
|
|||||||
state = 2
|
state = 2
|
||||||
end = _find_matching_parenthesis(expression)
|
end = _find_matching_parenthesis(expression)
|
||||||
if end == None:
|
if end == None:
|
||||||
raise TokenizerException("Missing matching ')' in '%s'" %expression)
|
raise TokenizerException(
|
||||||
|
"Missing matching ')' in '%s'" % expression)
|
||||||
# Appends the tokenization of the content of the parenthesis
|
# Appends the tokenization of the content of the parenthesis
|
||||||
items.append(tokenize(expression[1:end]))
|
items.append(tokenize(expression[1:end]))
|
||||||
# Removes the entire parentesis and content from the expression
|
# Removes the entire parentesis and content from the expression
|
||||||
expression = expression[end + 1:].strip()
|
expression = expression[end + 1:].strip()
|
||||||
|
|
||||||
elif expression.startswith((u"σ", u"π", u"ρ")): # Unary 2 bytes
|
elif expression.startswith((u"σ", u"π", u"ρ")): # Unary 2 bytes
|
||||||
items.append(expression[0:1]) #Adding operator in the top of the list
|
items.append(expression[0:1])
|
||||||
expression=expression[1:].strip() #Removing operator from the expression
|
#Adding operator in the top of the list
|
||||||
|
expression = expression[
|
||||||
|
1:].strip() # Removing operator from the expression
|
||||||
|
|
||||||
if expression.startswith('('): # Expression with parenthesis, so adding what's between open and close without tokenization
|
if expression.startswith('('): # Expression with parenthesis, so adding what's between open and close without tokenization
|
||||||
par=expression.find('(',_find_matching_parenthesis(expression))
|
par = expression.find(
|
||||||
|
'(', _find_matching_parenthesis(expression))
|
||||||
else: # Expression without parenthesis, so adding what's between start and parenthesis as whole
|
else: # Expression without parenthesis, so adding what's between start and parenthesis as whole
|
||||||
par = expression.find('(')
|
par = expression.find('(')
|
||||||
|
|
||||||
items.append(expression[:par].strip()) #Inserting parameter of the operator
|
items.append(expression[:par].strip())
|
||||||
expression=expression[par:].strip() #Removing parameter from the expression
|
#Inserting parameter of the operator
|
||||||
|
expression = expression[
|
||||||
|
par:].strip() # Removing parameter from the expression
|
||||||
elif expression.startswith((u"÷", u"ᑎ", u"ᑌ", u"*", u"-")):
|
elif expression.startswith((u"÷", u"ᑎ", u"ᑌ", u"*", u"-")):
|
||||||
items.append(expression[0])
|
items.append(expression[0])
|
||||||
expression = expression[1:].strip() # 1 char from the expression
|
expression = expression[1:].strip() # 1 char from the expression
|
||||||
@ -336,26 +360,29 @@ def tokenize(expression):
|
|||||||
expression = expression[i + 1:].strip()
|
expression = expression[i + 1:].strip()
|
||||||
state = 4
|
state = 4
|
||||||
elif re.match(r'[_0-9A-Za-z]', expression[0]) == None: # At this point we only have relation names, so we raise errors for anything else
|
elif re.match(r'[_0-9A-Za-z]', expression[0]) == None: # At this point we only have relation names, so we raise errors for anything else
|
||||||
raise TokenizerException("Unexpected '%c' in '%s'" % (expression[0],expression))
|
raise TokenizerException(
|
||||||
|
"Unexpected '%c' in '%s'" % (expression[0], expression))
|
||||||
else: # Relation (hopefully)
|
else: # Relation (hopefully)
|
||||||
if state == 1: # Previous was a relation, appending to the last token
|
if state == 1: # Previous was a relation, appending to the last token
|
||||||
i = items.pop()
|
i = items.pop()
|
||||||
items.append(i + expression[0])
|
items.append(i + expression[0])
|
||||||
expression=expression[1:].strip() #1 char from the expression
|
expression = expression[
|
||||||
|
1:].strip() # 1 char from the expression
|
||||||
else:
|
else:
|
||||||
state = 1
|
state = 1
|
||||||
items.append(expression[0])
|
items.append(expression[0])
|
||||||
expression=expression[1:].strip() #1 char from the expression
|
expression = expression[
|
||||||
|
1:].strip() # 1 char from the expression
|
||||||
|
|
||||||
return items
|
return items
|
||||||
|
|
||||||
|
|
||||||
def tree(expression):
|
def tree(expression):
|
||||||
'''This function parses a relational algebra expression into a tree and returns
|
'''This function parses a relational algebra expression into a tree and returns
|
||||||
the root node using the Node class defined in this module.'''
|
the root node using the Node class defined in this module.'''
|
||||||
return node(tokenize(expression))
|
return node(tokenize(expression))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def parse(expr):
|
def parse(expr):
|
||||||
'''This function parses a relational algebra expression, converting it into python,
|
'''This function parses a relational algebra expression, converting it into python,
|
||||||
executable by eval function to get the result of the expression.
|
executable by eval function to get the result of the expression.
|
||||||
|
@ -21,10 +21,13 @@
|
|||||||
|
|
||||||
import parser
|
import parser
|
||||||
|
|
||||||
|
|
||||||
class TypeException(Exception):
|
class TypeException(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Query(object):
|
class Query(object):
|
||||||
|
|
||||||
def __init__(self, query):
|
def __init__(self, query):
|
||||||
|
|
||||||
if not isinstance(query, unicode):
|
if not isinstance(query, unicode):
|
||||||
|
@ -23,7 +23,9 @@
|
|||||||
from rtypes import *
|
from rtypes import *
|
||||||
import csv
|
import csv
|
||||||
|
|
||||||
|
|
||||||
class relation (object):
|
class relation (object):
|
||||||
|
|
||||||
'''This objects defines a relation (as a group of consistent tuples) and operations
|
'''This objects defines a relation (as a group of consistent tuples) and operations
|
||||||
A relation can be represented using a table
|
A relation can be represented using a table
|
||||||
Calling an operation and providing a non relation parameter when it is expected will
|
Calling an operation and providing a non relation parameter when it is expected will
|
||||||
@ -122,8 +124,10 @@ class relation (object):
|
|||||||
if eval(expr, attributes):
|
if eval(expr, attributes):
|
||||||
newt.content.add(i)
|
newt.content.add(i)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
raise Exception("Failed to evaluate %s\n%s" % (expr,e.__str__()))
|
raise Exception(
|
||||||
|
"Failed to evaluate %s\n%s" % (expr, e.__str__()))
|
||||||
return newt
|
return newt
|
||||||
|
|
||||||
def product(self, other):
|
def product(self, other):
|
||||||
'''Cartesian product, attributes must be different to avoid collisions
|
'''Cartesian product, attributes must be different to avoid collisions
|
||||||
Doing this operation on relations with colliding attributes will
|
Doing this operation on relations with colliding attributes will
|
||||||
@ -131,7 +135,8 @@ class relation (object):
|
|||||||
It is possible to use rename on attributes and then use the product'''
|
It is possible to use rename on attributes and then use the product'''
|
||||||
|
|
||||||
if (self.__class__ != other.__class__)or(self.header.sharedAttributes(other.header) != 0):
|
if (self.__class__ != other.__class__)or(self.header.sharedAttributes(other.header) != 0):
|
||||||
raise Exception('Unable to perform product on relations with colliding attributes')
|
raise Exception(
|
||||||
|
'Unable to perform product on relations with colliding attributes')
|
||||||
newt = relation()
|
newt = relation()
|
||||||
newt.header = header(self.header.attributes + other.header.attributes)
|
newt.header = header(self.header.attributes + other.header.attributes)
|
||||||
|
|
||||||
@ -140,7 +145,6 @@ class relation (object):
|
|||||||
newt.content.add(i + j)
|
newt.content.add(i + j)
|
||||||
return newt
|
return newt
|
||||||
|
|
||||||
|
|
||||||
def projection(self, * attributes):
|
def projection(self, * attributes):
|
||||||
'''Projection operator, takes many parameters, for each field to use.
|
'''Projection operator, takes many parameters, for each field to use.
|
||||||
Can also use a single parameter with a list.
|
Can also use a single parameter with a list.
|
||||||
@ -202,7 +206,8 @@ class relation (object):
|
|||||||
It is possible to use projection and rename to make headers match.'''
|
It is possible to use projection and rename to make headers match.'''
|
||||||
other = self._rearrange_(other) # Rearranges attributes' order
|
other = self._rearrange_(other) # Rearranges attributes' order
|
||||||
if (self.__class__ != other.__class__)or(self.header != other.header):
|
if (self.__class__ != other.__class__)or(self.header != other.header):
|
||||||
raise Exception('Unable to perform intersection on relations with different attributes')
|
raise Exception(
|
||||||
|
'Unable to perform intersection on relations with different attributes')
|
||||||
newt = relation()
|
newt = relation()
|
||||||
newt.header = header(list(self.header.attributes))
|
newt.header = header(list(self.header.attributes))
|
||||||
|
|
||||||
@ -217,12 +222,14 @@ class relation (object):
|
|||||||
It is possible to use projection and rename to make headers match.'''
|
It is possible to use projection and rename to make headers match.'''
|
||||||
other = self._rearrange_(other) # Rearranges attributes' order
|
other = self._rearrange_(other) # Rearranges attributes' order
|
||||||
if (self.__class__ != other.__class__)or(self.header != other.header):
|
if (self.__class__ != other.__class__)or(self.header != other.header):
|
||||||
raise Exception('Unable to perform difference on relations with different attributes')
|
raise Exception(
|
||||||
|
'Unable to perform difference on relations with different attributes')
|
||||||
newt = relation()
|
newt = relation()
|
||||||
newt.header = header(list(self.header.attributes))
|
newt.header = header(list(self.header.attributes))
|
||||||
|
|
||||||
newt.content = self.content.difference(other.content)
|
newt.content = self.content.difference(other.content)
|
||||||
return newt
|
return newt
|
||||||
|
|
||||||
def division(self, other):
|
def division(self, other):
|
||||||
'''Division operator
|
'''Division operator
|
||||||
The division is a binary operation that is written as R ÷ S. The
|
The division is a binary operation that is written as R ÷ S. The
|
||||||
@ -233,8 +240,8 @@ class relation (object):
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
# d_headers are the headers from self that aren't also headers in other
|
# d_headers are the headers from self that aren't also headers in other
|
||||||
d_headers=list(set(self.header.attributes) - set(other.header.attributes))
|
d_headers = list(
|
||||||
|
set(self.header.attributes) - set(other.header.attributes))
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Wikipedia defines the division as follows:
|
Wikipedia defines the division as follows:
|
||||||
@ -261,12 +268,14 @@ class relation (object):
|
|||||||
It is possible to use projection and rename to make headers match.'''
|
It is possible to use projection and rename to make headers match.'''
|
||||||
other = self._rearrange_(other) # Rearranges attributes' order
|
other = self._rearrange_(other) # Rearranges attributes' order
|
||||||
if (self.__class__ != other.__class__)or(self.header != other.header):
|
if (self.__class__ != other.__class__)or(self.header != other.header):
|
||||||
raise Exception('Unable to perform union on relations with different attributes')
|
raise Exception(
|
||||||
|
'Unable to perform union on relations with different attributes')
|
||||||
newt = relation()
|
newt = relation()
|
||||||
newt.header = header(list(self.header.attributes))
|
newt.header = header(list(self.header.attributes))
|
||||||
|
|
||||||
newt.content = self.content.union(other.content)
|
newt.content = self.content.union(other.content)
|
||||||
return newt
|
return newt
|
||||||
|
|
||||||
def thetajoin(self, other, expr):
|
def thetajoin(self, other, expr):
|
||||||
'''Defined as product and then selection with the given expression.'''
|
'''Defined as product and then selection with the given expression.'''
|
||||||
return self.product(other).selection(expr)
|
return self.product(other).selection(expr)
|
||||||
@ -347,11 +356,13 @@ class relation (object):
|
|||||||
shared attributes, it will behave as cartesian product.'''
|
shared attributes, it will behave as cartesian product.'''
|
||||||
|
|
||||||
# List of attributes in common between the relations
|
# List of attributes in common between the relations
|
||||||
shared=list(set(self.header.attributes).intersection(set(other.header.attributes)))
|
shared = list(set(self.header.attributes)
|
||||||
|
.intersection(set(other.header.attributes)))
|
||||||
|
|
||||||
newt = relation() # Creates the new relation
|
newt = relation() # Creates the new relation
|
||||||
|
|
||||||
#Adding to the headers all the fields, done like that because order is needed
|
# Adding to the headers all the fields, done like that because order is
|
||||||
|
# needed
|
||||||
newt.header = header(list(self.header.attributes))
|
newt.header = header(list(self.header.attributes))
|
||||||
for i in other.header.attributes:
|
for i in other.header.attributes:
|
||||||
if i not in shared:
|
if i not in shared:
|
||||||
@ -382,10 +393,12 @@ class relation (object):
|
|||||||
newt.content.add(tuple(item))
|
newt.content.add(tuple(item))
|
||||||
|
|
||||||
return newt
|
return newt
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
'''Returns true if the relations are the same, ignoring order of items.
|
'''Returns true if the relations are the same, ignoring order of items.
|
||||||
This operation is rather heavy, since it requires sorting and comparing.'''
|
This operation is rather heavy, since it requires sorting and comparing.'''
|
||||||
other=self._rearrange_(other) #Rearranges attributes' order so can compare tuples directly
|
other = self._rearrange_(
|
||||||
|
other) # Rearranges attributes' order so can compare tuples directly
|
||||||
|
|
||||||
if (self.__class__ != other.__class__)or(self.header != other.header):
|
if (self.__class__ != other.__class__)or(self.header != other.header):
|
||||||
return False # Both parameters must be a relation
|
return False # Both parameters must be a relation
|
||||||
@ -393,8 +406,6 @@ class relation (object):
|
|||||||
if set(self.header.attributes) != set(other.header.attributes):
|
if set(self.header.attributes) != set(other.header.attributes):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# comparing content
|
# comparing content
|
||||||
return self.content == other.content
|
return self.content == other.content
|
||||||
|
|
||||||
@ -416,7 +427,6 @@ class relation (object):
|
|||||||
for f in range(len(self.header.attributes)):
|
for f in range(len(self.header.attributes)):
|
||||||
res += "%s" % (self.header.attributes[f].ljust(2 + m_len[f]))
|
res += "%s" % (self.header.attributes[f].ljust(2 + m_len[f]))
|
||||||
|
|
||||||
|
|
||||||
for r in self.content:
|
for r in self.content:
|
||||||
col = 0
|
col = 0
|
||||||
res += "\n"
|
res += "\n"
|
||||||
@ -438,7 +448,8 @@ class relation (object):
|
|||||||
affected = 0
|
affected = 0
|
||||||
attributes = {}
|
attributes = {}
|
||||||
keys = dic.keys() # List of headers to modify
|
keys = dic.keys() # List of headers to modify
|
||||||
f_ids=self.header.getAttributesId(keys) #List of indexes corresponding to keys
|
f_ids = self.header.getAttributesId(
|
||||||
|
keys) # List of indexes corresponding to keys
|
||||||
|
|
||||||
# new_content=[] #New content of the relation
|
# new_content=[] #New content of the relation
|
||||||
for i in self.content:
|
for i in self.content:
|
||||||
@ -492,14 +503,15 @@ class relation (object):
|
|||||||
for j in range(len(self.header.attributes)):
|
for j in range(len(self.header.attributes)):
|
||||||
attributes[self.header.attributes[j]] = self._autocast(i[j])
|
attributes[self.header.attributes[j]] = self._autocast(i[j])
|
||||||
|
|
||||||
|
|
||||||
if not eval(expr, attributes):
|
if not eval(expr, attributes):
|
||||||
affected -= 1
|
affected -= 1
|
||||||
new_content.add(i)
|
new_content.add(i)
|
||||||
self.content = new_content
|
self.content = new_content
|
||||||
return affected
|
return affected
|
||||||
|
|
||||||
|
|
||||||
class header (object):
|
class header (object):
|
||||||
|
|
||||||
'''This class defines the header of a relation.
|
'''This class defines the header of a relation.
|
||||||
It is used within relations to know if requested operations are accepted'''
|
It is used within relations to know if requested operations are accepted'''
|
||||||
|
|
||||||
@ -517,7 +529,6 @@ class header (object):
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "header(%s)" % (self.attributes.__repr__())
|
return "header(%s)" % (self.attributes.__repr__())
|
||||||
|
|
||||||
|
|
||||||
def rename(self, old, new):
|
def rename(self, old, new):
|
||||||
'''Renames a field. Doesn't check if it is a duplicate.
|
'''Renames a field. Doesn't check if it is a duplicate.
|
||||||
Returns True if the field was renamed, False otherwise'''
|
Returns True if the field was renamed, False otherwise'''
|
||||||
@ -542,6 +553,7 @@ class header (object):
|
|||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return self.attributes == other.attributes
|
return self.attributes == other.attributes
|
||||||
|
|
||||||
def __ne__(self, other):
|
def __ne__(self, other):
|
||||||
return self.attributes != other.attributes
|
return self.attributes != other.attributes
|
||||||
|
|
||||||
@ -553,4 +565,3 @@ class header (object):
|
|||||||
if i == self.attributes[j]:
|
if i == self.attributes[j]:
|
||||||
res.append(j)
|
res.append(j)
|
||||||
return res
|
return res
|
||||||
|
|
@ -24,8 +24,11 @@
|
|||||||
import datetime
|
import datetime
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
|
||||||
class rstring (str):
|
class rstring (str):
|
||||||
|
|
||||||
'''String subclass with some custom methods'''
|
'''String subclass with some custom methods'''
|
||||||
|
|
||||||
def isInt(self):
|
def isInt(self):
|
||||||
'''Returns true if the string represents an int number
|
'''Returns true if the string represents an int number
|
||||||
it only considers as int numbers the strings matching
|
it only considers as int numbers the strings matching
|
||||||
@ -36,6 +39,7 @@ class rstring (str):
|
|||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def isFloat(self):
|
def isFloat(self):
|
||||||
'''Returns true if the string represents a float number
|
'''Returns true if the string represents a float number
|
||||||
it only considers as float numbers, the strings matching
|
it only considers as float numbers, the strings matching
|
||||||
@ -58,7 +62,8 @@ class rstring (str):
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
r= re.match(r'^([0-9]{1,4})(\\|-|/)([0-9]{1,2})(\\|-|/)([0-9]{1,2})$',self)
|
r = re.match(
|
||||||
|
r'^([0-9]{1,4})(\\|-|/)([0-9]{1,2})(\\|-|/)([0-9]{1,2})$', self)
|
||||||
if r == None:
|
if r == None:
|
||||||
self._isdate = False
|
self._isdate = False
|
||||||
self._date = None
|
self._date = None
|
||||||
@ -84,8 +89,12 @@ class rstring (str):
|
|||||||
except:
|
except:
|
||||||
self.isDate()
|
self.isDate()
|
||||||
return self._date
|
return self._date
|
||||||
|
|
||||||
|
|
||||||
class rdate (object):
|
class rdate (object):
|
||||||
|
|
||||||
'''Represents a date'''
|
'''Represents a date'''
|
||||||
|
|
||||||
def __init__(self, date):
|
def __init__(self, date):
|
||||||
'''date: A string representing a date'''
|
'''date: A string representing a date'''
|
||||||
if not isinstance(date, rstring):
|
if not isinstance(date, rstring):
|
||||||
@ -99,23 +108,32 @@ class rdate (object):
|
|||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return self.intdate.__hash__()
|
return self.intdate.__hash__()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.intdate.__str__()
|
return self.intdate.__str__()
|
||||||
|
|
||||||
def __add__(self, days):
|
def __add__(self, days):
|
||||||
res = self.intdate + datetime.timedelta(days)
|
res = self.intdate + datetime.timedelta(days)
|
||||||
return rdate(res.__str__())
|
return rdate(res.__str__())
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return self.intdate == other.intdate
|
return self.intdate == other.intdate
|
||||||
|
|
||||||
def __ge__(self, other):
|
def __ge__(self, other):
|
||||||
return self.intdate >= other.intdate
|
return self.intdate >= other.intdate
|
||||||
|
|
||||||
def __gt__(self, other):
|
def __gt__(self, other):
|
||||||
return self.intdate > other.intdate
|
return self.intdate > other.intdate
|
||||||
|
|
||||||
def __le__(self, other):
|
def __le__(self, other):
|
||||||
return self.intdate <= other.intdate
|
return self.intdate <= other.intdate
|
||||||
|
|
||||||
def __lt__(self, other):
|
def __lt__(self, other):
|
||||||
return self.intdate < other.intdate
|
return self.intdate < other.intdate
|
||||||
|
|
||||||
def __ne__(self, other):
|
def __ne__(self, other):
|
||||||
return self.intdate != other.intdate
|
return self.intdate != other.intdate
|
||||||
|
|
||||||
def __sub__(self, other):
|
def __sub__(self, other):
|
||||||
return (self.intdate - other.intdate).days
|
return (self.intdate - other.intdate).days
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ import signal
|
|||||||
import sys
|
import sys
|
||||||
from relational import *
|
from relational import *
|
||||||
|
|
||||||
|
|
||||||
def terminate(*a):
|
def terminate(*a):
|
||||||
'''Restores the terminal and terminates'''
|
'''Restores the terminal and terminates'''
|
||||||
curses.nocbreak()
|
curses.nocbreak()
|
||||||
@ -32,6 +33,7 @@ def terminate(*a):
|
|||||||
|
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
global stdscr
|
global stdscr
|
||||||
# Initializes the signal
|
# Initializes the signal
|
||||||
@ -52,15 +54,11 @@ def main():
|
|||||||
|
|
||||||
win = curses.panel.new_panel(curses.newwin(termsize[0], termsize[1]))
|
win = curses.panel.new_panel(curses.newwin(termsize[0], termsize[1]))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# win.window().box()
|
# win.window().box()
|
||||||
win.window().addstr(0, (termsize[1] / 2) - 5, "Relational")
|
win.window().addstr(0, (termsize[1] / 2) - 5, "Relational")
|
||||||
win.window().refresh()
|
win.window().refresh()
|
||||||
# curses.napms(1000)
|
# curses.napms(1000)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
query = curses.panel.new_panel(curses.newwin(3, termsize[1], 1, 0))
|
query = curses.panel.new_panel(curses.newwin(3, termsize[1], 1, 0))
|
||||||
query.window().box()
|
query.window().box()
|
||||||
query.window().addstr(1, 1, "")
|
query.window().addstr(1, 1, "")
|
||||||
@ -71,9 +69,7 @@ def main():
|
|||||||
|
|
||||||
# curses.napms(1000)
|
# curses.napms(1000)
|
||||||
|
|
||||||
|
|
||||||
# qq=curses.textpad.Textbox(stdscr)
|
# qq=curses.textpad.Textbox(stdscr)
|
||||||
|
|
||||||
'''win = curses.newwin(0, 0)#New windows for the entire screen
|
'''win = curses.newwin(0, 0)#New windows for the entire screen
|
||||||
#stdscr.border(0)
|
#stdscr.border(0)
|
||||||
stdscr.addstr(str(dir (win)))
|
stdscr.addstr(str(dir (win)))
|
||||||
@ -97,13 +93,11 @@ def main():
|
|||||||
if c == 27: # Escape
|
if c == 27: # Escape
|
||||||
squery += add_symbol(symselect)
|
squery += add_symbol(symselect)
|
||||||
|
|
||||||
|
|
||||||
# elif c==curses.KEY_BACKSPACE: #Delete
|
# elif c==curses.KEY_BACKSPACE: #Delete
|
||||||
elif c == 13:
|
elif c == 13:
|
||||||
squery = squery[:-1]
|
squery = squery[:-1]
|
||||||
else:
|
else:
|
||||||
squery+=chr(c);
|
squery += chr(c)
|
||||||
|
|
||||||
|
|
||||||
query.window().box()
|
query.window().box()
|
||||||
query.top()
|
query.top()
|
||||||
@ -111,10 +105,13 @@ def main():
|
|||||||
query.window().addstr(1, 1, squery)
|
query.window().addstr(1, 1, squery)
|
||||||
|
|
||||||
query.window().refresh()
|
query.window().refresh()
|
||||||
|
|
||||||
|
|
||||||
def init_symbol_list(termsize, create=True):
|
def init_symbol_list(termsize, create=True):
|
||||||
|
|
||||||
if create:
|
if create:
|
||||||
p=curses.panel.new_panel(curses.newwin(15,16,2,termsize[1]/2-7))
|
p = curses.panel.new_panel(
|
||||||
|
curses.newwin(15, 16, 2, termsize[1] / 2 - 7))
|
||||||
else:
|
else:
|
||||||
p = termsize
|
p = termsize
|
||||||
p.window().box()
|
p.window().box()
|
||||||
@ -135,13 +132,15 @@ def init_symbol_list(termsize,create=True):
|
|||||||
|
|
||||||
# p.hide()
|
# p.hide()
|
||||||
return p
|
return p
|
||||||
|
|
||||||
|
|
||||||
def add_symbol(p):
|
def add_symbol(p):
|
||||||
'''Shows the panel to add a symbol
|
'''Shows the panel to add a symbol
|
||||||
and then returns the choosen symbol itself'''
|
and then returns the choosen symbol itself'''
|
||||||
init_symbol_list(p, False)
|
init_symbol_list(p, False)
|
||||||
|
|
||||||
d_={'0':'*','1':'-','2':'ᑌ','3':'ᑎ','4':'ᐅᐊ','5':'ᐅLEFTᐊ','6':'ᐅRIGHTᐊ','7':'ᐅFULLᐊ','8':'σ','9':'ρ','a':'π','b':'➡'}
|
d_ = {'0': '*', '1': '-', '2': 'ᑌ', '3': 'ᑎ', '4': 'ᐅᐊ', '5': 'ᐅLEFTᐊ',
|
||||||
|
'6': 'ᐅRIGHTᐊ', '7': 'ᐅFULLᐊ', '8': 'σ', '9': 'ρ', 'a': 'π', 'b': '➡'}
|
||||||
|
|
||||||
p.show()
|
p.show()
|
||||||
p.top()
|
p.top()
|
||||||
@ -156,6 +155,7 @@ def add_symbol(p):
|
|||||||
char = ''
|
char = ''
|
||||||
return char
|
return char
|
||||||
|
|
||||||
|
|
||||||
def spaces(t):
|
def spaces(t):
|
||||||
'''Returns a number of spaces specified t'''
|
'''Returns a number of spaces specified t'''
|
||||||
s = ''
|
s = ''
|
||||||
|
@ -42,6 +42,7 @@ def printver(exit=True):
|
|||||||
if exit:
|
if exit:
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
def printhelp(code=0):
|
def printhelp(code=0):
|
||||||
print "Relational"
|
print "Relational"
|
||||||
print
|
print
|
||||||
@ -92,7 +93,6 @@ if __name__ == "__main__":
|
|||||||
from PySide import QtCore, QtGui
|
from PySide import QtCore, QtGui
|
||||||
pyqt = False
|
pyqt = False
|
||||||
|
|
||||||
|
|
||||||
if pyqt:
|
if pyqt:
|
||||||
try:
|
try:
|
||||||
from relational_gui import maingui, guihandler, about, surveyForm
|
from relational_gui import maingui, guihandler, about, surveyForm
|
||||||
@ -106,14 +106,13 @@ if __name__ == "__main__":
|
|||||||
print >> sys.stderr, "Module relational_pyside is missing.\nPlease install relational package."
|
print >> sys.stderr, "Module relational_pyside is missing.\nPlease install relational package."
|
||||||
sys.exit(3)
|
sys.exit(3)
|
||||||
|
|
||||||
|
|
||||||
about.version = version
|
about.version = version
|
||||||
surveyForm.version = version
|
surveyForm.version = version
|
||||||
guihandler.version = version
|
guihandler.version = version
|
||||||
|
|
||||||
app = QtGui.QApplication(sys.argv)
|
app = QtGui.QApplication(sys.argv)
|
||||||
app.setOrganizationName('None');
|
app.setOrganizationName('None')
|
||||||
app.setApplicationName('relational');
|
app.setApplicationName('relational')
|
||||||
|
|
||||||
ui = maingui.Ui_MainWindow()
|
ui = maingui.Ui_MainWindow()
|
||||||
Form = guihandler.relForm(ui)
|
Form = guihandler.relForm(ui)
|
||||||
@ -146,4 +145,3 @@ if __name__ == "__main__":
|
|||||||
sys.exit(3)
|
sys.exit(3)
|
||||||
relational_readline.linegui.version = version
|
relational_readline.linegui.version = version
|
||||||
relational_readline.linegui.main(files)
|
relational_readline.linegui.main(files)
|
||||||
|
|
||||||
|
@ -37,7 +37,9 @@ except:
|
|||||||
|
|
||||||
version = 0
|
version = 0
|
||||||
|
|
||||||
|
|
||||||
class Ui_Dialog(object):
|
class Ui_Dialog(object):
|
||||||
|
|
||||||
def setupUi(self, Dialog):
|
def setupUi(self, Dialog):
|
||||||
Dialog.setObjectName("Dialog")
|
Dialog.setObjectName("Dialog")
|
||||||
Dialog.resize(510, 453)
|
Dialog.resize(510, 453)
|
||||||
@ -96,14 +98,16 @@ class Ui_Dialog(object):
|
|||||||
self.verticalLayout_7.setObjectName("verticalLayout_7")
|
self.verticalLayout_7.setObjectName("verticalLayout_7")
|
||||||
if (webk):
|
if (webk):
|
||||||
self.webView = QtWebKit.QWebView(self.tab_2)
|
self.webView = QtWebKit.QWebView(self.tab_2)
|
||||||
self.webView.setUrl(QtCore.QUrl("http://galileo.dmi.unict.it/wiki/relational/doku.php"))
|
self.webView.setUrl(
|
||||||
|
QtCore.QUrl("https://github.com/ltworf/relational/wiki/Grammar-and-language"))
|
||||||
self.webView.setObjectName("webView")
|
self.webView.setObjectName("webView")
|
||||||
self.verticalLayout_7.addWidget(self.webView)
|
self.verticalLayout_7.addWidget(self.webView)
|
||||||
else:
|
else:
|
||||||
self.webLink = QtGui.QLabel(self.groupBox)
|
self.webLink = QtGui.QLabel(self.groupBox)
|
||||||
self.webLink.setFont(font)
|
self.webLink.setFont(font)
|
||||||
self.webLink.setObjectName("lblLink")
|
self.webLink.setObjectName("lblLink")
|
||||||
self.webLink.setText(QtGui.QApplication.translate("Dialog", "<a href=\"http://galileo.dmi.unict.it/wiki/relational/\">Relational's website</a>", None,))
|
self.webLink.setText(QtGui.QApplication.translate(
|
||||||
|
"Dialog", "<a href=\"https://github.com/ltworf/relational\">Relational's website</a>", None,))
|
||||||
self.webLink.setOpenExternalLinks(True)
|
self.webLink.setOpenExternalLinks(True)
|
||||||
self.webLink.setTextFormat(QtCore.Qt.AutoText)
|
self.webLink.setTextFormat(QtCore.Qt.AutoText)
|
||||||
self.webLink.setTextInteractionFlags(
|
self.webLink.setTextInteractionFlags(
|
||||||
@ -126,24 +130,39 @@ class Ui_Dialog(object):
|
|||||||
|
|
||||||
self.retranslateUi(Dialog)
|
self.retranslateUi(Dialog)
|
||||||
self.tabWidget.setCurrentIndex(0)
|
self.tabWidget.setCurrentIndex(0)
|
||||||
QtCore.QObject.connect(self.buttonBox,QtCore.SIGNAL("accepted()"),Dialog.accept)
|
QtCore.QObject.connect(
|
||||||
QtCore.QObject.connect(self.buttonBox,QtCore.SIGNAL("rejected()"),Dialog.reject)
|
self.buttonBox, QtCore.SIGNAL("accepted()"), Dialog.accept)
|
||||||
|
QtCore.QObject.connect(
|
||||||
|
self.buttonBox, QtCore.SIGNAL("rejected()"), Dialog.reject)
|
||||||
QtCore.QMetaObject.connectSlotsByName(Dialog)
|
QtCore.QMetaObject.connectSlotsByName(Dialog)
|
||||||
|
|
||||||
def retranslateUi(self, Dialog):
|
def retranslateUi(self, Dialog):
|
||||||
Dialog.setWindowTitle(QtGui.QApplication.translate("Dialog", "Documentation", None, QtGui.QApplication.UnicodeUTF8))
|
Dialog.setWindowTitle(QtGui.QApplication.translate(
|
||||||
self.groupBox.setTitle(QtGui.QApplication.translate("Dialog", "Relational", None, QtGui.QApplication.UnicodeUTF8))
|
"Dialog", "Documentation", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.label.setText(QtGui.QApplication.translate("Dialog", "Relational", None, QtGui.QApplication.UnicodeUTF8))
|
self.groupBox.setTitle(QtGui.QApplication.translate(
|
||||||
self.label_3.setText(QtGui.QApplication.translate("Dialog", "Version "+version, None, QtGui.QApplication.UnicodeUTF8))
|
"Dialog", "Relational", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.label_3.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByMouse)
|
self.label.setText(QtGui.QApplication.translate(
|
||||||
self.groupBox_3.setTitle(QtGui.QApplication.translate("Dialog", "Author", None, QtGui.QApplication.UnicodeUTF8))
|
"Dialog", "Relational", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.label_2.setText(QtGui.QApplication.translate("Dialog", "Salvo \"LtWorf\" Tomaselli <<a href=\"mailto:tiposchi@tiscali.it\">tiposchi@tiscali.it</a>><br>Emilio Di Prima <emiliodiprima[at]msn[dot]com> (For the windows setup)", None, QtGui.QApplication.UnicodeUTF8))
|
self.label_3.setText(QtGui.QApplication.translate(
|
||||||
|
"Dialog", "Version " + version, None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.label_3.setTextInteractionFlags(
|
||||||
|
QtCore.Qt.LinksAccessibleByMouse | QtCore.Qt.TextSelectableByMouse)
|
||||||
|
self.groupBox_3.setTitle(QtGui.QApplication.translate(
|
||||||
|
"Dialog", "Author", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.label_2.setText(QtGui.QApplication.translate(
|
||||||
|
"Dialog", "Salvo \"LtWorf\" Tomaselli <<a href=\"mailto:tiposchi@tiscali.it\">tiposchi@tiscali.it</a>><br>Emilio Di Prima <emiliodiprima[at]msn[dot]com> (For the windows setup)", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.label_2.setOpenExternalLinks(True)
|
self.label_2.setOpenExternalLinks(True)
|
||||||
self.label_2.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByMouse)
|
self.label_2.setTextInteractionFlags(
|
||||||
self.groupBox_2.setTitle(QtGui.QApplication.translate("Dialog", "Links", None, QtGui.QApplication.UnicodeUTF8))
|
QtCore.Qt.LinksAccessibleByMouse | QtCore.Qt.TextSelectableByMouse)
|
||||||
self.label_4.setText(QtGui.QApplication.translate("Dialog", "<a href=\"http://galileo.dmi.unict.it/wiki/relational/\">http://galileo.dmi.unict.it/wiki/relational/</a>", None, QtGui.QApplication.UnicodeUTF8))
|
self.groupBox_2.setTitle(QtGui.QApplication.translate(
|
||||||
|
"Dialog", "Links", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.label_4.setText(QtGui.QApplication.translate(
|
||||||
|
"Dialog", "<a href=\"https://github.com/ltworf/relational/\">https://github.com/ltworf/relational/</a>", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.label_4.setOpenExternalLinks(True)
|
self.label_4.setOpenExternalLinks(True)
|
||||||
self.label_4.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByMouse)
|
self.label_4.setTextInteractionFlags(
|
||||||
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), QtGui.QApplication.translate("Dialog", "About", None, QtGui.QApplication.UnicodeUTF8))
|
QtCore.Qt.LinksAccessibleByMouse | QtCore.Qt.TextSelectableByMouse)
|
||||||
|
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), QtGui.QApplication.translate(
|
||||||
|
"Dialog", "About", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.textEdit.setHtml(QtGui.QApplication.translate("Dialog", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
|
self.textEdit.setHtml(QtGui.QApplication.translate("Dialog", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
|
||||||
"<html><head><meta name=\"qrichtext\" content=\"1\" /><title>GNU General Public License - GNU Project - Free Software Foundation (FSF)</title><style type=\"text/css\">\n"
|
"<html><head><meta name=\"qrichtext\" content=\"1\" /><title>GNU General Public License - GNU Project - Free Software Foundation (FSF)</title><style type=\"text/css\">\n"
|
||||||
"p, li { white-space: pre-wrap; }\n"
|
"p, li { white-space: pre-wrap; }\n"
|
||||||
@ -286,9 +305,10 @@ class Ui_Dialog(object):
|
|||||||
"<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">The hypothetical commands `show w\' and `show c\' should show the appropriate parts of the General Public License. Of course, your program\'s commands might be different; for a GUI interface, you would use an “about box”. </p>\n"
|
"<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">The hypothetical commands `show w\' and `show c\' should show the appropriate parts of the General Public License. Of course, your program\'s commands might be different; for a GUI interface, you would use an “about box”. </p>\n"
|
||||||
"<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">You should also get your employer (if you work as a programmer) or school, if any, to sign a “copyright disclaimer” for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see <http://www.gnu.org/licenses/>. </p>\n"
|
"<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">You should also get your employer (if you work as a programmer) or school, if any, to sign a “copyright disclaimer” for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see <http://www.gnu.org/licenses/>. </p>\n"
|
||||||
"<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read <http://www.gnu.org/philosophy/why-not-lgpl.html>. </p></body></html>", None, QtGui.QApplication.UnicodeUTF8))
|
"<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read <http://www.gnu.org/philosophy/why-not-lgpl.html>. </p></body></html>", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.tabWidget.setTabText(self.tabWidget.indexOf(self.License), QtGui.QApplication.translate("Dialog", "License", None, QtGui.QApplication.UnicodeUTF8))
|
self.tabWidget.setTabText(self.tabWidget.indexOf(self.License), QtGui.QApplication.translate(
|
||||||
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), QtGui.QApplication.translate("Dialog", "Docs", None, QtGui.QApplication.UnicodeUTF8))
|
"Dialog", "License", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), QtGui.QApplication.translate(
|
||||||
|
"Dialog", "Docs", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
@ -299,4 +319,3 @@ if __name__ == "__main__":
|
|||||||
ui.setupUi(Dialog)
|
ui.setupUi(Dialog)
|
||||||
Dialog.show()
|
Dialog.show()
|
||||||
sys.exit(app.exec_())
|
sys.exit(app.exec_())
|
||||||
|
|
||||||
|
@ -34,15 +34,20 @@ def get_py_str(a):
|
|||||||
return unicode(a.toUtf8(), 'utf-8')
|
return unicode(a.toUtf8(), 'utf-8')
|
||||||
return a # Already a python string in PySide
|
return a # Already a python string in PySide
|
||||||
|
|
||||||
|
|
||||||
def set_utf8_text(component, text):
|
def set_utf8_text(component, text):
|
||||||
if not pyqt:
|
if not pyqt:
|
||||||
component.setText(text)
|
component.setText(text)
|
||||||
else:
|
else:
|
||||||
component.setText(QtCore.QString.fromUtf8(text))
|
component.setText(QtCore.QString.fromUtf8(text))
|
||||||
|
|
||||||
|
|
||||||
def get_filename(filename):
|
def get_filename(filename):
|
||||||
if pyqt:
|
if pyqt:
|
||||||
return str(filename.toUtf8())
|
return str(filename.toUtf8())
|
||||||
return filename[0]
|
return filename[0]
|
||||||
|
|
||||||
|
|
||||||
def add_list_item(l, item):
|
def add_list_item(l, item):
|
||||||
if pyqt:
|
if pyqt:
|
||||||
history_item = QtCore.QString()
|
history_item = QtCore.QString()
|
||||||
|
@ -28,12 +28,14 @@ import rel_edit
|
|||||||
|
|
||||||
|
|
||||||
class creatorForm(QtGui.QDialog):
|
class creatorForm(QtGui.QDialog):
|
||||||
|
|
||||||
def __init__(self, rel=None):
|
def __init__(self, rel=None):
|
||||||
QtGui.QDialog.__init__(self)
|
QtGui.QDialog.__init__(self)
|
||||||
|
|
||||||
self.setSizeGripEnabled(True)
|
self.setSizeGripEnabled(True)
|
||||||
self.result_relation = None
|
self.result_relation = None
|
||||||
self.rel = rel
|
self.rel = rel
|
||||||
|
|
||||||
def setUi(self, ui):
|
def setUi(self, ui):
|
||||||
self.ui = ui
|
self.ui = ui
|
||||||
self.table = self.ui.table
|
self.table = self.ui.table
|
||||||
@ -42,6 +44,7 @@ class creatorForm(QtGui.QDialog):
|
|||||||
self.setup_empty()
|
self.setup_empty()
|
||||||
else:
|
else:
|
||||||
self.setup_relation(self.rel)
|
self.setup_relation(self.rel)
|
||||||
|
|
||||||
def setup_relation(self, rel):
|
def setup_relation(self, rel):
|
||||||
|
|
||||||
self.table.insertRow(0)
|
self.table.insertRow(0)
|
||||||
@ -60,6 +63,7 @@ class creatorForm(QtGui.QDialog):
|
|||||||
self.table.setItem(self.table.rowCount() - 1, j, item)
|
self.table.setItem(self.table.rowCount() - 1, j, item)
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def setup_empty(self):
|
def setup_empty(self):
|
||||||
self.table.insertColumn(0)
|
self.table.insertColumn(0)
|
||||||
self.table.insertColumn(0)
|
self.table.insertColumn(0)
|
||||||
@ -79,15 +83,18 @@ class creatorForm(QtGui.QDialog):
|
|||||||
self.table.setItem(0, 1, i01)
|
self.table.setItem(0, 1, i01)
|
||||||
self.table.setItem(1, 0, i10)
|
self.table.setItem(1, 0, i10)
|
||||||
self.table.setItem(1, 1, i11)
|
self.table.setItem(1, 1, i11)
|
||||||
|
|
||||||
def create_relation(self):
|
def create_relation(self):
|
||||||
hlist = []
|
hlist = []
|
||||||
|
|
||||||
for i in range(self.table.columnCount()):
|
for i in range(self.table.columnCount()):
|
||||||
hlist.append(compatibility.get_py_str(self.table.item(0,i).text()))
|
hlist.append(
|
||||||
|
compatibility.get_py_str(self.table.item(0, i).text()))
|
||||||
try:
|
try:
|
||||||
header = relation.header(hlist)
|
header = relation.header(hlist)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
QtGui.QMessageBox.information(None,QtGui.QApplication.translate("Form", "Error"),"%s\n%s" % (QtGui.QApplication.translate("Form", "Header error!"),e.__str__()) )
|
QtGui.QMessageBox.information(None, QtGui.QApplication.translate("Form", "Error"), "%s\n%s" % (
|
||||||
|
QtGui.QApplication.translate("Form", "Header error!"), e.__str__()))
|
||||||
return None
|
return None
|
||||||
r = relation.relation()
|
r = relation.relation()
|
||||||
r.header = header
|
r.header = header
|
||||||
@ -96,9 +103,11 @@ class creatorForm(QtGui.QDialog):
|
|||||||
hlist = []
|
hlist = []
|
||||||
for j in range(self.table.columnCount()):
|
for j in range(self.table.columnCount()):
|
||||||
try:
|
try:
|
||||||
hlist.append(compatibility.get_py_str(self.table.item(i,j).text()))
|
hlist.append(
|
||||||
|
compatibility.get_py_str(self.table.item(i, j).text()))
|
||||||
except:
|
except:
|
||||||
QtGui.QMessageBox.information(None,QtGui.QApplication.translate("Form", "Error"),QtGui.QApplication.translate("Form", "Unset value in %d,%d!"% (i+1,j+1)) )
|
QtGui.QMessageBox.information(None, QtGui.QApplication.translate(
|
||||||
|
"Form", "Error"), QtGui.QApplication.translate("Form", "Unset value in %d,%d!" % (i + 1, j + 1)))
|
||||||
return None
|
return None
|
||||||
r.content.add(tuple(hlist))
|
r.content.add(tuple(hlist))
|
||||||
return r
|
return r
|
||||||
@ -111,20 +120,25 @@ class creatorForm(QtGui.QDialog):
|
|||||||
if self.result_relation != None:
|
if self.result_relation != None:
|
||||||
QtGui.QDialog.accept(self)
|
QtGui.QDialog.accept(self)
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def reject(self):
|
def reject(self):
|
||||||
self.result_relation = None
|
self.result_relation = None
|
||||||
QtGui.QDialog.reject(self)
|
QtGui.QDialog.reject(self)
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def addColumn(self):
|
def addColumn(self):
|
||||||
self.table.insertColumn(self.table.columnCount())
|
self.table.insertColumn(self.table.columnCount())
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def addRow(self):
|
def addRow(self):
|
||||||
self.table.insertRow(1)
|
self.table.insertRow(1)
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def deleteColumn(self):
|
def deleteColumn(self):
|
||||||
if self.table.columnCount() > 1:
|
if self.table.columnCount() > 1:
|
||||||
self.table.removeColumn(self.table.currentColumn())
|
self.table.removeColumn(self.table.currentColumn())
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def deleteRow(self):
|
def deleteRow(self):
|
||||||
if self.table.rowCount() > 2:
|
if self.table.rowCount() > 2:
|
||||||
self.table.removeRow(self.table.currentRow())
|
self.table.removeRow(self.table.currentRow())
|
||||||
@ -149,5 +163,6 @@ def edit_relation(rel=None):
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import sys
|
import sys
|
||||||
app = QtGui.QApplication(sys.argv)
|
app = QtGui.QApplication(sys.argv)
|
||||||
r=relation.relation("/home/salvo/dev/relational/trunk/samples/people.csv")
|
r = relation.relation(
|
||||||
|
"/home/salvo/dev/relational/trunk/samples/people.csv")
|
||||||
print edit_relation(r)
|
print edit_relation(r)
|
||||||
|
@ -26,7 +26,6 @@ except:
|
|||||||
from PySide import QtCore, QtGui
|
from PySide import QtCore, QtGui
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
from relational import relation, parser, optimizer, rtypes
|
from relational import relation, parser, optimizer, rtypes
|
||||||
|
|
||||||
import about
|
import about
|
||||||
@ -55,14 +54,17 @@ class relForm(QtGui.QMainWindow):
|
|||||||
online = maintenance.check_latest_version()
|
online = maintenance.check_latest_version()
|
||||||
|
|
||||||
if online > version:
|
if online > version:
|
||||||
r=QtGui.QApplication.translate("Form", "New version available online: %s." % online)
|
r = QtGui.QApplication.translate(
|
||||||
|
"Form", "New version available online: %s." % online)
|
||||||
elif online == version:
|
elif online == version:
|
||||||
r=QtGui.QApplication.translate("Form", "Latest version installed.")
|
r = QtGui.QApplication.translate(
|
||||||
|
"Form", "Latest version installed.")
|
||||||
else:
|
else:
|
||||||
r=QtGui.QApplication.translate("Form", "You are using an unstable version.")
|
r = QtGui.QApplication.translate(
|
||||||
|
"Form", "You are using an unstable version.")
|
||||||
QtGui.QMessageBox.information(self,QtGui.QApplication.translate("Form", "Version"),r)
|
|
||||||
|
|
||||||
|
QtGui.QMessageBox.information(
|
||||||
|
self, QtGui.QApplication.translate("Form", "Version"), r)
|
||||||
|
|
||||||
def load_query(self, *index):
|
def load_query(self, *index):
|
||||||
self.ui.txtQuery.setText(self.savedQ.itemData(index[0]).toString())
|
self.ui.txtQuery.setText(self.savedQ.itemData(index[0]).toString())
|
||||||
@ -81,9 +83,8 @@ class relForm(QtGui.QMainWindow):
|
|||||||
result = optimizer.optimize_all(query, self.relations)
|
result = optimizer.optimize_all(query, self.relations)
|
||||||
compatibility.set_utf8_text(self.ui.txtQuery, result)
|
compatibility.set_utf8_text(self.ui.txtQuery, result)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
QtGui.QMessageBox.information(None,QtGui.QApplication.translate("Form", "Error"),"%s\n%s" % (QtGui.QApplication.translate("Form", "Check your query!"),e.__str__()) )
|
QtGui.QMessageBox.information(None, QtGui.QApplication.translate("Form", "Error"), "%s\n%s" %
|
||||||
|
(QtGui.QApplication.translate("Form", "Check your query!"), e.__str__()))
|
||||||
|
|
||||||
|
|
||||||
def resumeHistory(self, item):
|
def resumeHistory(self, item):
|
||||||
itm = compatibility.get_py_str(item.text()).split(' = ', 1)
|
itm = compatibility.get_py_str(item.text()).split(' = ', 1)
|
||||||
@ -94,10 +95,12 @@ class relForm(QtGui.QMainWindow):
|
|||||||
'''Executes the query'''
|
'''Executes the query'''
|
||||||
|
|
||||||
query = compatibility.get_py_str(self.ui.txtQuery.text())
|
query = compatibility.get_py_str(self.ui.txtQuery.text())
|
||||||
res_rel=compatibility.get_py_str(self.ui.txtResult.text())#result relation's name
|
res_rel = compatibility.get_py_str(
|
||||||
|
self.ui.txtResult.text()) # result relation's name
|
||||||
|
|
||||||
if not rtypes.is_valid_relation_name(res_rel):
|
if not rtypes.is_valid_relation_name(res_rel):
|
||||||
QtGui.QMessageBox.information(self,QtGui.QApplication.translate("Form", "Error"),QtGui.QApplication.translate("Form", "Wrong name for destination relation."))
|
QtGui.QMessageBox.information(self, QtGui.QApplication.translate(
|
||||||
|
"Form", "Error"), QtGui.QApplication.translate("Form", "Wrong name for destination relation."))
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -106,22 +109,27 @@ class relForm(QtGui.QMainWindow):
|
|||||||
print query, "-->", expr # Printing debug
|
print query, "-->", expr # Printing debug
|
||||||
result = eval(expr, self.relations) # Evaluating the expression
|
result = eval(expr, self.relations) # Evaluating the expression
|
||||||
|
|
||||||
self.relations[res_rel]=result #Add the relation to the dictionary
|
self.relations[
|
||||||
|
res_rel] = result # Add the relation to the dictionary
|
||||||
self.updateRelations() # update the list
|
self.updateRelations() # update the list
|
||||||
self.selectedRelation = result
|
self.selectedRelation = result
|
||||||
self.showRelation(self.selectedRelation) #Show the result in the table
|
self.showRelation(self.selectedRelation)
|
||||||
|
# Show the result in the table
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print e.__unicode__()
|
print e.__unicode__()
|
||||||
QtGui.QMessageBox.information(None,QtGui.QApplication.translate("Form", "Error"),u"%s\n%s" % (QtGui.QApplication.translate("Form", "Check your query!"),e.__unicode__()) )
|
QtGui.QMessageBox.information(None, QtGui.QApplication.translate("Form", "Error"), u"%s\n%s" %
|
||||||
|
(QtGui.QApplication.translate("Form", "Check your query!"), e.__unicode__()))
|
||||||
return
|
return
|
||||||
|
|
||||||
# Adds to history
|
# Adds to history
|
||||||
item=u'%s = %s' % (compatibility.get_py_str(self.ui.txtResult.text()),compatibility.get_py_str(self.ui.txtQuery.text()))
|
item = u'%s = %s' % (compatibility.get_py_str(
|
||||||
|
self.ui.txtResult.text()), compatibility.get_py_str(self.ui.txtQuery.text()))
|
||||||
# item=item.decode('utf-8'))
|
# item=item.decode('utf-8'))
|
||||||
compatibility.add_list_item(self.ui.lstHistory, item)
|
compatibility.add_list_item(self.ui.lstHistory, item)
|
||||||
|
|
||||||
self.qcounter += 1
|
self.qcounter += 1
|
||||||
compatibility.set_utf8_text(self.ui.txtResult,u"_last%d"% self.qcounter) #Sets the result relation name to none
|
compatibility.set_utf8_text(self.ui.txtResult, u"_last%d" %
|
||||||
|
self.qcounter) # Sets the result relation name to none
|
||||||
|
|
||||||
def showRelation(self, rel):
|
def showRelation(self, rel):
|
||||||
'''Shows the selected relation into the table'''
|
'''Shows the selected relation into the table'''
|
||||||
@ -143,11 +151,12 @@ class relForm(QtGui.QMainWindow):
|
|||||||
# Sets columns
|
# Sets columns
|
||||||
for i in range(len(rel.header.attributes)):
|
for i in range(len(rel.header.attributes)):
|
||||||
self.ui.table.headerItem().setText(i, rel.header.attributes[i])
|
self.ui.table.headerItem().setText(i, rel.header.attributes[i])
|
||||||
self.ui.table.resizeColumnToContents(i) #Must be done in order to avoid too small columns
|
self.ui.table.resizeColumnToContents(
|
||||||
|
i) # Must be done in order to avoid too small columns
|
||||||
|
|
||||||
def printRelation(self, item):
|
def printRelation(self, item):
|
||||||
self.selectedRelation=self.relations[compatibility.get_py_str(item.text())]
|
self.selectedRelation = self.relations[
|
||||||
|
compatibility.get_py_str(item.text())]
|
||||||
self.showRelation(self.selectedRelation)
|
self.showRelation(self.selectedRelation)
|
||||||
|
|
||||||
def showAttributes(self, item):
|
def showAttributes(self, item):
|
||||||
@ -162,25 +171,31 @@ class relForm(QtGui.QMainWindow):
|
|||||||
for i in self.relations:
|
for i in self.relations:
|
||||||
if i != "__builtins__":
|
if i != "__builtins__":
|
||||||
self.ui.lstRelations.addItem(i)
|
self.ui.lstRelations.addItem(i)
|
||||||
|
|
||||||
def saveRelation(self):
|
def saveRelation(self):
|
||||||
filename = QtGui.QFileDialog.getSaveFileName(self,QtGui.QApplication.translate("Form", "Save Relation"),"",QtGui.QApplication.translate("Form", "Relations (*.csv)"))
|
filename = QtGui.QFileDialog.getSaveFileName(self, QtGui.QApplication.translate(
|
||||||
|
"Form", "Save Relation"), "", QtGui.QApplication.translate("Form", "Relations (*.csv)"))
|
||||||
|
|
||||||
filename = compatibility.get_filename(filename)
|
filename = compatibility.get_filename(filename)
|
||||||
if (len(filename) == 0): # Returns if no file was selected
|
if (len(filename) == 0): # Returns if no file was selected
|
||||||
return
|
return
|
||||||
self.selectedRelation.save(filename)
|
self.selectedRelation.save(filename)
|
||||||
return
|
return
|
||||||
|
|
||||||
def unloadRelation(self):
|
def unloadRelation(self):
|
||||||
for i in self.ui.lstRelations.selectedItems():
|
for i in self.ui.lstRelations.selectedItems():
|
||||||
del self.relations[compatibility.get_py_str(i.text())]
|
del self.relations[compatibility.get_py_str(i.text())]
|
||||||
self.updateRelations()
|
self.updateRelations()
|
||||||
|
|
||||||
def editRelation(self):
|
def editRelation(self):
|
||||||
import creator
|
import creator
|
||||||
for i in self.ui.lstRelations.selectedItems():
|
for i in self.ui.lstRelations.selectedItems():
|
||||||
result=creator.edit_relation(self.relations[compatibility.get_py_str(i.text())])
|
result = creator.edit_relation(
|
||||||
|
self.relations[compatibility.get_py_str(i.text())])
|
||||||
if result != None:
|
if result != None:
|
||||||
self.relations[compatibility.get_py_str(i.text())] = result
|
self.relations[compatibility.get_py_str(i.text())] = result
|
||||||
self.updateRelations()
|
self.updateRelations()
|
||||||
|
|
||||||
def newRelation(self):
|
def newRelation(self):
|
||||||
import creator
|
import creator
|
||||||
result = creator.edit_relation()
|
result = creator.edit_relation()
|
||||||
@ -190,7 +205,8 @@ class relForm(QtGui.QMainWindow):
|
|||||||
res = QtGui.QInputDialog.getText(
|
res = QtGui.QInputDialog.getText(
|
||||||
self,
|
self,
|
||||||
QtGui.QApplication.translate("Form", "New relation"),
|
QtGui.QApplication.translate("Form", "New relation"),
|
||||||
QtGui.QApplication.translate("Form", "Insert the name for the new relation"),
|
QtGui.QApplication.translate(
|
||||||
|
"Form", "Insert the name for the new relation"),
|
||||||
QtGui.QLineEdit.Normal, '')
|
QtGui.QLineEdit.Normal, '')
|
||||||
if res[1] == False or len(res[0]) == 0:
|
if res[1] == False or len(res[0]) == 0:
|
||||||
return
|
return
|
||||||
@ -199,22 +215,26 @@ class relForm(QtGui.QMainWindow):
|
|||||||
name = compatibility.get_py_str(res[0])
|
name = compatibility.get_py_str(res[0])
|
||||||
|
|
||||||
if not rtypes.is_valid_relation_name(name):
|
if not rtypes.is_valid_relation_name(name):
|
||||||
r=QtGui.QApplication.translate("Form", str("Wrong name for destination relation: %s." % name))
|
r = QtGui.QApplication.translate(
|
||||||
QtGui.QMessageBox.information(self,QtGui.QApplication.translate("Form", "Error"),r)
|
"Form", str("Wrong name for destination relation: %s." % name))
|
||||||
|
QtGui.QMessageBox.information(
|
||||||
|
self, QtGui.QApplication.translate("Form", "Error"), r)
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.relations[name] = result
|
self.relations[name] = result
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print e
|
print e
|
||||||
QtGui.QMessageBox.information(None,QtGui.QApplication.translate("Form", "Error"),"%s\n%s" % (QtGui.QApplication.translate("Form", "Check your query!"),e.__str__()) )
|
QtGui.QMessageBox.information(None, QtGui.QApplication.translate("Form", "Error"), "%s\n%s" %
|
||||||
|
(QtGui.QApplication.translate("Form", "Check your query!"), e.__str__()))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
self.updateRelations()
|
self.updateRelations()
|
||||||
|
|
||||||
def closeEvent(self, event):
|
def closeEvent(self, event):
|
||||||
self.save_settings()
|
self.save_settings()
|
||||||
event.accept()
|
event.accept()
|
||||||
|
|
||||||
def save_settings(self):
|
def save_settings(self):
|
||||||
# self.settings.setValue("width",)
|
# self.settings.setValue("width",)
|
||||||
pass
|
pass
|
||||||
@ -245,7 +265,8 @@ class relForm(QtGui.QMainWindow):
|
|||||||
It shouldn't be called giving filename but not giving name.'''
|
It shouldn't be called giving filename but not giving name.'''
|
||||||
# Asking for file to load
|
# Asking for file to load
|
||||||
if filename == None:
|
if filename == None:
|
||||||
filename = QtGui.QFileDialog.getOpenFileName(self,QtGui.QApplication.translate("Form", "Load Relation"),"",QtGui.QApplication.translate("Form", "Relations (*.csv);;Text Files (*.txt);;All Files (*)"))
|
filename = QtGui.QFileDialog.getOpenFileName(self, QtGui.QApplication.translate(
|
||||||
|
"Form", "Load Relation"), "", QtGui.QApplication.translate("Form", "Relations (*.csv);;Text Files (*.txt);;All Files (*)"))
|
||||||
filename = compatibility.get_filename(filename)
|
filename = compatibility.get_filename(filename)
|
||||||
|
|
||||||
# Default relation's name
|
# Default relation's name
|
||||||
@ -259,7 +280,9 @@ class relForm(QtGui.QMainWindow):
|
|||||||
defname = defname[:-4]
|
defname = defname[:-4]
|
||||||
|
|
||||||
if name == None: # Prompt dialog to insert name for the relation
|
if name == None: # Prompt dialog to insert name for the relation
|
||||||
res=QtGui.QInputDialog.getText(self, QtGui.QApplication.translate("Form", "New relation"),QtGui.QApplication.translate("Form", "Insert the name for the new relation"),
|
res = QtGui.QInputDialog.getText(
|
||||||
|
self, QtGui.QApplication.translate("Form", "New relation"), QtGui.QApplication.translate(
|
||||||
|
"Form", "Insert the name for the new relation"),
|
||||||
QtGui.QLineEdit.Normal, defname)
|
QtGui.QLineEdit.Normal, defname)
|
||||||
if res[1] == False or len(res[0]) == 0:
|
if res[1] == False or len(res[0]) == 0:
|
||||||
return
|
return
|
||||||
@ -268,44 +291,58 @@ class relForm(QtGui.QMainWindow):
|
|||||||
name = compatibility.get_py_str(res[0])
|
name = compatibility.get_py_str(res[0])
|
||||||
|
|
||||||
if not rtypes.is_valid_relation_name(name):
|
if not rtypes.is_valid_relation_name(name):
|
||||||
r=QtGui.QApplication.translate("Form", str("Wrong name for destination relation: %s." % name))
|
r = QtGui.QApplication.translate(
|
||||||
QtGui.QMessageBox.information(self,QtGui.QApplication.translate("Form", "Error"),r)
|
"Form", str("Wrong name for destination relation: %s." % name))
|
||||||
|
QtGui.QMessageBox.information(
|
||||||
|
self, QtGui.QApplication.translate("Form", "Error"), r)
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.relations[name] = relation.relation(filename)
|
self.relations[name] = relation.relation(filename)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print e
|
print e
|
||||||
QtGui.QMessageBox.information(None,QtGui.QApplication.translate("Form", "Error"),"%s\n%s" % (QtGui.QApplication.translate("Form", "Check your query!"),e.__str__()) )
|
QtGui.QMessageBox.information(None, QtGui.QApplication.translate("Form", "Error"), "%s\n%s" %
|
||||||
|
(QtGui.QApplication.translate("Form", "Check your query!"), e.__str__()))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
self.updateRelations()
|
self.updateRelations()
|
||||||
|
|
||||||
def addProduct(self):
|
def addProduct(self):
|
||||||
self.addSymbolInQuery(u"*")
|
self.addSymbolInQuery(u"*")
|
||||||
|
|
||||||
def addDifference(self):
|
def addDifference(self):
|
||||||
self.addSymbolInQuery(u"-")
|
self.addSymbolInQuery(u"-")
|
||||||
|
|
||||||
def addUnion(self):
|
def addUnion(self):
|
||||||
self.addSymbolInQuery(u"ᑌ")
|
self.addSymbolInQuery(u"ᑌ")
|
||||||
|
|
||||||
def addIntersection(self):
|
def addIntersection(self):
|
||||||
self.addSymbolInQuery(u"ᑎ")
|
self.addSymbolInQuery(u"ᑎ")
|
||||||
|
|
||||||
def addDivision(self):
|
def addDivision(self):
|
||||||
self.addSymbolInQuery(u"÷")
|
self.addSymbolInQuery(u"÷")
|
||||||
|
|
||||||
def addOLeft(self):
|
def addOLeft(self):
|
||||||
self.addSymbolInQuery(u"ᐅLEFTᐊ")
|
self.addSymbolInQuery(u"ᐅLEFTᐊ")
|
||||||
|
|
||||||
def addJoin(self):
|
def addJoin(self):
|
||||||
self.addSymbolInQuery(u"ᐅᐊ")
|
self.addSymbolInQuery(u"ᐅᐊ")
|
||||||
|
|
||||||
def addORight(self):
|
def addORight(self):
|
||||||
self.addSymbolInQuery(u"ᐅRIGHTᐊ")
|
self.addSymbolInQuery(u"ᐅRIGHTᐊ")
|
||||||
|
|
||||||
def addOuter(self):
|
def addOuter(self):
|
||||||
self.addSymbolInQuery(u"ᐅFULLᐊ")
|
self.addSymbolInQuery(u"ᐅFULLᐊ")
|
||||||
|
|
||||||
def addProjection(self):
|
def addProjection(self):
|
||||||
self.addSymbolInQuery(u"π")
|
self.addSymbolInQuery(u"π")
|
||||||
|
|
||||||
def addSelection(self):
|
def addSelection(self):
|
||||||
self.addSymbolInQuery(u"σ")
|
self.addSymbolInQuery(u"σ")
|
||||||
|
|
||||||
def addRename(self):
|
def addRename(self):
|
||||||
self.addSymbolInQuery(u"ρ")
|
self.addSymbolInQuery(u"ρ")
|
||||||
|
|
||||||
def addArrow(self):
|
def addArrow(self):
|
||||||
self.addSymbolInQuery(u"➡")
|
self.addSymbolInQuery(u"➡")
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Form implementation generated from reading ui file 'relational_gui/maingui.ui'
|
# Form implementation generated from reading ui file 'relational_gui/maingui.ui'
|
||||||
#
|
#
|
||||||
# Created: Fri Dec 27 00:05:54 2013
|
# Created: Fri Dec 27 00:23:51 2013
|
||||||
# by: PyQt4 UI code generator 4.10.3
|
# by: PyQt4 UI code generator 4.10.3
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Form implementation generated from reading ui file 'relational_gui/rel_edit.ui'
|
# Form implementation generated from reading ui file 'relational_gui/rel_edit.ui'
|
||||||
#
|
#
|
||||||
# Created: Fri Dec 27 00:05:54 2013
|
# Created: Fri Dec 27 00:23:51 2013
|
||||||
# by: PyQt4 UI code generator 4.10.3
|
# by: PyQt4 UI code generator 4.10.3
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Form implementation generated from reading ui file 'relational_gui/survey.ui'
|
# Form implementation generated from reading ui file 'relational_gui/survey.ui'
|
||||||
#
|
#
|
||||||
# Created: Fri Dec 27 00:05:54 2013
|
# Created: Fri Dec 27 00:23:51 2013
|
||||||
# by: PyQt4 UI code generator 4.10.3
|
# by: PyQt4 UI code generator 4.10.3
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
File diff suppressed because one or more lines are too long
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Form implementation generated from reading ui file 'relational_pyside/maingui.ui'
|
# Form implementation generated from reading ui file 'relational_pyside/maingui.ui'
|
||||||
#
|
#
|
||||||
# Created: Fri Dec 27 00:05:55 2013
|
# Created: Fri Dec 27 00:23:51 2013
|
||||||
# by: pyside-uic 0.2.15 running on PySide 1.2.1
|
# by: pyside-uic 0.2.15 running on PySide 1.2.1
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Form implementation generated from reading ui file 'relational_pyside/rel_edit.ui'
|
# Form implementation generated from reading ui file 'relational_pyside/rel_edit.ui'
|
||||||
#
|
#
|
||||||
# Created: Fri Dec 27 00:05:55 2013
|
# Created: Fri Dec 27 00:23:51 2013
|
||||||
# by: pyside-uic 0.2.15 running on PySide 1.2.1
|
# by: pyside-uic 0.2.15 running on PySide 1.2.1
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Form implementation generated from reading ui file 'relational_pyside/survey.ui'
|
# Form implementation generated from reading ui file 'relational_pyside/survey.ui'
|
||||||
#
|
#
|
||||||
# Created: Fri Dec 27 00:05:54 2013
|
# Created: Fri Dec 27 00:23:51 2013
|
||||||
# by: pyside-uic 0.2.15 running on PySide 1.2.1
|
# by: pyside-uic 0.2.15 running on PySide 1.2.1
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
@ -17,7 +17,8 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
# author Salvo "LtWorf" Tomaselli <tiposchi@tiscali.it>
|
# author Salvo "LtWorf" Tomaselli <tiposchi@tiscali.it>
|
||||||
# Initial readline code from http://www.doughellmann.com/PyMOTW/readline/index.html
|
# Initial readline code from
|
||||||
|
# http://www.doughellmann.com/PyMOTW/readline/index.html
|
||||||
|
|
||||||
import readline
|
import readline
|
||||||
import logging
|
import logging
|
||||||
@ -31,7 +32,9 @@ from xtermcolor import colorize
|
|||||||
PROMPT_COLOR = 0xffff00
|
PROMPT_COLOR = 0xffff00
|
||||||
ERROR_COLOR = 0xff0000
|
ERROR_COLOR = 0xff0000
|
||||||
|
|
||||||
|
|
||||||
class SimpleCompleter(object):
|
class SimpleCompleter(object):
|
||||||
|
|
||||||
'''Handles completion'''
|
'''Handles completion'''
|
||||||
|
|
||||||
def __init__(self, options):
|
def __init__(self, options):
|
||||||
@ -95,11 +98,15 @@ class SimpleCompleter(object):
|
|||||||
|
|
||||||
|
|
||||||
relations = {}
|
relations = {}
|
||||||
completer=SimpleCompleter(['SURVEY','LIST','LOAD ','UNLOAD ','HELP ','QUIT','SAVE ','_PRODUCT ','_UNION ','_INTERSECTION ','_DIFFERENCE ','_JOIN ','_LJOIN ','_RJOIN ','_FJOIN ','_PROJECTION ','_RENAME_TO ','_SELECTION ','_RENAME ','_DIVISION '])
|
completer = SimpleCompleter(
|
||||||
|
['SURVEY', 'LIST', 'LOAD ', 'UNLOAD ', 'HELP ', 'QUIT', 'SAVE ', '_PRODUCT ', '_UNION ', '_INTERSECTION ',
|
||||||
|
'_DIFFERENCE ', '_JOIN ', '_LJOIN ', '_RJOIN ', '_FJOIN ', '_PROJECTION ', '_RENAME_TO ', '_SELECTION ', '_RENAME ', '_DIVISION '])
|
||||||
|
|
||||||
|
|
||||||
def load_relation(filename, defname=None):
|
def load_relation(filename, defname=None):
|
||||||
if not os.path.isfile(filename):
|
if not os.path.isfile(filename):
|
||||||
print >> sys.stderr, colorize("%s is not a file" % filename,ERROR_COLOR)
|
print >> sys.stderr, colorize(
|
||||||
|
"%s is not a file" % filename, ERROR_COLOR)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
f = filename.split('/')
|
f = filename.split('/')
|
||||||
@ -109,7 +116,8 @@ def load_relation(filename,defname=None):
|
|||||||
defname = defname[:-4]
|
defname = defname[:-4]
|
||||||
|
|
||||||
if not rtypes.is_valid_relation_name(defname):
|
if not rtypes.is_valid_relation_name(defname):
|
||||||
print >> sys.stderr, colorize("%s is not a valid relation name" % defname,ERROR_COLOR)
|
print >> sys.stderr, colorize(
|
||||||
|
"%s is not a valid relation name" % defname, ERROR_COLOR)
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
relations[defname] = relation.relation(filename)
|
relations[defname] = relation.relation(filename)
|
||||||
@ -121,18 +129,21 @@ def load_relation(filename,defname=None):
|
|||||||
print >>sys.stderr, colorize(e, ERROR_COLOR)
|
print >>sys.stderr, colorize(e, ERROR_COLOR)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def survey():
|
def survey():
|
||||||
'''performs a survey'''
|
'''performs a survey'''
|
||||||
from relational import maintenance
|
from relational import maintenance
|
||||||
|
|
||||||
post = {'software': 'Relational algebra (cli)', 'version': version}
|
post = {'software': 'Relational algebra (cli)', 'version': version}
|
||||||
|
|
||||||
fields=('System','Country','School','Age','How did you find','email (only if you want a reply)','Comments')
|
fields = ('System', 'Country', 'School', 'Age', 'How did you find',
|
||||||
|
'email (only if you want a reply)', 'Comments')
|
||||||
for i in fields:
|
for i in fields:
|
||||||
a = raw_input('%s: ' % i)
|
a = raw_input('%s: ' % i)
|
||||||
post[i] = a
|
post[i] = a
|
||||||
maintenance.send_survey(post)
|
maintenance.send_survey(post)
|
||||||
|
|
||||||
|
|
||||||
def help(command):
|
def help(command):
|
||||||
'''Prints help on the various functions'''
|
'''Prints help on the various functions'''
|
||||||
p = command.split(' ', 1)
|
p = command.split(' ', 1)
|
||||||
@ -225,6 +236,7 @@ def exec_line(command):
|
|||||||
else:
|
else:
|
||||||
exec_query(command)
|
exec_query(command)
|
||||||
|
|
||||||
|
|
||||||
def replacements(query):
|
def replacements(query):
|
||||||
'''This funcion replaces ascii easy operators with the correct ones'''
|
'''This funcion replaces ascii easy operators with the correct ones'''
|
||||||
query = query.replace(u'_PRODUCT', u'*')
|
query = query.replace(u'_PRODUCT', u'*')
|
||||||
@ -242,6 +254,7 @@ def replacements(query):
|
|||||||
query = query.replace(u'_DIVISION', u'÷')
|
query = query.replace(u'_DIVISION', u'÷')
|
||||||
return query
|
return query
|
||||||
|
|
||||||
|
|
||||||
def exec_query(command):
|
def exec_query(command):
|
||||||
'''This function executes a query and prints the result on the screen
|
'''This function executes a query and prints the result on the screen
|
||||||
if the command terminates with ";" the result will not be printed
|
if the command terminates with ";" the result will not be printed
|
||||||
@ -255,8 +268,6 @@ def exec_query(command):
|
|||||||
else:
|
else:
|
||||||
printrel = True
|
printrel = True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Performs replacements for weird operators
|
# Performs replacements for weird operators
|
||||||
command = replacements(command)
|
command = replacements(command)
|
||||||
|
|
||||||
@ -270,7 +281,6 @@ def exec_query(command):
|
|||||||
relname = 'last_'
|
relname = 'last_'
|
||||||
query = command
|
query = command
|
||||||
|
|
||||||
|
|
||||||
# Execute query
|
# Execute query
|
||||||
try:
|
try:
|
||||||
pyquery = parser.parse(query)
|
pyquery = parser.parse(query)
|
||||||
@ -288,6 +298,7 @@ def exec_query(command):
|
|||||||
except Exception, e:
|
except Exception, e:
|
||||||
print colorize(e, ERROR_COLOR)
|
print colorize(e, ERROR_COLOR)
|
||||||
|
|
||||||
|
|
||||||
def main(files=[]):
|
def main(files=[]):
|
||||||
print colorize('> ', PROMPT_COLOR) + "; Type HELP to get the HELP"
|
print colorize('> ', PROMPT_COLOR) + "; Type HELP to get the HELP"
|
||||||
print colorize('> ', PROMPT_COLOR) + "; Completion is activated using the tab (if supported by the terminal)"
|
print colorize('> ', PROMPT_COLOR) + "; Completion is activated using the tab (if supported by the terminal)"
|
||||||
@ -301,7 +312,6 @@ def main(files=[]):
|
|||||||
readline.parse_and_bind('set editing-mode emacs')
|
readline.parse_and_bind('set editing-mode emacs')
|
||||||
readline.set_completer_delims(" ")
|
readline.set_completer_delims(" ")
|
||||||
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
line = raw_input(colorize('> ', PROMPT_COLOR))
|
line = raw_input(colorize('> ', PROMPT_COLOR))
|
||||||
@ -317,4 +327,3 @@ def main(files=[]):
|
|||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user