def _to_filter_stmt(self, prefix: str = 'p', relative_to: str = None) -> Stmt: if isinstance(self.compare_value, Var): return Stmt( f'FILTER {relative_to}.{self.attribute} {self.operator} {self.compare_value._name}{self.compare_value.attribute_return}', {}) return Stmt( f'FILTER {relative_to}.{self.attribute} {self.operator} @{prefix} ', {prefix: self.compare_value})
def _to_select_stmt(self, prefix: str, relative_to: str, alias_to_result: Dict[str, Result]) -> Stmt: if self.field in (object, ): return Stmt(relative_to, {}, result=DOCUMENT_RESULT, aliases=self.aliases, alias_to_result=alias_to_result) return Stmt(f'''{relative_to}.{self.field}''', {}, result=VALUE_RESULT, alias_to_result=alias_to_result, aliases=self.aliases)
def _to_group_stmt(self, prefix: str, collected: str, alias_to_result: Dict[str, Result]) -> Stmt: if self.field in (object, ): return Stmt(collected, {}, result=ListResult(DOCUMENT_RESULT), alias_to_result=alias_to_result, aliases=self.aliases) if self.used_in_by: return Stmt(f'field_{self.field}', {}, result=VALUE_RESULT, alias_to_result=alias_to_result, aliases=self.aliases) return Stmt(f'''{collected}[*].{self.field}''', {}, result=ListResult(VALUE_RESULT), alias_to_result=alias_to_result, aliases=self.aliases)
def _to_select_stmt(self, prefix: str, relative_to: str, alias_to_result: Dict[str, Result]) -> Stmt: stmt = self.group._to_select_stmt(prefix, relative_to=relative_to, alias_to_result=alias_to_result) query_str, bind_vars = stmt.expand() alias_to_result.update(stmt.alias_to_result) return Stmt(f'''{self.func}({query_str})''', bind_vars, result=VALUE_RESULT, alias_to_result=alias_to_result)
def _get_traversal_stmt(self, prefix: str, relative_to: str = '', alias_to_result: Dict[str, Result] = None): if not alias_to_result: alias_to_result = {} result = self._get_result( AnyResult([e.document_type for e in self.edge_collections] ) if self.edge_collections else DOCUMENT_RESULT) step_stmts, bind_vars, bind_vars_index = self._get_step_stmts( relative_to=f'{prefix}_e', returns=f'{prefix}_e' + self.attribute_return, prefix=prefix) if self.outer_query: previous_stmt = self.outer_query._to_stmt( prefix=f'{prefix}_0', alias_to_result=alias_to_result) alias_to_result.update(previous_stmt.alias_to_result) previous_str, previous_vars = previous_stmt.expand_without_return() bind_vars.update(previous_vars) return Stmt(f''' {previous_str} FOR {prefix}_v, {prefix}_e IN {self.min_depth}..{self.max_depth} {self.direction} {previous_stmt.returns}._id {traversal_edge_collection_names(self.edge_collections)} {step_stmts} ''', bind_vars, returns=f'{prefix}_e' + self.attribute_return, result=result, aliases=self.aliases, alias_to_result=alias_to_result) return Stmt(f''' FOR {prefix}_v, {prefix}_e IN {self.min_depth}..{self.max_depth} {self.direction} {relative_to}._id {traversal_edge_collection_names(self.edge_collections)} {step_stmts} ''', bind_vars, returns=f'{prefix}_e' + self.attribute_return, result=result, aliases=self.aliases)
def _to_group_stmt(self, prefix: str, collected: str, alias_to_result: Dict[str, Result]) -> Stmt: stmt = self.group._to_group_stmt(prefix, collected=collected, alias_to_result=alias_to_result) query_str, bind_vars = stmt.expand() alias_to_result.update(stmt.alias_to_result) return Stmt(f'''{self.func}({query_str})''', bind_vars, result=VALUE_RESULT, aliases=self.aliases, alias_to_result=alias_to_result)
def _to_select_stmt(self, prefix: str, relative_to: str, alias_to_result: Dict[str, Result]) -> Stmt: returns = f'o_{prefix}' + self.attribute_return step_stmts, bind_vars, bind_vars_index = self._get_step_stmts( returns=returns, relative_to=f'o_{prefix}', prefix=prefix, bind_vars_index=1) if self.collection: return Stmt(f''' FOR o_{prefix} IN {self.collection.name} {step_stmts} ''', bind_vars, returns=f'o_{prefix}' + self.attribute_return, result=VALUE_RESULT if self.attribute_return else self.collection.document_type, aliases=self.aliases) if self.previous: previous_stmt = self.previous._to_stmt( prefix=f'{prefix}_0', alias_to_result=alias_to_result) alias_to_result.update(previous_stmt.alias_to_result) previous_str, previous_bind_vars = previous_stmt.expand() bind_vars.update(previous_bind_vars) return Stmt(f''' LET previous = ({previous_str}) FOR o_{prefix} IN previous {step_stmts} ''', bind_vars, returns=f'o_{prefix}{self.attribute_return}', result=VALUE_RESULT if self.attribute_return else self.collection.document_type, aliases=self.aliases) raise ValueError
def _to_stmt(self, prefix: str = 'p', alias_to_result: Dict[str, Result] = None) -> Stmt: if not alias_to_result: alias_to_result = {} returns = f'o_{prefix}' + self.attribute_return step_stmts, bind_vars, bind_vars_index = self._get_step_stmts( returns=returns, relative_to=f'o_{prefix}', prefix=prefix, bind_vars_index=1) if self.collection: return Stmt(f''' FOR o_{prefix} IN {self.collection.name} {step_stmts} ''', bind_vars, returns=returns, result=self._get_result(self.collection.document_type), aliases=self.aliases, alias_to_result=alias_to_result) if self.previous: previous_stmt = self.previous._to_stmt( prefix=f'{prefix}_0', alias_to_result=alias_to_result) alias_to_result.update(previous_stmt.alias_to_result) previous_str, previous_bind_vars = previous_stmt.expand() return Stmt(f''' LET previous = ({previous_str}) FOR o_{prefix} IN previous {step_stmts} ''', bind_vars, returns=returns, result=self._get_result(self.collection.document_type), aliases=self.aliases) raise ValueError
def set(self, from_: Union[Query, Document], edge_document: Union[Type, TEdge], to_: Union[Query, Document], data: Dict[str, Any] = None): if isinstance(from_, Document) and isinstance(to_, Document): return self._set_from_objects(from_, to_, edge_document, data) self._ensure_edge_collection(edge_document._get_collection()) bind_vars = {} from_stmt = from_._to_stmt( prefix='from_p') if isinstance(from_, Query) else Stmt( f'[{{_id: @from_id}}]', bind_vars={'from_id': from_._id}) from_str, from_bind_vars = from_stmt.expand() bind_vars.update(from_bind_vars) to_stmt = to_._to_stmt( prefix='to_p') if isinstance(to_, Query) else Stmt( f'[{{_id: @to_id}}]', bind_vars={'to_id': to_._id}) to_str, to_bind_vars = to_stmt.expand() bind_vars.update(to_bind_vars) if isclass(edge_document): dict_doc = Document._dump_from_dict(data, Document.INIT_PROPERTIES) else: dict_doc = edge_document._dump() for key, value in dict_doc.items(): bind_vars[f'edge_{key}'] = value statement = f''' LET from_entities = ({from_str}) LET to_entities = ({to_str}) FOR from_entity IN from_entities FOR to_entity IN to_entities insert {{_from: from_entity._id, _to: to_entity._id{',' if len(dict_doc) > 0 else ''} {', '.join([f'{key}: @edge_{key}' for key in dict_doc.keys()])}}} INTO {edge_document._get_collection().name} ''' self.db.aql.execute(statement, bind_vars=bind_vars)
def _to_stmt(self, prefix: str = 'p', alias_to_result: Dict[str, Result] = None) -> Stmt: if not alias_to_result: alias_to_result = {} stmt = self.query._to_stmt(prefix=f'{prefix}_0', alias_to_result=alias_to_result) alias_to_result.update(stmt.alias_to_result) previous, bind_vars = stmt.expand_without_return() bind_vars_index = 1 groups_stmt = [] result = {} for display_field, group_field in self.display_field_to_grouped.items( ): if isinstance(group_field, Field) and group_field.field in self.by_fields: group_field.used_in_by = True group_stmt = group_field._to_select_stmt( prefix=f'{prefix}_{bind_vars_index}', relative_to=stmt.returns, alias_to_result=alias_to_result) alias_to_result.update(group_stmt.alias_to_result) group_str, b_vars = group_stmt.expand() result[display_field] = group_stmt.result field_bind = f'{prefix}_{bind_vars_index + 1}' groups_stmt.append(f'@{field_bind}: ({group_str})') bind_vars[field_bind] = display_field bind_vars.update(b_vars) bind_vars_index += 2 return Stmt(f''' {previous} RETURN {{ {f',{DELIMITER}'.join(groups_stmt)} }} ''', bind_vars, result=self._get_result(DictResult(result)), aliases=self.aliases, alias_to_result=alias_to_result)
def _to_stmt(self, prefix: str = 'p', alias_to_result: Dict[str, Result] = None) -> Stmt: if not alias_to_result: alias_to_result = {} returns = f'array_{prefix}' step_stmts, bind_vars, bind_vars_index = self._get_step_stmts( relative_to=returns, returns=f'array_{prefix}' + self.attribute_return, prefix=prefix, bind_vars_index=1) self.inner_query.outer_query_returns = f'oqr_{prefix}' outer_stmt = self.outer_query._to_stmt(f'{prefix}_0', alias_to_result=alias_to_result) alias_to_result.update(outer_stmt.alias_to_result) outer_str, outer_bind_vars = outer_stmt.expand_without_return() bind_vars.update(outer_bind_vars) inner_stmt = self.inner_query._to_stmt(f'{prefix}_1', alias_to_result=alias_to_result) alias_to_result.update(inner_stmt.alias_to_result) inner_str, inner_bind_vars = inner_stmt.expand() bind_vars.update(inner_bind_vars) return Stmt(f''' {outer_str} LET oqr_{prefix} = {outer_stmt.returns} LET {returns} = ( {inner_str} ) {step_stmts} ''', bind_vars=bind_vars, returns=returns + self.attribute_return, alias_to_result=alias_to_result, aliases=self.aliases, result=self._get_result(ListResult(inner_stmt.result)))
def _to_filter_stmt(self, prefix: str = 'p', relative_to: str = None) -> Stmt: relative_to = relative_to[:-1] + 'v' if relative_to.endswith( 'e') else relative_to returns = f'{prefix}_v' if self.outer_query: edge_query = self.outer_query filter_target_collection = f'''FILTER {" OR ".join([f"IS_SAME_COLLECTION('{t.name}', {returns})" for t in self.target_collections])}''' if self.target_collections else '' previous_str = '' if self.outer_query.outer_query: filter_target_collection = f'''FILTER {" OR ".join([f"IS_SAME_COLLECTION('{t.name}', {relative_to})" for t in self.target_collections])}''' if self.target_collections else '' step_stmts, bind_vars, bind_vars_index = self._get_step_stmts( relative_to=relative_to, returns=returns + self.attribute_return, prefix=prefix, bind_vars_index=0) previous_stmt = self.outer_query.outer_query._to_stmt( f'{prefix}_0') previous_str, previous_bind_vars = previous_stmt.expand_without_return( ) bind_vars.update(previous_bind_vars) relative_to = previous_stmt.returns else: step_stmts, bind_vars, bind_vars_index = self._get_step_stmts( relative_to=returns, returns=returns + self.attribute_return, prefix=prefix, bind_vars_index=0) outer_query_step_stmts, bind_vars, bind_vars_index = self.outer_query._get_step_stmts( relative_to=f'{prefix}_e', bind_vars=bind_vars, bind_vars_index=bind_vars_index, prefix=f'{prefix}', returns=f'{prefix}_e' + self.outer_query.attribute_return) return Stmt( f''' LET {prefix}_sub = ( {previous_str} FOR {prefix}_v, {prefix}_e IN {self.outer_query.min_depth}..{self.outer_query.max_depth} {edge_query.direction} {relative_to}._id {",".join([e.name for e in edge_query.edge_collections]) if edge_query.edge_collections else ""} {filter_target_collection} {step_stmts} {outer_query_step_stmts} RETURN 1 ) FILTER LENGTH({prefix}_sub) > 0 ''', bind_vars) filter_target_collection = f'''FILTER {" OR ".join([f"IS_SAME_COLLECTION('{t.name}', {relative_to})" for t in self.target_collections])}''' if self.target_collections else '' step_stmts, bind_vars, bind_vars_index = self._get_step_stmts( relative_to=relative_to, returns=returns + self.attribute_return, prefix=prefix, bind_vars_index=0) return Stmt( f''' LET {prefix}_sub = ( {filter_target_collection} {step_stmts} RETURN 1 ) FILTER LENGTH({prefix}_sub) > 0 ''', bind_vars)
def _get_traversal_stmt(self, prefix: str, relative_to: str, alias_to_result: Dict[str, Result] = None): if self.outer_query_returns: relative_to = self.outer_query_returns if not alias_to_result: alias_to_result = {} returns = f'{prefix}_v' result = self._get_result( AnyResult([t.document_type for t in self.target_collections]) if len(self.target_collections) > 0 else DOCUMENT_RESULT) step_stmts, bind_vars, bind_vars_index = self._get_step_stmts( relative_to=returns, returns=returns + self.attribute_return, prefix=prefix, bind_vars_index=1) filter_target_collection = f'''FILTER {" OR ".join([f"IS_SAME_COLLECTION('{t.name}', {returns})" for t in self.target_collections])}''' if self.target_collections else '' if self.outer_query: edge_query = self.outer_query previous_str = '' outer_query_step_stmts, bind_vars, bind_vars_index = self.outer_query._get_step_stmts( relative_to=f'{prefix}_e', bind_vars=bind_vars, bind_vars_index=bind_vars_index, prefix=f'{prefix}', returns=f'{prefix}_e' + self.outer_query.attribute_return) if self.outer_query.outer_query: previous_stmt = self.outer_query.outer_query._to_stmt( f'{prefix}_0', alias_to_result=alias_to_result) alias_to_result.update(previous_stmt.alias_to_result) previous_str, previous_bind_vars = previous_stmt.expand_without_return( ) bind_vars.update(previous_bind_vars) relative_to = previous_stmt.returns return Stmt(f''' {previous_str} FOR {prefix}_v, {prefix}_e IN {self.outer_query.min_depth}..{self.outer_query.max_depth} {edge_query.direction} {relative_to}._id {",".join([e.name for e in edge_query.edge_collections]) if edge_query.edge_collections else ""} {filter_target_collection} {step_stmts} {outer_query_step_stmts} ''', bind_vars, alias_to_result=alias_to_result, returns=returns + self.attribute_return, result=result, aliases=self.aliases) return Stmt(f''' {filter_target_collection} {step_stmts} ''', bind_vars, alias_to_result=alias_to_result, result=result, returns=returns + self.attribute_return, aliases=self.aliases)
def _to_stmt(self, prefix: str = 'p', alias_to_result: Dict[str, Result] = None) -> Stmt: if not alias_to_result: alias_to_result = {} if len(self.by_fields) == 0: self.by_fields = ['_key'] stmt = self.query._to_stmt(f'{prefix}_0', alias_to_result) alias_to_result.update(stmt.alias_to_result) previous, bind_vars = stmt.expand_without_return() previous_result = stmt.returns by_fields_stmt = [] for by_field in self.by_fields: if isinstance(by_field, str): by_fields_stmt.append( f'field_{by_field} = {previous_result}.{by_field}') elif isinstance(by_field, Var): by_fields_stmt.append( f'field_{by_field._name} = {by_field.attribute_return}') else: raise TypeError bind_vars_index = 1 groups_stmt = [] result = {} for display_field, group_field in self.display_field_to_grouped.items( ): print(display_field, group_field) if isinstance(group_field, Field) and group_field.field in self.by_fields: group_field.used_in_by = True group_stmt = group_field._to_group_stmt( prefix=f'{prefix}_{bind_vars_index}', collected='groups', alias_to_result=alias_to_result) alias_to_result.update(alias_to_result) group_str, b_vars = group_stmt.expand() result[display_field] = group_stmt.result field_bind = f'{prefix}_{bind_vars_index + 1}' groups_stmt.append(f'@{field_bind}: ({group_str})') bind_vars[field_bind] = display_field bind_vars.update(b_vars) bind_vars_index += 2 return Stmt(f''' {previous} COLLECT {', '.join(by_fields_stmt)} INTO groups = {previous_result} RETURN {{ {f',{DELIMITER}'.join(groups_stmt)} }} ''', bind_vars, result=self._get_result(DictResult(result)), aliases=self.aliases)
def _to_select_stmt(self, prefix: str, alias_to_result: Dict[str, Result], relative_to: str = '') -> Stmt: return Stmt(f'''{self._name}{self.attribute_return}''', {}, result=self._get_result(alias_to_result[self._name]))
def _to_group_stmt(self, prefix: str, alias_to_result: Dict[str, Result], collected: str = 'groups') -> Stmt: return Stmt(f'''{self._name}{self.attribute_return}''', {}, result=self._get_result(alias_to_result[self._name]))