Relational Python: Restrict


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 was in the categories: python relational_python but I'm still in the process of migrating categories over.

The original post had 6 comments I'm in the process of migrating over.