diff --git a/relation.py b/relation.py index f5f296b..62e005f 100644 --- a/relation.py +++ b/relation.py @@ -54,6 +54,18 @@ class relation (object): fp=file(filename,'w') fp.write(res) fp.close() + def rearrange(self,other): + '''If two relations share the same attributes in a different order, this method + will use projection to make them have the same attributes' order. + It is not exactely related to relational algebra. Just a method used + internally. + Will return None if they don't share the same attributes''' + if (self.__class__!=other.__class__): + return None + if self.header.sharedAttributes(other.header) == len(self.header.attributes) == len(other.header.attributes): + return other.projection(list(self.header.attributes)) + return None + def selection(self,expr): '''Selection, expr must be a valid boolean expression, can contain field names, constant, math operations and boolean ones.''' @@ -150,6 +162,7 @@ class relation (object): Will return an empty one if there are no common items. Will return None if headers are different. It is possible to use projection and rename to make headers match.''' + other=self.rearrange(other) #Rearranges attributes' order if (self.__class__!=other.__class__)or(self.header!=other.header): return None newt=relation() @@ -167,6 +180,7 @@ class relation (object): Will return an empty one if the second is a superset of first. Will return None if headers are different. It is possible to use projection and rename to make headers match.''' + other=self.rearrange(other) #Rearranges attributes' order if (self.__class__!=other.__class__)or(self.header!=other.header): return None newt=relation() @@ -185,6 +199,7 @@ class relation (object): Will not insert tuplicated items. Will return None if headers are different. It is possible to use projection and rename to make headers match.''' + other=self.rearrange(other) #Rearranges attributes' order if (self.__class__!=other.__class__)or(self.header!=other.header): return None newt=relation() @@ -198,7 +213,81 @@ class relation (object): if e not in newt.content: newt.content.append(list(e)) return newt + def outer(self,other): + '''Does a left and a right outer join and returns their union.''' + a=self.outer_right(other) + b=self.outer_left(other) + print a + print b + return a.union(b) + + def outer_right(self,other): + '''Same as left join, with swapped parameters''' + return self.outer_left(other,True) + + def outer_left(self,other,swap=False): + '''Outer left join. Considers self as left and param as right. If the + tuple has no corrispondence, empty attributes are filled with a "---" + string. This is due to the fact that empty string or a space would cause + problems when saving the relation. + Just like natural join, it works considering shared attributes. + If swap is True, it will behave as a right join''' + + if swap: + tmp=other + other=self + self=tmp + + shared=[] + for i in self.header.attributes: + if i in other.header.attributes: + shared.append(i) + + newt=relation() #Creates the new relation + + #Adds all the attributes of the 1st relation + newt.header=header(list(self.header.attributes)) + + #Adds all the attributes of the 2nd, when non shared + for i in other.header.attributes: + if i not in shared: + newt.header.attributes.append(i) + #Shared ids of self + sid=self.header.getAttributesId(shared) + #Shared ids of the other relation + oid=other.header.getAttributesId(shared) + + #Non shared ids of the other relation + noid=[] + for i in range(len(other.header.attributes)): + if i not in oid: + noid.append(i) + + for i in self.content: + #Tuple partecipated to the join? + added=False + for j in other.content: + match=True + for k in range(len(sid)): + match=match and ( i[sid[k]]== j[oid[k]]) + + if match: + item=list(i) + for l in noid: + item.append(j[l]) + + newt.content.append(item) + added=True + #If it didn't partecipate, adds it + if not added: + item=list(i) + for l in range(len(noid)): + item.append("---") + newt.content.append(item) + + return newt + def join(self,other): '''Natural join, joins on shared attributes (one or more). If there are no shared attributes, it will behave as cartesian product.''' diff --git a/samples/skills.tlb b/samples/skills.tlb index ca0d9e5..57a5d6e 100644 --- a/samples/skills.tlb +++ b/samples/skills.tlb @@ -14,4 +14,5 @@ id skill 5 C 7 Python 7 C -7 PHP \ No newline at end of file +7 PHP +9 Java \ No newline at end of file