def _join_inverse_relation(self, relation_name: str, attributes: list, arguments: dict): parent = self.relation_parents[relation_name] parent_info = self._get_relation_info(parent) relation_name_snake = to_snake(relation_name).split('_') assert relation_name_snake[0] == 'inv' relation_attr_name = '_'.join(relation_name_snake[1:-2]) dst_catalog_name = relation_name_snake[-2] dst_collection_name = relation_name_snake[-1] dst_model_name = self.model.get_table_name(dst_catalog_name, dst_collection_name) dst_info = self._collect_relation_info(relation_name, f'{dst_model_name}') json_attrs = self._json_build_attrs(attributes, dst_info['alias']) json_attrs = f"{json_attrs}, '_catalog', '{dst_catalog_name}', '_collection', '{dst_collection_name}'" alias = f"_inv_{relation_attr_name}_{dst_info['catalog_name']}_{dst_info['collection_name']}" relation_name = get_relation_name( self.model, dst_info['catalog_name'], dst_info['collection_name'], relation_attr_name ) self._add_relation_joins(parent_info, dst_info, relation_name, arguments, is_inverse=True) self.select_expressions.append(f"json_build_object({json_attrs}) {alias}")
def _join_relation(self, relation_name: str, attributes: list, arguments: dict): parent = self.relation_parents[relation_name] parent_info = self._get_relation_info(parent) relation_attr_name = to_snake(self.relation_aliases[relation_name]) dst_catalog_name, dst_collection_name = self.model.get_catalog_collection_names_from_ref( parent_info['collection']['attributes'][relation_attr_name]['ref'] ) dst_info = self._collect_relation_info(relation_name, f'{dst_catalog_name}_{dst_collection_name}') alias = f"_{to_snake(relation_name)}" json_attrs = self._json_build_attrs(attributes, dst_info['alias']) json_attrs = f"{json_attrs}, '_catalog', '{dst_catalog_name}', '_collection', '{dst_collection_name}'" relation_name = get_relation_name( self.model, parent_info['catalog_name'], parent_info['collection_name'], relation_attr_name ) self._add_relation_joins(parent_info, dst_info, relation_name, arguments, self._is_srcvalue_requested(attributes), relation_attr_name, self._is_many(parent_info['collection']['attributes'][relation_attr_name]['type'])) self.select_expressions.append(f"json_build_object({json_attrs}) {alias}")
def _validate_attribute(self, relation_info: dict, attribute: str, relation_name: str): if to_snake(attribute) not in list(relation_info['all_fields']) + [ FIELD.SOURCE_VALUE, FIELD.SOURCE_INFO, API_FIELD.START_VALIDITY_RELATION, API_FIELD.END_VALIDITY_RELATION ]: raise InvalidQueryException( f"Attribute {attribute} does not exist for {relation_name}")
def _select_expression(self, relation: dict, field: str): if field == self.CURSOR_ID: return f"{relation['alias']}.{FIELD.GOBID} AS {self.CURSOR_ID}" field_snake = to_snake(field) expression = f"{relation['alias']}.{field_snake}" # If geometry field, transform to WKT if field_snake in relation['attributes'] and is_gob_geo_type(relation['attributes'][field_snake]['type']): return f"ST_AsText({expression}) {field_snake}" return expression
def resolve_schema_collection_name(schema_collection_name: str): """ Resolve catalog and collection from schema collection name :param schema_collection_name: :return: """ model = GOBModel() names = to_snake(schema_collection_name).split('_') for n in range(1, len(names)): catalog_name = '_'.join(names[:-n]) collection_name = '_'.join(names[-n:]) catalog = model.get_catalog(catalog_name) collection = model.get_collection(catalog_name, collection_name) if catalog and collection: return catalog_name, collection_name return None, None
def _json_build_attrs(self, attributes: list, relation_name: str): """Create the list of attributes to be used in json_build_object( ) for attributes in relation_name :param attributes: :param relation_name: :return: """ snake_attrs = [to_snake(attr) for attr in attributes] json_attrs = ",".join([f"'{attr}', {relation_name}.{attr}" for attr in snake_attrs if attr not in self.srcvalues_attributes + self.relvalues_attributes]) if self._is_relvalue_requested(attributes): rel_attrs = ",".join([f"'{attr}', rel_{self.relcnt}.{attr.replace('_relatie', '')}" for attr in snake_attrs if attr in self.relvalues_attributes]) json_attrs = f"{json_attrs}, {rel_attrs}" return json_attrs
def _get_filter_arguments(self, arguments: dict) -> dict: """Returns filter arguments from arguments dict Changes GraphQL strings with double quotes to single quotes for Postgres :param arguments: :return: """ ignore = ['first', 'last', 'before', 'after', 'sort', 'active'] def change_quotation(value): strval = str(value) double_quote = '"' if strval[0] == double_quote and strval[-1] == double_quote: return "'" + strval[1:-1] + "'" return value return {to_snake(k): change_quotation(v) for k, v in arguments.items() if k not in ignore and not k.endswith('_desc') and not k.endswith('_asc') }
def test_to_snake(): assert (to_snake("") == "") assert (to_snake("a") == "a") assert (to_snake("A") == "_a") assert (to_snake("ABC") == "_a_b_c") assert (to_snake("firstSecond") == "first_second")
def _is_relvalue_requested(self, attributes: list): return any([to_snake(attr) in self.relvalues_attributes for attr in attributes])