Exemple #1
0
    def _where_clause(self):
        """Build the where clause.

        Example:
        If the path is Environment->Host

        WHERE
            environment.uuid = $identity AND
            r_t1_state.from <= $t1 < r_t1_state.to AND
            r_t2_state.from <= $t2 < r_t2_state.to AND
            t1_state <> t2_state AND
            ALL (r IN RELATIONSHIPS(p_t1) WHERE r.from <= $t1 < r.to) AND
            ALL (r in RELATIONSHIPS(p_t2) WHERE r.from <= $t2 < r.to)

        :returns: Where clause
        :rtype: str
        """
        wheres = [
            '{}.{} = $identity'.format(
                self._var_from_label(self.path[0]),
                registry.identity_property(self.path[0]))
        ]

        wheres.append('r_t1_state.from <= $t1 < r_t1_state.to')
        wheres.append('r_t2_state.from <= $t2 < r_t2_state.to')
        wheres.append('t1_state <> t2_state')

        wheres.append(
            'ALL (r IN RELATIONSHIPS(p_t1) WHERE r.from <= $t1 < r.to)')
        wheres.append(
            'ALL (r in RELATIONSHIPS(p_t2) WHERE r.from <= $t2 < r.to)')

        cipher = "WHERE " + ' AND '.join(wheres)
        return cipher
Exemple #2
0
    def __init__(self, path, identity, times, pagesize=5000):
        """Init the diff query

        :param path: Path to build a diff query around
        :type path: list
        :param identity: Starting node's identity
        :type identity: str
        :param times: Two times for comparison
        :type times: tuple
        :param pagesize: How many results to fetch at once
        :type pagesize: int
        """
        self.path = path
        self.end = self.path[-1]
        self.full_path = registry.path(self.end)
        self.t1 = times[0]
        self.t2 = times[1]
        self.identity = identity
        self.pagesize = pagesize

        self.selects = [
            '{}.{}'.format(self._var_from_label(m),
                           registry.identity_property(m)) for m in self.path
        ]

        self.params = {'t1': self.t1, 't2': self.t2, 'identity': self.identity}
 def __str__(self):
     var = self.label.lower()
     identity_prop = registry.identity_property(self.label)
     cypher = "MATCH p = ({}:{})-[*]->(other)".format(var, self.label)
     cypher += "\nWHERE {}.{} = $identity".format(var, identity_prop)
     cypher += "\nWITH relationships(p) as rels"
     cypher += "\nUNWIND rels as r"
     cypher += "\nreturn DISTINCT r.from as t"
     cypher += "\nORDER BY t DESC"
     return cypher
Exemple #4
0
    def getnode(self, model, data):
        """Get a node of model type matching data.

        Create a new node if one does not exist.

        :param model: Name of the model
        :type model: str
        :param data: Dict representation of node
        :type data: dict
        :returns: Node with matching data
        :rtype: Node
        """
        identity = data[registry.identity_property(model)]
        nodemap = self.nodes.setdefault(model, {})
        node = nodemap.setdefault(identity, Node(identity, model))
        return node
    def node_at_time(self, t):
        """Get a node from the database at time t.

        :param t: A time in milliseconds
        :type t: int
        :returns: A dictionary of properties
        :rtype: dict
        """
        var_models = []
        rels = []
        returns = ['n']
        for model, reltype in self.full_path:
            var_models.append((model.lower(), model))
            rels.append(reltype)
        var_models.append(('n', self.model))

        if registry.state_properties(self.model):
            var_models.append(('ns', registry.models[self.model].state_label))
            rels.append('HAS_STATE')
            returns.append('ns')

        cipher = 'MATCH p = ({}:{})'.format(var_models[0][0], var_models[0][1])

        for var_model, rel in zip(var_models[1:], rels):
            var, model = var_model
            cipher += '-[:{}]->({}:{})'.format(rel, var, model)

        cipher += (
            ' WHERE ALL (r IN RELATIONSHIPS(p) WHERE r.from <= $t < r.to) AND'
        )
        cipher += (
            ' n.{} = $identity'.format(registry.identity_property(self.model))
        )
        cipher += ' RETURN ' + ','.join(returns) + ' LIMIT 1'

        self.params['t'] = t

        record = self._fetch(cipher).single()
        if record is None:
            node = {}
        else:
            node = {k: v for k, v in record['n'].items()}
            if 'ns' in record:
                for k, v in record['ns'].items():
                    node[k] = v
        return node
Exemple #6
0
    def _orderby_clause(self):
        """Create order by clause.

        :returns: ORDER BY clause
        :rtype: str
        """
        cypher = ' \nORDER BY '

        # Default to ordering by identity property
        ob = []
        if not self._orderby:
            self.orderby(registry.identity_property(self.label),
                         'ASC',
                         label=self.label)
        for ob_varname, ob_prop, ob_dir in self._orderby:
            ob.append('{}.{} {}'.format(ob_varname, ob_prop, ob_dir))
        cypher += ', '.join(ob)
        return cypher
Exemple #7
0
    def feedpath(self, path, time, side):
        """Feed all of a path from a side to the diff.

        :param path: List of models indicating path through data to a model
        :type path: list
        :param time: Integer milliseconds since epoch
        :type time: int
        :param side: Which side to feed the diff from.
        :type side: str
        """
        # Build query
        q = Query(path[-1]) \
            .filter(
                registry.identity_property(self.model),
                '=',
                self.identity, self.model
            ).time(time)

        # Start at page 1 and page through all results.
        page = 1
        records = q.page(page, self.pagesize)
        while (records):
            for record in records:
                parent = None
                for label in path:
                    # Update diff with results
                    node = self.getnode(label, record[label])
                    node.update(record[label], side)

                    # Make parent -> child relationship
                    if parent is not None:
                        parent.add_child(label, node, side)
                        node.parents.add(parent)

                    # Advance parent for next part of path.
                    parent = node

            page += 1
            records = q.page(page, self.pagesize)
Exemple #8
0
    def _match_clause(self):
        """Build the multistage match clause.

        Find all paths that match in t2. Then find all paths that match in t1
        that are not in t2.

        Example:
        If your path is Environment->Host->AptPackage

        MATCH
            p_t2 =
                (environment:Environment)-[:HAS_HOST]->
                (host:Host)-[:HAS_APT_PACKAGE]->
                (aptpackage:AptPackage)
        WHERE
            environment.uuid = $identity AND
            ALL (r IN RELATIONSHIPS(p_t2) WHERE r.from <= $t2 < r.to)
        WITH
            COLLECT([environment,host,aptpackage]) as t2_nodes
        MATCH
            p_t1 =
                (environment:Environment)-[:HAS_HOST]->
                (host:Host)-[:HAS_APT_PACKAGE]->
                (aptpackage:AptPackage)
        WHERE
            environment.uuid = $identity AND
            ALL (r IN RELATIONSHIPS(p_t1) WHERE r.from <= $t1 < r.to) AND
            NOT [environment,host,aptpackage] IN t2_nodes

        :returns: Major portion of cipher query
        :rtype: str
        """
        path_vars = []
        for model, _ in self.full_path:
            path_vars.append(self._var_from_label(model))
        path_vars.append(self._var_from_label(self.end))

        cipher = 'MATCH p_t2 = '
        for model, reltype in self.full_path:
            cipher += '({}:{})-[:{}]->'.format(self._var_from_label(model),
                                               model, reltype)
        cipher += '({}:{})'.format(self._var_from_label(self.end), self.end)

        cipher += '\nWHERE '
        cipher += '{}.{} = $identity AND '.format(
            self._var_from_label(self.path[0]),
            registry.identity_property(self.path[0]))
        cipher += 'ALL (r IN RELATIONSHIPS(p_t2) WHERE r.from <= $t2 < r.to)'
        cipher += '\nWITH COLLECT([{}]) as t2_nodes'.format(
            ','.join(path_vars))

        cipher += '\nMATCH p_t1 = '
        for model, reltype in self.full_path:
            cipher += '({}:{})-[:{}]->'.format(self._var_from_label(model),
                                               model, reltype)
        cipher += '({}:{})'.format(self._var_from_label(self.end), self.end)
        cipher += '\nWHERE '
        cipher += '{}.{} = $identity AND '.format(
            self._var_from_label(self.path[0]),
            registry.identity_property(self.path[0]))
        cipher += 'ALL (r IN RELATIONSHIPS(p_t1) WHERE r.from <= $t1 < r.to)'
        cipher += ' AND NOT [{}] IN t2_nodes'.format(','.join(path_vars))
        return cipher