diff --git a/CHANGELOG b/CHANGELOG index effa5db..0715b77 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -84,4 +84,5 @@ - Implemented selection_and_product specific optimization - Added stub for converting SQL to relational algebra - Implemented futile_union_intersection_subtraction general optimization -- Implemented swap_rename_projection general optimization \ No newline at end of file +- Implemented swap_rename_projection general optimization +- Replaced old relational algebra to python compiler with new one based on the new tokenizer/parser (Rev 188) \ No newline at end of file diff --git a/relational/optimizer.py b/relational/optimizer.py index c8406d8..629dd8f 100644 --- a/relational/optimizer.py +++ b/relational/optimizer.py @@ -97,11 +97,13 @@ class node (object): #Converting parameters if self.name=='π':#Projection - prop=prop.replace(' ','').replace(',','\",\"') + prop='\"%s\"' % prop.replace(' ','').replace(',','\",\"') elif self.name=="ρ": #Rename - prop=prop.replace(',','\",\"').replace('➡','\":\"').replace(' ','') + prop='{\"%s\"}' % prop.replace(',','\",\"').replace('➡','\":\"').replace(' ','') + else: #Selection + prop='\"%s\"' % prop - return '%s.%s(\"%s\")' % (self.child.toPython(),op_functions[self.name],prop) + return '%s.%s(%s)' % (self.child.toPython(),op_functions[self.name],prop) else: return self.name pass @@ -317,6 +319,13 @@ if __name__=="__main__": #print optimizations.selection_and_product(n,rels) + ''' + σ skill=='C' (π id,name,chief,age (σ chief==i and age>a (ρ id➡i,age➡a(π id,age(people))*people)) ᐅᐊ 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 n diff --git a/relational/parser.py b/relational/parser.py index 7ba70c6..9a49705 100644 --- a/relational/parser.py +++ b/relational/parser.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- # coding=UTF-8 # Relational # Copyright (C) 2008 Salvo "LtWorf" Tomaselli @@ -16,6 +17,9 @@ # along with this program. If not, see . # # author Salvo "LtWorf" Tomaselli + +import optimizer + def parse(expr): '''This function parses a relational algebra expression, converting it into python, executable by eval function to get the result of the expression. @@ -46,120 +50,8 @@ def parse(expr): ρid➡i,name➡n(π a,b(A)) A ᐅᐊ B ''' - symbols=("σ","π","ρ") + return optimizer.tree(expr).toPython() - starts=[]#List with starts and ends - parenthesis=0 - lexpr=list(expr) - #Parses the string finding all 1st level parenthesis - for i in range(len(lexpr)): - if lexpr[i]=="(": - if parenthesis==0: - starts.append(i+1) - parenthesis+=1 - elif lexpr[i]==")": - parenthesis-=1 - if parenthesis==0: - starts.append(i) - - - if len(starts)==0: #No parenthesis: no operators with parameters - return parse_op(expr) - - while len(starts)>0: - #Converting the last complex operator into python - end=starts.pop() - start=starts.pop() - - internal=parse(expr[start:end]) - - endp=start-1 - symbol="" - for i in range(endp,-1,-1): - if expr[i:i+2] in symbols: - symbol=expr[i:i+2] - start=i+2 - break - if expr[i:i+1] ==")": - break #No symbol before - - parameters=expr[start:endp] - - res="" #String for result - if symbol=="π":#Projection - params="" - count=0 - for i in parameters.split(","): - if count!=0: - params+="," - else: - count=1 - params+="\"%s\"" % (i.strip()) - - res="%s.projection(%s)" % (internal,params) - expr= ("%s%s%s") % (expr[0:start-2],res,expr[end+1:]) - elif symbol== "σ": #Selection - res="%s.selection(\"%s\")" % (internal,parameters) - expr= ("%s%s%s") % (expr[0:start-2],res,expr[end+1:]) - elif symbol=="ρ": #Rename - params=parameters.replace(",","\",\"").replace("➡","\":\"").replace(" ","") - res="%s.rename({\"%s\"})" % (internal,params) - expr= ("%s%s%s") % (expr[0:start-2],res,expr[end+1:]) - else: - res="(%s)" % (internal) - expr= ("%s%s%s") % (expr[0:start-1],res,expr[end+1:]) - #Last complex operator is replaced with it's python code - #Next cycle will do the same to the new last unparsed complex operator - #At the end, parse_op will convert operators without parameters - return parse_op(expr) - -def parse_op(expr): - '''This function parses a relational algebra expression including only operators - without parameters, converting it into python. - Executable by eval function to get the result of the expression.''' - - result="" - symbols={} - - symbols["*"]=".product(%s)" - symbols["-"]=".difference(%s)" - symbols["ᑌ"]=".union(%s)" - symbols["ᑎ"]=".intersection(%s)" - symbols["ᐅLEFTᐊ"]=".outer_left(%s)" - symbols["ᐅRIGHTᐊ"]=".outer_right(%s)" - symbols["ᐅFULLᐊ"]=".outer(%s)" - symbols["ᐅᐊ"]=".join(%s)" - - - #We want to avoid to parse expressions within quotes. - #We split the string into an array, and we parse only the ones with even index - quotes=expr.split('"'); - - - - for i in range (0,len(quotes),2): - for j in symbols: - quotes[i]=quotes[i].replace(j,"_____%s_____"% (j)) - - #The parts outside the quotes was parsed, put the string together again - if (len(quotes)>1): - expr= '"'.join(quotes) - else: - expr= quotes[0] - - tokens=expr.split("_____") - - i=0; - tk_l=len(tokens) - while i