Beispiel #1
0
    def initialize_tables(self, tablenames, formulas, target=None):
        """Event handler for (re)initializing a collection of tables."""
        # translate FORMULAS into list of formula objects
        actual_formulas = []
        formula_tables = set()

        if isinstance(formulas, basestring):
            formulas = self.parse(formulas)

        for formula in formulas:
            if isinstance(formula, basestring):
                formula = self.parse1(formula)
            elif isinstance(formula, tuple):
                formula = compile.Literal.create_from_iter(formula)
            assert formula.is_atom()
            actual_formulas.append(formula)
            formula_tables.add(formula.table)

        tablenames = set(tablenames) | formula_tables
        self.table_log(None, "Initializing tables %s with %s",
                       iterstr(tablenames), iterstr(actual_formulas))
        # implement initialization by computing the requisite
        #   update.
        theory = self.get_target(target)
        old = set(theory.content(tablenames=tablenames))
        new = set(actual_formulas)
        to_add = new - old
        to_rem = old - new
        to_add = [Event(formula_, insert=True) for formula_ in to_add]
        to_rem = [Event(formula_, insert=False) for formula_ in to_rem]
        self.table_log(None, "Initialize converted to update with %s and %s",
                       iterstr(to_add), iterstr(to_rem))
        return self.update(to_add + to_rem, target=target)
Beispiel #2
0
    def process_new_bindings(self, bindings, atom, insert, original_rule):
        """Process new bindings.

        For each of BINDINGS, apply to ATOM, and enqueue it as an insert if
        INSERT is True and as a delete otherwise.
        """
        # for each binding, compute generated tuple and group bindings
        #    by the tuple they generated
        new_atoms = {}
        for binding in bindings:
            new_atom = atom.plug(binding)
            if new_atom not in new_atoms:
                new_atoms[new_atom] = []
            new_atoms[new_atom].append(Database.Proof(binding, original_rule))
        self.log(atom.table, "new tuples generated: %s", iterstr(new_atoms))

        # enqueue each distinct generated tuple, recording appropriate bindings
        for new_atom in new_atoms:
            # self.log(event.table, "new_tuple %s: %s", new_tuple,
            #          new_tuples[new_tuple])
            # Only enqueue if new data.
            # Putting the check here is necessary to support recursion.
            self.enqueue(
                Event(formula=new_atom,
                      proofs=new_atoms[new_atom],
                      insert=insert))
Beispiel #3
0
    def enqueue_any(self, event):
        """Enqueue event.

        Processing rules is a bit different than processing atoms
        in that they generate additional events that we want
        to process either before the rule is deleted or after
        it is inserted.  PROCESS_QUEUE is similar but assumes
        that only the data will cause propagations (and ignores
        included theories).
        """
        # Note: all included theories must define MODIFY
        formula = event.formula
        if formula.is_atom():
            self.log(formula.tablename(), "compute/enq: atom %s", formula)
            assert not self.is_view(
                formula.table), ("Cannot directly modify tables" +
                                 " computed from other tables")
            # self.log(formula.table, "%s: %s", text, formula)
            self.enqueue(event)
            return []
        else:
            # rules do not need to talk to included theories because they
            #   only generate events for views
            # need to eliminate self-joins here so that we fill all
            #   the tables introduced by self-join elimination.
            for rule in DeltaRuleTheory.eliminate_self_joins([formula]):
                new_event = Event(formula=rule,
                                  insert=event.insert,
                                  target=event.target)
                self.enqueue(new_event)
            return []
Beispiel #4
0
    def load_file(self, filename, target=None):
        """Load content from file.

        Compile the given FILENAME and insert each of the statements
        into the runtime.  Assumes that FILENAME includes no modals.
        """
        formulas = compile.parse_file(
            filename, theories=self.theory)
        try:
            self.policy_object(target)
        except KeyError:
            self.create_policy(target)
        return self.update(
            [Event(formula=x, insert=True) for x in formulas], target)
Beispiel #5
0
    def project_updates(self, delta, theory):
        """Project atom/delta rule insertion/deletion.

        Takes an atom/rule DELTA with update head table
        (i.e. ending in + or -) and inserts/deletes, respectively,
        that atom/rule into THEORY after stripping
        the +/-. Returns None if DELTA had no effect on the
        current state.
        """
        theory = delta.theory_name() or theory

        self.table_log(None, "Applying update %s to %s", delta, theory)
        th_obj = self.theory[theory]
        insert = delta.tablename().endswith('+')
        newdelta = delta.drop_update().drop_theory()
        changed = th_obj.update([Event(formula=newdelta, insert=insert)])
        if changed:
            return delta.invert_update()
        else:
            return None
Beispiel #6
0
 def delete(self, formula):
     return self.update([Event(formula=formula, insert=False)])
Beispiel #7
0
 def insert(self, formula):
     return self.update([Event(formula=formula, insert=True)])
Beispiel #8
0
 def delete(self, rule):
     changes = self.update([Event(formula=rule, insert=False)])
     return [event.formula for event in changes]
Beispiel #9
0
 def insert(self, rule):
     changes = self.update([Event(formula=rule, insert=True)])
     return [event.formula for event in changes]
Beispiel #10
0
 def define(self, rules):
     """Empties and then inserts RULES."""
     self.empty()
     return self.update(
         [Event(formula=rule, insert=True) for rule in rules])
Beispiel #11
0
 def delete(self, atom, proofs=None):
     """Deletes ATOM from the DB.  Returns changes."""
     return self.modify(Event(formula=atom, insert=False, proofs=proofs))
Beispiel #12
0
 def insert(self, atom, proofs=None):
     """Inserts ATOM into the DB.  Returns changes."""
     return self.modify(Event(formula=atom, insert=True, proofs=proofs))
Beispiel #13
0
 def delete_obj(self, formula, theory_string):
     return self.update_obj([Event(formula=formula, insert=False,
                                   target=theory_string)])
Beispiel #14
0
 def delete_string(self, policy_string, theory_string):
     policy = self.parse(policy_string)
     return self.update_obj(
         [Event(formula=x, insert=False, target=theory_string)
          for x in policy])
Beispiel #15
0
 def insert_obj(self, formula, theory_string):
     return self.update_obj([Event(formula=formula, insert=True,
                                   target=theory_string)])