The next relational operator I implemented in my relational python experiment was RESTRICT.
Restrict filters the set of tuples by some condition. In many formulations of the relational algebra, the restriction is on just one attribute at a time and you chain RESTRICTs together but for relational python, we'll use a lambda that can do rich testing across one or more attributes.
Here was my first attempt:
def RESTRICT(orig_rel, restriction): new_rel = Rel(orig_rel.attributes()) for tup in orig_rel.tuples(): if restriction(tup): new_rel.add(tup) return new_rel
but I thought it would be neater as a list comprehension. The only problem was, there was no way in Rel to add multiple tuples at a time so I added the following method to Rel:
def add_multiple(self, tupset): self.tuples_.update(set([self._convert_dict(tup) for tup in tupset]))
This enabled me to rewrite RESTRICT as:
def RESTRICT(orig_rel, restriction): new_rel = Rel(orig_rel.attributes()) new_rel.add_multiple([tup for tup in orig_rel.tuples() if restriction(tup)]) return new_rel
Here's how to use the function:
rel4 = RESTRICT(rel1, lambda tup: tup["SALARY"] > "30K")
And, of course, I had to write a lazy "view" version:
class RESTRICT_VIEW(Rel): def __init__(self, orig_rel, restriction): Rel.__init__(self, orig_rel.attributes()) self.orig_rel = orig_rel self.restriction = restriction def add(self, tup): raise Exception def tuples(self): for tup in self.orig_rel.tuples(): if self.restriction(tup): yield tup
As always, suggestions for improvements are welcome in comments.
Next up, I'll implement the cross product.
The original post had 6 comments I'm in the process of migrating over.