Exemplo n.º 1
0
    def join(self, target_table: Table, query: Query) -> Query:
        if target_table == Table.metaproteomic_analysis:
            return query.join(
                models.MetaPGeneFunctionAggregation,
                models.MetaPGeneFunctionAggregation.metaproteomic_analysis_id
                == models.MetaproteomicAnalysis.id,
            ).join(
                MetaPGeneFunction,
                MetaPGeneFunction.id ==
                models.MetaPGeneFunctionAggregation.gene_function_id,
            )

        query = super().join(target_table, query)
        return (query.join(
            models.MetaproteomicAnalysis,
            models.MetaproteomicAnalysis.omics_processing_id ==
            models.OmicsProcessing.id,
        ).join(
            models.MetaPGeneFunctionAggregation,
            models.MetaPGeneFunctionAggregation.metaproteomic_analysis_id ==
            models.MetaproteomicAnalysis.id,
        ).join(
            MetaPGeneFunction,
            MetaPGeneFunction.id ==
            models.MetaPGeneFunctionAggregation.gene_function_id,
        ))
Exemplo n.º 2
0
    def join(self, target_table: Table, query: Query) -> Query:
        if target_table == Table.metagenome_annotation:
            return query.join(
                models.MGAGeneFunctionAggregation,
                models.MGAGeneFunctionAggregation.metagenome_annotation_id ==
                models.MetagenomeAnnotation.id,
            ).join(
                models.GeneFunction,
                models.GeneFunction.id ==
                models.MGAGeneFunctionAggregation.gene_function_id,
            )

        query = super().join(target_table, query)
        return (query.join(
            models.MetagenomeAnnotation,
            models.MetagenomeAnnotation.omics_processing_id ==
            models.OmicsProcessing.id,
        ).join(
            models.MGAGeneFunctionAggregation,
            models.MGAGeneFunctionAggregation.metagenome_annotation_id ==
            models.MetagenomeAnnotation.id,
        ).join(
            models.GeneFunction,
            models.GeneFunction.id ==
            models.MGAGeneFunctionAggregation.gene_function_id,
        ))
Exemplo n.º 3
0
    def join_envo(self, table: Table, query: Query) -> Query:
        """Join with an envo table.

        Assumes the query is already joined with the biosample table.
        """
        if table == Table.env_broad_scale:
            return query.join(
                EnvBroadScaleAncestor,
                models.Biosample.env_broad_scale_id ==
                EnvBroadScaleAncestor.id,
            ).join(
                EnvBroadScaleTerm,
                EnvBroadScaleAncestor.ancestor_id == EnvBroadScaleTerm.id,
            )
        if table == Table.env_local_scale:
            return query.join(
                EnvLocalScaleAncestor,
                models.Biosample.env_local_scale_id ==
                EnvLocalScaleAncestor.id,
            ).join(
                EnvLocalScaleTerm,
                EnvLocalScaleAncestor.ancestor_id == EnvLocalScaleTerm.id,
            )
        if table == Table.env_medium:
            return query.join(
                EnvMediumAncestor,
                models.Biosample.env_medium_id == EnvMediumAncestor.id,
            ).join(
                EnvMediumTerm,
                EnvMediumAncestor.ancestor_id == EnvMediumTerm.id,
            )
        return query
Exemplo n.º 4
0
 def join_biosample(self, query: Query) -> Query:
     return self.join_self(
         query.join(
             models.OmicsProcessing,
             models.Biosample.id == models.OmicsProcessing.biosample_id),
         Table.omics_processing,
     )
Exemplo n.º 5
0
 def __apply_filters_to_query(self, query: Query,
                              filters: Union[Dict[str, List[str]]]):
     query = query.join(MetaORM)
     for key, values in filters.items():
         query = query.filter(MetaORM.name == key,
                              MetaORM.value.in_(values))
     return query
Exemplo n.º 6
0
 def create_multi_join_view(cls, db, view_name, selectable, joins,
                            order_by):
     with db.managed_session() as session:
         query = Query(selectable, session=session)
         for (join_table, join_clause) in joins:
             query = query.join(join_table, join_clause)
         query = query.order_by(order_by)
         cls.__create_view_if_not_exists(session, view_name, str(query))
Exemplo n.º 7
0
 def _filter_storages(self, ctx: RunContext, sess: Session,
                      query: Query) -> Query:
     if not self.storages:
         return query
     return query.join(StoredDataBlockMetadata).filter(
         StoredDataBlockMetadata.storage_url.in_(
             [s.url for s in self.storages])  # type: ignore
     )
Exemplo n.º 8
0
    def data_layer_get_object_update_query(self,
                                           *args,
                                           query: Query = None,
                                           qs: QueryStringManager = None,
                                           view_kwargs=None,
                                           self_json_api=None,
                                           **kwargs) -> Query:
        """
        Во время создания запроса к БД на выгрузку объекта. Тут можно пропатчить запрос к БД.
        Навешиваем ограничения на запрос, чтобы не тянулись поля из БД, которые данному
        пользователю не доступны. Также навешиваем фильтры, чтобы пользователь не смог увидеть
        записи, которые ему не доступны
        :param args:
        :param Query query: Сформированный запрос к БД
        :param QueryStringManager qs: список параметров для запроса
        :param view_kwargs: список фильтров для запроса
        :param self_json_api:
        :param kwargs:
        :return: возвращает пропатченный запрос к бд
        """
        permission: PermissionUser = self._get_permission_user(view_kwargs)
        permission_for_get: PermissionForGet = permission.permission_for_get(
            self_json_api.model)

        # Навешиваем фильтры (например пользователь не должен видеть некоторые поля)
        for i_join in permission_for_get.joins:
            query = query.join(*i_join)
        query = query.filter(*permission_for_get.filters)

        # Навешиваем ограничения по атрибутам (которые доступны & которые запросил пользователь)
        name_columns = permission_for_get.columns
        if qs:
            user_requested_columns = qs.fields.get(
                self_json_api.resource.schema.Meta.type_)
            if user_requested_columns:
                name_columns = list(
                    set(name_columns) & set(user_requested_columns))
        # Убираем relationship поля
        name_columns = [
            i_name for i_name in name_columns
            if i_name in self_json_api.model.__table__.columns.keys()
        ]
        required_columns_names = []
        for i_name in name_columns:
            required_columns_names.extend(
                get_required_fields(i_name, self_json_api.model))
        name_columns = list(set(name_columns) | set(required_columns_names))

        query = query.options(load_only(*name_columns))
        if qs:
            query = self._eagerload_includes(query,
                                             qs,
                                             permission,
                                             self_json_api=self_json_api)

        # Запретим использовать стандартную функцию eagerload_includes для присоединения сторонних молелей
        self_json_api.eagerload_includes = lambda x, y: x
        return query
Exemplo n.º 9
0
    def _inject_omics_data_summary(self, db: Session, query: Query) -> Query:
        aggs = []
        for omics_class in workflow_search_classes:
            pipeline_model = omics_class().table.model
            table_name = pipeline_model.__tablename__  # type: ignore
            filter_conditions = [
                c for c in self.conditions if c.table.value in
                {"omics_processing", table_name, "biosample"}
            ]

            query_schema = omics_class(conditions=filter_conditions)
            omics_subquery = self._count_omics_data_query(
                db, query_schema).subquery()
            study_id = getattr(omics_subquery.c, f"{table_name}_study_id")
            query = query.join(
                omics_subquery,
                self.table.model.id == study_id,  # type: ignore
                isouter=True,
            )
            aggs.append(
                func.json_build_object(
                    "type", table_name, "count",
                    getattr(omics_subquery.c, f"{table_name}_count")))

        op_filter_conditions = [
            c for c in self.conditions
            if c.table.value in {"omics_processing", "biosample"}
        ]
        op_summary_subquery = self._count_omics_processing_summary(
            db, op_filter_conditions).subquery()
        query = query.join(
            op_summary_subquery,
            op_summary_subquery.c.omics_processing_study_id == models.Study.id,
            isouter=True,
        )

        aggregation = func.json_build_array(*aggs)
        return query.populate_existing().options(
            with_expression(models.Study.omics_counts, aggregation),
            with_expression(
                models.Study.omics_processing_counts,
                op_summary_subquery.c.omics_processing_summary,
            ),
        )
Exemplo n.º 10
0
def filter_role(db: Session, query: Query, zones: List[GeoZone], role: str):
    all_zones = [[zone.id] + [child.id for child in get_child(db, zone)]
                 for zone in zones]
    all_zones = [item for sublist in all_zones for item in sublist]

    if role == 'referent':
        return query.join(Adherents.managed_area) \
            .join(ReferentManagedAreasTags.referent_tag) \
            .join(ReferentTags.zone.and_(GeoZone.id.in_(all_zones)))

    if role in ['deputy', 'senator']:
        return query.join(AdherentMessages.filter) \
            .join(AdherentMessageFilters.referent_tag) \
            .join(ReferentTags.zone.and_(GeoZone.id.in_(all_zones)))

    if role == 'candidate':
        return query.join(AdherentMessages.filter) \
            .join(AdherentMessageFilters.zone.and_(GeoZone.id.in_(all_zones)))
    return query
Exemplo n.º 11
0
def restricted_incident_filter(query: orm.Query, current_user: DispatchUser):
    """Adds additional incident filters to query (usually for permissions)."""
    query = (query.join(
        Participant,
        Incident.id == Participant.incident_id).join(IndividualContact).filter(
            or_(
                Incident.visibility == Visibility.open.value,
                IndividualContact.email == current_user.email,
            )).distinct())
    return query
Exemplo n.º 12
0
    def data_layer_get_collection_update_query(self,
                                               *args,
                                               query: Query = None,
                                               qs: QueryStringManager = None,
                                               view_kwargs=None,
                                               self_json_api=None,
                                               **kwargs) -> Query:
        """
        Во время создания запроса к БД на выгрузку объектов. Тут можно пропатчить запрос к БД
        :param args:
        :param Query query: Сформированный запрос к БД
        :param QueryStringManager qs: список параметров для запроса
        :param view_kwargs: список фильтров для запроса
        :param self_json_api:
        :param kwargs:
        :return: возвращает пропатченный запрос к бд
        """
        permission: PermissionUser = self._get_permission_user(view_kwargs)
        permission_for_get: PermissionForGet = permission.permission_for_get(
            self_json_api.model)

        # Навешиваем фильтры (например пользователь не должен видеть некоторые поля)
        for i_join in permission_for_get.joins:
            query = query.join(*i_join)
        query = query.filter(*permission_for_get.filters)

        # Навешиваем ограничения по атрибутам (которые доступны & которые запросил пользователь)
        name_columns = permission_for_get.columns
        user_requested_columns = qs.fields.get(
            self_json_api.resource.schema.Meta.type_)
        if user_requested_columns:
            name_columns = list(
                set(name_columns) & set(user_requested_columns))

        # required fields (from Meta.required_fields)
        required_columns_names = []
        for i_name in name_columns:
            required_columns_names.extend(
                get_required_fields(i_name, self_json_api.model))

        # remove relationship fields
        name_columns = list(
            set(name_columns)
            & set(get_columns_for_query(self_json_api.model)))
        name_columns = list(set(name_columns) | set(required_columns_names))

        query = query.options(load_only(*name_columns))

        # Запретим использовать стандартную функцию eagerload_includes для присоединения сторонних молелей
        setattr(self_json_api, "eagerload_includes", False)
        query = self._eagerload_includes(query,
                                         qs,
                                         permission,
                                         self_json_api=self_json_api)
        return query
Exemplo n.º 13
0
    def _join_biosample_related_tables(self, target_table: Table,
                                       query: Query) -> Query:
        if target_table != Table.biosample:
            query = query.join(models.Biosample)

        query = self.join_biosample(query)
        if target_table == Table.biosample:
            return query
        if target_table in envo_tables:
            return self.join_envo(target_table, query)
        return query
Exemplo n.º 14
0
 def apply_joins(self, query: Query, joins: List[SqlJoin]) -> Query:
     """ Augment the sql alchemy query with joins from the analysis.
     """
     for join in joins:
         foreign_table = self.get_table(join.right)
         query = query.join(
             foreign_table,
             self.get_column(join.right) == self.get_column(join.left),
             isouter=True,
         )
     return query
Exemplo n.º 15
0
def _join_envo_facet(query: Query, attribute: str) -> Query:
    if attribute == "env_broad_scale":
        return query.join(
            EnvBroadScaleAncestor,
            EnvBroadScaleTerm.id == EnvBroadScaleAncestor.ancestor_id).join(
                models.Biosample, models.Biosample.env_broad_scale_id ==
                EnvBroadScaleAncestor.id)
    elif attribute == "env_local_scale":
        return query.join(
            EnvLocalScaleAncestor,
            EnvLocalScaleTerm.id == EnvLocalScaleAncestor.ancestor_id).join(
                models.Biosample, models.Biosample.env_local_scale_id ==
                EnvLocalScaleAncestor.id)
    elif attribute == "env_medium":
        return query.join(
            EnvMediumAncestor,
            EnvMediumTerm.id == EnvMediumAncestor.ancestor_id).join(
                models.Biosample,
                models.Biosample.env_medium_id == EnvMediumAncestor.id)
    else:
        raise Exception("Unknown envo attribute")
Exemplo n.º 16
0
def restricted_incident_filter(query: orm.Query, current_user: DispatchUser,
                               role: UserRoles):
    """Adds additional incident filters to query (usually for permissions)."""
    if role != UserRoles.owner:
        # We don't allow users that are not owners to see restricted incidents
        query = (query.join(
            Participant, Incident.id == Participant.incident_id).join(
                IndividualContact).filter(
                    or_(
                        Incident.visibility == Visibility.open,
                        IndividualContact.email == current_user.email,
                    )))
    return query.distinct()
Exemplo n.º 17
0
def restricted_incident_filter(query: orm.Query, current_user: DispatchUser,
                               role: UserRoles):
    """Adds additional incident filters to query (usually for permissions)."""
    if role == UserRoles.member:
        # We filter out resticted incidents for users with a member role if the user is not an incident participant
        query = (query.join(
            Participant, Incident.id == Participant.incident_id).join(
                IndividualContact).filter(
                    or_(
                        Incident.visibility == Visibility.open,
                        IndividualContact.email == current_user.email,
                    )))
    return query.distinct()
Exemplo n.º 18
0
    def query(self, base_query: Query, field_value: Any) -> Query:
        """
        Get the current field query

        Args:
            base_query: base query used for building the query
            field_value: value of the field filter

        Returns: field query

        """
        return base_query.join(getattr(New, self.new_join_field)).filter(
            getattr(self.destination_entity, self.destination_field) ==
            field_value)
Exemplo n.º 19
0
 def create_multi_join_view(cls,
                            db,
                            view_name,
                            selectable,
                            joins,
                            order_by=None):
     """Create a database view named view_name if it doesn't already exist."""
     with db.managed_session() as session:
         query = Query(selectable, session=session)
         for (join_table, join_clause) in joins:
             query = query.join(join_table, join_clause)
         if order_by is not None:
             query = query.order_by(order_by)
         cls.__create_view_if_not_exists(session, view_name, str(query))
Exemplo n.º 20
0
def restricted_incident_filter(query: orm.Query, current_user: DispatchUser):
    """Adds additional incident filters to query (usually for permissions)"""
    return (
        query.join(Participant, Incident.id == Participant.incident_id)
        .join(IndividualContact)
        .filter(
            not_(
                and_(
                    Incident.visibility == Visibility.restricted.value,
                    IndividualContact.email != current_user.email,
                )
            )
        )
    )
Exemplo n.º 21
0
    def get_scenario_view_states(self, states_filter=None, pagination=None):
        """Search for scenario view_states by filter.

        :param states_filter: instance of :class:`ScenarioStateFilter
            <autostorage.core.scenario.param_spec.ScenarioStateFilter>`.
        :param pagination: instance of `Pagination <autostorage.core.param_spec.Pagination>`.
        :returns: list with instances of :class:`ScenarioState
            <autostorage.core.scenario.scenario.ScenarioState>`.
        """
        ids_query = Query(ScenarioViewStateRecord)

        subquery = Query([
            ScenarioViewStateRecord.scenario_id,
            func.max(ScenarioViewStateRecord.changed).label('newest_change_date')
            ])

        if states_filter and states_filter.date:
            subquery = subquery.filter(ScenarioViewStateRecord.changed <= states_filter.date)

        subquery = subquery.group_by(ScenarioViewStateRecord.scenario_id).subquery()

        ids_query = ids_query.join(
            subquery,
            and_(
                ScenarioViewStateRecord.scenario_id == subquery.columns.scenario_id,
                ScenarioViewStateRecord.changed == subquery.columns.newest_change_date
                )
            )

        if pagination:
            offset = pagination.page_index * pagination.items_per_page
            ids_query = ids_query.offset(offset).limit(pagination.items_per_page)

        with self.base.get_session() as session:
            bound_query = ids_query.with_session(session)
            states = []
            for state_record in bound_query:
                scenario = ScenarioEntity(self.base, state_record.scenario_id)
                state = ScenarioViewStateEntity(
                    scenario=scenario,
                    name=state_record.name,
                    description=state_record.description,
                    date=state_record.changed
                    )
                states.append(state)

        return states
Exemplo n.º 22
0
 def join_to_clusters(base_citation_query: Query) -> Tuple[Query, Alias, Alias]:
     citing_opinion, cited_opinion = aliased(Opinion), aliased(Opinion)
     citing_cluster, cited_cluster = aliased(Cluster), aliased(Cluster)
     return (
         (
             base_citation_query.join(
                 citing_opinion,
                 Citation.citing_opinion_id == citing_opinion.resource_id,
             )
             .join(
                 cited_opinion,
                 Citation.cited_opinion_id == cited_opinion.resource_id,
             )
             .join(
                 citing_cluster,
                 citing_opinion.cluster_id == citing_cluster.resource_id,
             )
             .join(
                 cited_cluster, cited_opinion.cluster_id == cited_cluster.resource_id
             )
         ),
         citing_cluster,
         cited_cluster,
     )
Exemplo n.º 23
0
def restricted_job_filter(query: orm.Query, current_user: DispatchUser,
                          role: UserRoles):
    """Adds additional incident type filters to query (usually for permissions)."""

    if current_user:
        if role == UserRoles.WORKER:
            query = (query.join(
                Worker, Worker.id == Job.scheduled_primary_worker_id).join(
                    DispatchUser,
                    DispatchUser.id == Worker.dispatch_user_id).filter(
                        DispatchUser.email == current_user.email))
            query.distinct()
        elif role == UserRoles.PLANNER:
            team_list = [i.id for i in current_user.managed_teams]
            team_list.append(current_user.default_team_id)
            query = query.filter(Job.team_id.in_(set(team_list)))
        elif role == UserRoles.CUSTOMER:
            # team_list = [i.id for i in current_user.managed_teams]
            locs = location_service.get_by_auth_email(db_session=query.session,
                                                      email=current_user.email)
            loc_id_list = [i.id for i in locs]
            query = query.filter(Job.location_id.in_(set(loc_id_list)))

    return query
Exemplo n.º 24
0
def query_select(session, columns, join, tool_metric_filters, multiqc):
    # Add the Sqlalchemy class columns needed for the given column selection.
    select_cols = []

    # Order of the column output is the order of user's --select input.
    for col in columns:
        if col == 'sample':
            select_cols.extend([
                Sample.id, Sample.sample_name, Sample.flowcell_lane,
                Sample.library_id, Sample.platform, Sample.centre,
                Sample.reference_genome, Sample.description
            ])
        if col == 'cohort':
            select_cols.extend([
                Cohort.id, Cohort.description, Cohort.sample_count,
                Cohort.batch_count
            ])
        if col == 'batch':
            select_cols.extend(
                [Batch.batch_name, Batch.description, Batch.sample_count])
        if col == 'tool-metric':
            # If filtering on tool, we need to select for the tool metrics.
            if tool_metric_filters:
                for tm in tool_metric_filters:
                    # Use the metric name as this column's alias.
                    c = func.max(RawData.metrics[tm[1]].astext).label(tm[1])
                    c.quote = True
                    select_cols.append(c)
            else:
                select_cols.append(RawData.qc_tool)
    if multiqc:
        # Need to add batch paths.
        select_cols.append(Batch.path)

    query = Query(select_cols, session=session)
    join['joined'].add(
        columns[0]
    )  # The first item in select query doesn't need to be explicitly joined

    ### ================================= JOIN  ==========================================####
    # Add the table joins needed for the given column selection or filtering.

    if 'sample' in join['joins'] and 'sample' not in join['joined']:
        if 'tool-metric' in join['joined']:
            query = query.join(Sample, Sample.id == RawData.sample_id)
        elif 'batch' in join['joined']:
            query = query.join(Sample, Sample.batch_id == Batch.id)
        elif 'cohort' in join['joined']:
            query = query.join(Sample, Sample.cohort_id == Cohort.id)
        join['joined'].add('sample')

    # For multiqc we need Batch for batch.path.
    if (multiqc or 'batch' in join['joins']) and 'batch' not in join['joined']:
        if 'tool-metric' in join['joined'] and 'sample' not in join['joined']:
            query = query.join(Sample, Sample.id == RawData.sample_id)
            join['joined'].add('sample')
        if 'sample' in join['joined']:
            query = query.join(Batch, Batch.id == Sample.batch_id)
        elif 'cohort' in join['joined']:
            query = query.join(Batch, Batch.cohort_id == Cohort.id)
        join['joined'].add('batch')

    if 'cohort' in join['joins'] and 'cohort' not in join['joined']:
        if 'tool-metric' in join['joined'] and 'sample' not in join['joined']:
            query = query.join(Sample, Sample.id == RawData.sample_id)
            join['joined'].add('sample')
        if 'sample' in join['joined']:
            query = query.join(Cohort, Cohort.id == Sample.cohort_id)
        elif 'batch' in join['joined']:
            query = query.join(Cohort, Cohort.id == Batch.cohort_id)
        join['joined'].add('cohort')

    if 'tool-metric' in join['joins'] and 'tool-metric' not in join['joined']:
        if 'batch' in join['joined'] and 'sample' not in join['joined']:
            query = query.join(Sample, Sample.batch_id == Batch.id)
        elif 'cohort' in join['joined'] and 'sample' not in join['joined']:
            query = query.join(Sample, Sample.cohort_id == Cohort.id)
        query = query.join(RawData, RawData.sample_id == Sample.id)
        join['joined'].add('tool-metric')

    return query
Exemplo n.º 25
0
def filter_users_with_at_least_one_not_validated_offerer_validated_user_offerer(
        query: Query) -> Query:
    return (query.join(UserOfferer).join(
        Offerer).filter((Offerer.validationToken != None)
                        & (UserOfferer.validationToken == None)))
Exemplo n.º 26
0
class QueryMaker(object):
    def __init__(
            self,
            # An optional `Declarative class <http://docs.sqlalchemy.org/en/latest/orm/tutorial.html#declare-a-mapping>`_ to query.
            declarative_class=None,
            # Optionally, begin with an existing query_.
            query=None):

        if declarative_class:
            assert _is_mapped_class(declarative_class)

        # If a query is provided, try to infer the declarative_class.
        if query is not None:
            assert isinstance(query, Query)
            self._query = query
            try:
                self._select = self._get_joinpoint_zero_class()
            except:
                # We can't infer it. Use what's provided instead, and add this to the query.
                assert declarative_class
                self._select = declarative_class
                self._query = self._query.select_from(declarative_class)
            else:
                # If a declarative_class was provided, make sure it's consistent with the inferred class.
                if declarative_class:
                    assert declarative_class is self._select
        else:
            # The declarative class must be provided if the query wasn't.
            assert declarative_class
            # Since a query was not provied, create an empty `query <http://docs.sqlalchemy.org/en/latest/orm/query.html>`_; ``to_query`` will fill in the missing information.
            self._query = Query([]).select_from(declarative_class)
            # Keep track of the last selectable construct, to generate the select in ``to_query``.
            self._select = declarative_class

    # Copied verbatim from ``sqlalchemy.orm.query.Query._clone``. This adds the support needed for the _`generative` interface. (Mostly) quoting from query_, "QueryMaker_ features a generative interface whereby successive calls return a new QueryMaker_ object, a copy of the former with additional criteria and options associated with it."
    def _clone(self):
        cls = self.__class__
        q = cls.__new__(cls)
        q.__dict__ = self.__dict__.copy()
        return q

    # Looking up a class's `Column <http://docs.sqlalchemy.org/en/latest/core/metadata.html#sqlalchemy.schema.Column>`_ or `relationship <http://docs.sqlalchemy.org/en/latest/orm/relationship_api.html#sqlalchemy.orm.relationship>`_ generates the matching query.
    @_generative()
    def __getattr__(self, name):
        # Find the Column_ or relationship_ in the join point class we're querying.
        attr = getattr(self._get_joinpoint_zero_class(), name)
        # If the attribute refers to a column, save this as a possible select statement. Note that a Column_ gets replaced with an `InstrumentedAttribute <http://docs.sqlalchemy.org/en/latest/orm/internals.html?highlight=instrumentedattribute#sqlalchemy.orm.attributes.InstrumentedAttribute>`_; see `QueryableAttribute <http://docs.sqlalchemy.org/en/latest/orm/internals.html?highlight=instrumentedattribute#sqlalchemy.orm.attributes.QueryableAttribute.property>`_.
        if isinstance(attr.property, ColumnProperty):
            self._select = attr
        elif isinstance(attr.property, RelationshipProperty):
            # Figure out what class this relationship refers to. See `mapper.params.class_ <http://docs.sqlalchemy.org/en/latest/orm/mapping_api.html?highlight=mapper#sqlalchemy.orm.mapper.params.class_>`_.
            declarative_class = attr.property.mapper.class_
            # Update the query by performing the implied join.
            self._query = self._query.join(declarative_class)
            # Save this relationship as a possible select statement.
            self._select = declarative_class
        else:
            # This isn't a Column_ or a relationship_.
            assert False

    # Indexing the object performs the implied filter. For example, ``session(User)['jack']`` implies ``session.query(User).filter(User.name == 'jack')``.
    @_generative()
    def __getitem__(
        self,
        # Most often, this is a key which will be filtered by the ``default_query`` method of the currently-active `Declarative class`_. In the example above, the ``User`` class must define a ``default_query`` to operate on strings. However, it may also be a filter criterion, such as ``session(User)[User.name == 'jack']``.
        key):

        # See if this is a filter criterion; if not, rely in the ``default_query`` defined by the `Declarative class`_ or fall back to the first primary key.
        criteria = None
        jp0_class = self._get_joinpoint_zero_class()
        if isinstance(key, ClauseElement):
            criteria = key
        elif hasattr(jp0_class, 'default_query'):
            criteria = jp0_class.default_query(key)
        if criteria is None:
            pks = inspect(jp0_class).primary_key
            criteria = pks[0] == key
        self._query = self._query.filter(criteria)

    # Support common syntax: ``for x in query_maker:`` converts this to a query and returns results. The session must already have been set.
    def __iter__(self):
        return self.to_query().__iter__()

    # This property returns a `_QueryWrapper`_, a query-like object which transforms returned Query_ values back into this class while leaving other return values unchanged.
    @property
    def q(self):
        return _QueryWrapper(self)

    # Transform this object into a Query_.
    def to_query(
        self,
        # Optionally, the `Session <http://docs.sqlalchemy.org/en/latest/orm/session_api.html?highlight=session#sqlalchemy.orm.session.Session>`_ to run this query in.
        session=None):

        # If a session was specified, use it to produce the query_; otherwise, use the existing query_.
        query = self._query.with_session(session) if session else self._query
        # Choose the correct method to select either a column or a class (e.g. an entity). As noted earlier, a Column_ becomes and InstrumentedAttribute_.
        if isinstance(self._select, InstrumentedAttribute):
            return query.add_columns(self._select)
        else:
            return query.add_entity(self._select)

    # Get the right-most join point in the current query.
    def _get_joinpoint_zero_class(self):
        jp0 = self._query._joinpoint_zero()
        # If the join point was returned as a `Mapper <http://docs.sqlalchemy.org/en/latest/orm/mapping_api.html#sqlalchemy.orm.mapper.Mapper>`_, get the underlying class.
        if isinstance(jp0, Mapper):
            jp0 = jp0.class_
        return jp0
Exemplo n.º 27
0
    def _join_omics_processing_related_tables(self, target_table: Table,
                                              query: Query) -> Query:
        if target_table != Table.omics_processing:
            query = query.join(models.OmicsProcessing)

        return self.join_omics_processing(query)
Exemplo n.º 28
0
 def _join_study_related_tables(self, target_table: Table,
                                query: Query) -> Query:
     if target_table != Table.study:
         query = query.join(models.Study)
     return self.join_study(query)
Exemplo n.º 29
0
 def join_self(self, query: Query, parent: Table) -> Query:
     if self.table == parent:
         return query
     return query.join(self.table.model)
Exemplo n.º 30
0
 def join_study(self, query: Query) -> Query:
     return self.join_self(
         query.join(models.OmicsProcessing,
                    models.Study.id == models.OmicsProcessing.study_id),
         Table.omics_processing,
     )
Exemplo n.º 31
0
 def join_study(self, query: Query) -> Query:
     return self.join_self(
         query.join(models.Biosample,
                    models.Study.id == models.Biosample.study_id),
         Table.biosample,
     )