Exemplo n.º 1
0
 def apply_outer_select_joins(
     self, query: BaseQuery, select_columns: List[str] = None
 ) -> BaseQuery:
     if not select_columns:
         return query
     for column in select_columns:
         if is_column_dotted(column):
             root_relation = get_column_root_relation(column)
             leaf_column = get_column_leaf(column)
             if self.is_relation_many_to_many(
                 root_relation
             ) or self.is_relation_one_to_many(root_relation):
                 query = query.options(
                     Load(self.obj).joinedload(root_relation).load_only(leaf_column)
                 )
             else:
                 related_model = self.get_related_model(root_relation)
                 query = query.options(Load(related_model).load_only(leaf_column))
         else:
             query = self._apply_normal_col_select_option(query, column)
     return query
Exemplo n.º 2
0
    def _add_prefetch(self, query: BaseQuery) -> BaseQuery:
        if self.prefetch:
            # apply joinedloaded rels
            for rels in self.prefetch:
                if is_listy(rels):
                    # list/tuple, construct chain of joinedloads
                    if len(rels) > 1:
                        opts = reduce(
                            lambda o, r: o.joinedload(r), rels[1:], joinedload(rels[0])
                        )
                    else:
                        opts = joinedload(rels[0])
                else:
                    # just a single relationship (not chained)
                    opts = joinedload(rels)

                query = query.options(opts)
        return query
Exemplo n.º 3
0
    def apply_inner_select_joins(
            self,
            query: BaseQuery,
            select_columns: List[str] = None) -> BaseQuery:
        """
        Add select load options to query. The goal
        is to only SQL select what is requested and join all the necessary
        models when dotted notation is used. Inner implies non dotted columns
        and one to many and one to one

        :param query:
        :param select_columns:
        :return:
        """
        if not select_columns:
            return query
        joined_models = list()
        for column in select_columns:
            if is_column_dotted(column):
                root_relation = get_column_root_relation(column)
                leaf_column = get_column_leaf(column)
                if self.is_relation_many_to_one(
                        root_relation) or self.is_relation_one_to_one(
                            root_relation):
                    if root_relation not in joined_models:
                        query = self._query_join_relation(query, root_relation)
                        # only needed if we need to wrap this query, from_self
                        if select_columns and self.exists_col_to_many(
                                select_columns):
                            related_model = self.get_related_model(
                                root_relation)
                            query = query.add_entity(related_model)
                        joined_models.append(root_relation)
                    query = query.options(
                        (contains_eager(root_relation).load_only(leaf_column)))
            else:
                query = self._apply_normal_col_select_option(query, column)
        return query
Exemplo n.º 4
0
    def _query_select_options(self,
                              query: BaseQuery,
                              select_columns: List[str] = None) -> BaseQuery:
        """
        Add select load options to query. The goal
        is to only SQL select what is requested and join all the necessary
        models when dotted notation is used

        :param query: SQLAlchemy Query obj to apply joins and selects
        :param select_columns: (list) of columns
        :return: Transformed SQLAlchemy Query
        """
        if select_columns:
            load_options = list()
            joined_models = list()
            for column in select_columns:
                if is_column_dotted(column):
                    root_relation = get_column_root_relation(column)
                    leaf_column = get_column_leaf(column)
                    if self.is_relation_many_to_many(
                            root_relation) or self.is_relation_one_to_many(
                                root_relation):
                        load_options.append((Load(self.obj).joinedload(
                            root_relation).load_only(leaf_column)))
                        continue
                    elif root_relation not in joined_models:
                        query = self._query_join_relation(query, root_relation)
                        joined_models.append(root_relation)
                    load_options.append(
                        (contains_eager(root_relation).load_only(leaf_column)))
                else:
                    if not self.is_relation(
                            column) and not self.is_property_or_function(
                                column):
                        load_options.append(load_only(column))
            query = query.options(*tuple(load_options))
        return query
Exemplo n.º 5
0
    def _query_select_options(self,
                              query: BaseQuery,
                              select_columns: List[str] = None) -> BaseQuery:
        """
        Add select load options to query. The goal
        is to only SQL select what is requested and join all the necessary
        models when dotted notation is used

        :param query: SQLAlchemy Query obj to apply joins and selects
        :param select_columns: (list) of columns
        :return: Transformed SQLAlchemy Query
        """
        if select_columns:
            load_options = list()
            joined_models = list()
            for column in select_columns:
                if is_column_dotted(column):
                    root_relation = get_column_root_relation(column)
                    leaf_column = get_column_leaf(column)
                    if root_relation not in joined_models:
                        query = self._query_join_relation(query, root_relation)
                        joined_models.append(root_relation)
                    load_options.append((Load(self.obj).joinedload(
                        root_relation).load_only(leaf_column)))
                else:
                    # is a custom property method field?
                    if hasattr(getattr(self.obj, column), "fget"):
                        pass
                    # is not a relation and not a function?
                    elif not self.is_relation(column) and not hasattr(
                            getattr(self.obj, column), "__call__"):
                        load_options.append(Load(self.obj).load_only(column))
                    # it's a normal column
                    else:
                        load_options.append(Load(self.obj))
            query = query.options(*tuple(load_options))
        return query