def get_node_information_query(node_name, node_type=None): """ :param node_name: name of the node to get information about. :return: the query for showing general information of one node (any entity) with a specific name. """ pypher_object = Pypher() if node_type is None: pypher_object.Match.node('u').where.u.__name__.CONTAINS( Param('per_param', node_name)) else: pypher_object.Match.node( 'u', labels=node_type).where.u.__name__.CONTAINS( Param('per_param', node_name)) pypher_object.RETURN('u') return GenerateQuery.reformat_query(pypher_object)
def filtering(self, query_variable): wheres = [] fields = self.controller.filter_by for i, field in enumerate(fields): try: if '.' in field: splits = field.split('.') field = splits[-1] query_variable = splits[0] value = self.controller.get_argument(field) except MissingArgumentError as e: # we will swallow these, but let the others proprogate continue if value: exclude = False clause = __() if value[0] == '!': exclude = True value = value[1:] if exclude: clause = clause.NOT query_variable = self.get_mapped_query_variable(query_variable) name = '{}_{}'.format(field, i).replace('.', '_') value = Param(name, value) clause = getattr(clause, query_variable).property(field) clause = clause.CONTAINS(value) wheres.append(clause) return wheres
def _entity_by_id_builder(self, entity, id_val, add_labels=False): qv = entity.query_variable if not qv: qv = VM.set_query_var(entity) _id = VM.get_next(entity, 'id') _id = Param(_id, id_val) node_kwargs = {} if add_labels: node_kwargs['labels'] = entity.labels if isinstance(entity, Relationship): node = __.node(**node_kwargs).relationship(qv).node() else: node = __.node(qv, **node_kwargs) where = __.ID(qv) == _id self.matches.append(node) self.wheres.append(where) self.returns.append(entity.query_variable) return self
def delete_node(self, entity): _id = VM.get_next(entity, 'id') _id = Param(_id, entity.id) match = __.node(entity.query_variable) match.WHERE(__.ID(entity.query_variable) == _id) self.matches.append(match) self.deletes.append(entity.query_variable) return self
def _node_by_id(self, entity): qv = entity.query_variable if not qv: qv = VM.set_query_var(entity) _id = VM.get_next(entity, 'id') _id = Param(_id, entity.id) return __.node(qv).WHERE(__.ID(qv) == _id)
def test_can_add_param_to_statement(self): p = Pypher() n = 'some_param' v = 'value {}'.format(random()) param = Param(n, v) p.CONTAINS(param) exp = 'CONTAINS ${}'.format(n) s = str(p) self.assertEqual(exp, s) self.assertEqual(1, len(p.bound_params))
def delete_relationship(self, entity): _id = VM.get_next(entity, 'id') _id = Param(_id, entity.id) match = __.node() match.rel(entity.query_variable, labels=entity.labels) match.node() match.WHERE(__.ID(entity.query_variable) == _id) self.matches.append(match) self.deletes.append(entity.query_variable) return self
def test_can_bind_param_object_to_pypher(self): n = 'some name' v = 'value {}'.format(random()) v = Param(n, v) p = Pypher() param = p.bind_param(v) str(p) params = p.bound_params self.assertNotEqual(id(v), id(param)) self.assertIn(v.value, params.values()) self.assertIn(n, params) self.assertEqual(1, len(params))
def delete_by_entity_id(self, *ids): if not ids: msg = 'There must be ids passed in to the delete method' raise AttributeError(msg) def _build_start(): pypher = Pypher() if self.start_entity.id is not None: qv = self.start_entity.query_variable where = __.ID(qv) == self.start_entity.id pypher.NODE(qv) self.wheres.append(where) else: pypher.NODE(self.start_query_variable) return pypher self.pypher = Pypher() self.matches.insert(0, self._build_end()) self.matches.insert(0, self._build_relationship()) self.matches.insert(0, _build_start()) self.pypher.MATCH for match in self.matches: self.pypher.append(match) id_params = [] for i in ids: key = 'end_id_{}'.format(i) id_params.append(Param(key, i)) self.wheres.append(__.ID(self.end_query_variable).IN(*id_params)) _id = __.ID(self.start_query_variable) if self.start_entity.id is not None: self.wheres.append(_id == self.start_entity.id) # else: # wheres.append(_id) self.pypher.WHERE.CAND(*self.wheres) self.pypher.DELETE(self.relationship_query_variable) self.reset() return str(self.pypher), self.pypher.bound_params
def _properties(self, entity, unique_only=False): props = {} mapper = get_mapper(entity) properties = mapper.entity_data(entity.data, unique_only=unique_only, data_type='graph') for field, value in properties.items(): name = VM.get_next(entity, field) param = Param(name=name, value=value) self.pypher.bind_param(param) props[field] = param return props
def test_can_bind_nonunique_mixed_primitive_and_param_object_to_pypher(self): n = 'some name' v = 'value {}'.format(random()) v2 = v v = Param(n, v) p = Pypher() param = p.bind_param(v) param2 = p.bind_param(v2) str(p) params = p.bound_params self.assertNotEqual(id(v), id(param)) self.assertIn(v.value, params.values()) self.assertIn(n, params) self.assertEqual(1, len(params)) self.assertEqual(param.name, param2.name)
def test_will_allow_binding_of_pypher_instances_as_values(self): p = Pypher() p.bind_param(__.ID('x'), 'SOME_ID') str(p) params = p.bound_params self.assertIn('SOME_ID', params) self.assertEqual('id(x)', params['SOME_ID']) self.assertEqual(1, len(params)) # do it in a Pypher string p = Pypher() val = 'some value {}'.format(random()) name = 'name' p.MATCH.node('p', 'person', lastname=__.coalesce(name, val)) cy = str(p) params = p.bound_params name = get_dict_key(params, 'name') val = get_dict_key(params, val) exp = 'MATCH (p:`person` {{`lastname`: coalesce(${name}, ${val})}})'.format( name=name, val=val) self.assertEqual(3, len(params)) self.assertEqual(exp, cy) # manually use Param and pass it in p = Pypher() val = 'some value {}'.format(random()) name = 'name' ln = Param(name, __.coalesce(name, val)) p.MATCH.node('p', 'person', lastname=ln) cy = str(p) params = p.bound_params name = get_dict_key(params, 'name') val = get_dict_key(params, val) exp = 'MATCH (p:`person` {{`lastname`: coalesce(${name}, ${val})}})'.format( name=name, val=val) self.assertEqual(3, len(params)) self.assertEqual(exp, cy)
def get_by_ids(self, entity, ids): p = Pypher() p.MATCH if isinstance(entity, Relationship): var = 'rel' p.node().rel(var, labels=entity.labels).node() else: var = 'node' p.node(var, labels=entity.labels) id_params = [] for i in ids: key = 'entity_id_{}'.format(i) id_params.append(Param(key, i)) p.WHERE.COR(__.ID(var).IN(*id_params)) p.RETURN(var) return str(p), p.bound_params
def get_detailed_bundle_info_query(bundle_name, aspect=None): """ :param bundle_name: retrieve specific information for this bundle. :param aspect: should be 'bundles', 'imports', 'Exports', 'packages','components','compilationUnit','Methods'. :return: the query for (general or specific) information about one bundle. """ if aspect is None: return GenerateQuery.get_node_information_query( bundle_name, 'bundles') pypher_object = Pypher() if aspect == 'compilationUnit': pypher_object.Match.node('u', labels='bundles').relationship('f', labels="Pkg_fragment").node('n')\ .relationship('c', labels="compiled_By").node("m") elif aspect == 'methods': pypher_object.Match.node('u', labels='bundles').relationship('pkg', labels="Pkg_fragment").node('k')\ .relationship('kl', labels='compiled_By').node('n')\ .relationship('r', labels='compiledUnits_topLevelType').node('nl')\ .relationship('rl', labels='Methods_Contains').node('m') else: if aspect == 'packages': labels = 'uses_pkgs' elif aspect == 'components': labels = 'uses_components' else: labels = aspect pypher_object.Match.node('u', labels='bundles').relationship( 'r', labels=labels).node('m') pypher_object.Match.node('u').where.u.__name__.CONTAINS( Param('per_param', bundle_name)) # this can be changed according to req. if we need all info or just names of packages # query = str(self.pypherObject.RETURN('u.name', 'm.name')) pypher_object.RETURN('u.name', 'm.name') return GenerateQuery.reformat_query(pypher_object)
def get_simple_query(self): extracted_intent = self.tracker.latest_message['intent']['name'] if len(self.tracker.latest_message['entities']) > 0: extracted_value = self.tracker.latest_message['entities'][0][ 'value'] extracted_entities = { self.tracker.latest_message['entities'][index]['entity']: self.tracker.latest_message['entities'][index]['value'] for index in range(len( self.tracker.latest_message['entities'])) } else: extracted_entities = self.tracker.slots if len(extracted_entities) <= 0: return [] if extracted_intent == 'showNodeInformation': if extracted_entities['node'] is None: return [] self.pypher_object.Match.node('u').where.u.__name__.CONTAINS( Param('per_param', extracted_entities['node'])) self.pypher_object.RETURN('u') elif extracted_intent == 'showAllNodes': self.pypher_object.Match.node( 'u', labels=self.get_key_with_none_empty_value(extracted_entities)) self.pypher_object.RETURN('u') elif extracted_intent == 'countAllNodes': self.pypher_object.Match.node( 'u', labels=self.get_key_with_none_empty_value(extracted_entities)) self.pypher_object.RETURN(__.count('u')) elif extracted_intent == 'showLargestCompilationUnit': if self.tracker.get_slot('Methods') is not None: self.pypher_object.Match.node('bundle', labels='bundles').relationship \ ('pkg', labels="Pkg_fragment").node('k').relationship \ ('kl', labels='compiled_By').node().relationship \ ('cp', labels="compiledUnits_topLevelType").node('n').relationship \ ('rl', 'Methods_Contains').node('mthd') self.pypher_object.RETURN('bundle.name', 'n.name', __.count('mthd')) self.pypher_object.OrderBy(__.count('mthd')) else: self.pypher_object.Match.node('bundle', labels='bundles').relationship \ ('pkg', labels="Pkg_fragment").node('k').relationship \ ('kl', labels='compiled_By').node('cmp') if self.tracker.get_slot('bundles') is not None: self.pypher_object.WHERE( __.bundle.__name__ == self.tracker.get_slot('bundles')) self.pypher_object.RETURN('bundle.name', 'cmp.name', 'cmp.Loc') self.pypher_object.OrderBy(__.cmp.__Loc__) self.pypher_object.Desc() self.pypher_object.Limit(1) elif extracted_intent == 'showDetailInfoBundles': bundle_name = None key_value = None # iterate through all entities for key, value in self.tracker.slots.items(): # key_value is assigned according to relation names if key == 'bundles': bundle_name = value elif key == 'imports' or key == 'Exports': key_value = value elif key == 'packages': key_value = 'uses_pkgs' elif key == 'components': key_value = 'uses_components' elif key == 'compilationUnit': key_value = 'compiled_By' elif key == 'Methods': key_value = 'Methods_Contains' # this is relation name if key_value == 'compiled_By': self.pypher_object.Match.node('u', labels='bundles').relationship \ ('f', labels="Pkg_fragment").node('n').relationship \ ('c', labels="compiled_By").node("m") elif key_value == 'Methods_Contains': self.pypher_object.Match.node('u', labels='bundles').relationship \ ('pkg', labels="Pkg_fragment").node('k').relationship \ ('kl', labels='compiled_By').node('n').relationship \ ('r', labels='compiledUnits_topLevelType').node('nl').relationship \ ('rl', labels='Methods_Contains').node('m') else: self.pypher_object.Match.node('u', labels='bundles').relationship \ ('r', labels=key_value).node('m') self.pypher_object.WHERE(__.u.__name__ == bundle_name) # this can be changed according to req. if we need all info or just names of packages # query = str(self.pypherObject.RETURN('u.name', 'm.name')) self.pypher_object.RETURN('u.name', 'm.name') elif self.extracted_intents == 'showProjectInformation': self.pypher_object.Match.node('u') self.pypher_object.WHERE( __.u.__name__ == self.tracker.get_slot('bundles')) self.pypher_object.RETURN('u') else: if extracted_value is not None: self.pypher_object.Match.node( 'u', labels=extracted_entities).WHERE.u.property( 'name') == extracted_value self.pypher_object.RETURN('u') query = str(self.pypher_object) params = self.pypher_object.bound_params return [query, params, extracted_intent]
def save_relationship(self, entity, ensure_unique=False): """this method handles creating and saving relationships. It will hanle quite a few situations. Given the structure: (start)-[rel]->[end] We can have: * A new start node * An existing start node * A new rel * An existing rel * A new end node * An existing end node Each start, rel, and end could have uniqueness assigned to it * start/end could have unique properties * rel could have unique relationships A Chyper query should be generated that looks something like this, depending on the settings for each of the nodes: MERGE (n_0:Node {`key`: val}) ON CREATE SET n_0.key = val, n_0.key2 = val2 ON MATCH SET n_0.key = val, n_0.key2 = val2 CREATE (n_0)-[r_0:RelLabel, {`key`: someVal}]->(n_1:Node {`key`: val}) RETURN n_0, n_1, r_0 """ start = entity.start start_properties = {} end = entity.end end_properties = {} props = self._properties(entity) if start is None or end is None: raise Exception('The relationship must have a start and end node') if not isinstance(start, Node): start = Node(id=start) if not isinstance(end, Node): end = Node(id=end) VM.set_query_var(start) VM.set_query_var(end) VM.set_query_var(entity) rel = Pypher() if start not in self.matched_entities: if start.id is not None: self._update_properties(start) self.matches.append(self._node_by_id(start)) else: start_properties = self._properties(start) self.matched_entities.append(start) self.returns.append(start.query_variable) if end not in self.matched_entities: if end.id is not None: self._update_properties(end) self.matches.append(self._node_by_id(end)) else: end_properties = self._properties(end) self.matched_entities.append(end) self.returns.append(end.query_variable) if entity.id is None: if start.id is not None: rel = rel.node(start.query_variable) else: start_query = Query(start, self.params) start_query.build_save_pypher() if len(start_query.creates): rel.append(*start_query.creates) elif len(start_query.merges): has_matches = len(self.matches) > 0 start_merge = Pypher() start_merge.MERGE(*start_query.merges) if start_query.on_create_sets: start_merge.OnCreateSet(*start_query.on_create_sets) if start_query.on_match_sets: start_merge.OnMatchSet(*start_query.on_match_sets) self.before_matches.append(start_merge) rel.node(start.query_variable) rel.rel(entity.query_variable, labels=entity.labels, direction='out', **props) if end.id is not None: rel.node(end.query_variable) else: end_query = Query(end, self.params) end_query.build_save_pypher() if len(end_query.creates): rel.append(*end_query.creates) elif len(end_query.merges): end_merge = Pypher().MERGE(*end_query.merges) if end_query.on_create_sets: end_merge.OnCreateSet(*end_query.on_create_sets) if end_query.on_match_sets: end_merge.OnMatchSet(*end_query.on_match_sets) self.before_matches.append(end_merge) rel.node(end.query_variable) if ensure_unique: self.merges.append(rel) else: self.creates.append(rel) else: _id = VM.get_next(entity, 'id') _id = Param(_id, entity.id) if start.id is not None: rel = rel.node(start.query_variable) else: start_query = Query(start, self.params) start_query.build_save_pypher() if len(start_query.creates): rel.append(*start_query.creates) elif len(start_query.merges): start_merge = Pypher().MERGE(*start_query.merges) if start_query.on_create_sets: start_merge.OnCreateSet(*start_query.on_create_sets) if start_query.on_match_sets: start_merge.OnMatchSet(*start_query.on_match_sets) if len(self.matches): self.matches[-1].append(start_merge) else: self.matches.append(start_merge) rel.node(start.query_variable) rel.rel(entity.query_variable, labels=entity.labels, direction='out') if end.id is not None: rel.node(end.query_variable) else: end_query = Query(end, self.params) end_query.build_save_pypher() if len(end_query.creates): rel.append(*end_query.creates) elif len(end_query.merges): end_merge = Pypher().MERGE(*end_query.merges) if end_query.on_create_sets: end_merge.OnCreateSet(*end_query.on_create_sets) if end_query.on_match_sets: end_merge.OnMatchSet(*end_query.on_match_sets) if len(self.matches): self.matches[-1].append(end_merge) else: self.matches.append(end_merge) rel.node(end.query_variable) rel.WHERE(__.ID(entity.query_variable) == _id) self._update_properties(entity) self.matches.append(rel) self.returns.append(entity.query_variable) return self
def bind_param(self, value, name=None): if not isinstance(value, Param): name = VM.get_next(self.entity, name) param = Param(name, value) return super(Builder, self).bind_param(value=Param, name=name)