コード例 #1
0
    def perform_subquery(self, allowed_platforms, dbgraph, user, query_plan):
        """
        Connect a new AST to the current AST using a SubQuery Node.
        If the connected table is "on join", we will use a LeftJoin and a CrossProduct Node instead.
        Args:
            dbgraph: The DBGraph instance related to the 3nf graph.
            allowed_platforms: A set of String where each String correponds to a queried platform name.
            user: The User issuing the Query.
            query_plan: The QueryPlan instance related to this Query, and that we're updating.
        """
        # We need to build an AST just to collect subqueries
        #OBSOLETE|        # XXX dbgraph not defined
        #OBSOLETE|        #if not self.ast:
        #OBSOLETE|        #    self.ast = self.build_union(self.root, self.keep_root_a, dbgraph, user)
        #OBSOLETE|        if not self.ast:
        #OBSOLETE|            fields = set()
        #OBSOLETE|            for _, (_, relation) in self.subqueries.items():
        #OBSOLETE|                fields |= relation.get_predicate().get_field_names()
        #OBSOLETE|            self.ast = self.build_union(self.root, fields, allowed_platforms, dbgraph, user, query_plan)
        if not self.ast:
            self.perform_union_all(self.root, allowed_platforms, dbgraph, user,
                                   query_plan)

        if self.root.capabilities.is_onjoin():
            # Let's identify tables involved in the key
            root_key_fields = self.root.keys.one().get_field_names()
            xp_ast_relation, sq_ast_relation = [], []
            xp_key = ()
            xp_value = ()
            for name, ast_relation in self.subqueries.items():
                if name in root_key_fields:
                    ast, relation = ast_relation
                    key, _, value = relation.get_predicate().get_tuple()
                    xp_key += (value, )
                    xp_value += (key, )
                    xp_ast_relation.append(ast_relation)
                else:
                    sq_ast_relation.append(ast_relation)

            ast = self.ast

            if sq_ast_relation:
                ast.subquery(sq_ast_relation)
            query = Query.action('get',
                                 self.root.get_name()).select(set(xp_key))
            self.ast = AST().cross_product(xp_ast_relation, query)
            predicate = Predicate(xp_key, eq, xp_value)

            self.ast.left_join(ast, predicate)
        else:
            self.ast.subquery(self.subqueries.values())
コード例 #2
0
    def perform_union_all(self, table, allowed_platforms, dbgraph, user,
                          query_plan):
        #OBSOLETE|    def build_union(self, table, needed_fields, allowed_platforms, dbgraph, user, query_plan):
        """
        Complete a QueryPlan instance by adding an Union of From Node related
        to a same Table.
        Args:
            table: The 3nf Table, potentially provided by several platforms.
            allowed_platforms: A set of String where each String correponds to a queried platform name.
            user: The User issuing the Query.
            query_plan: The QueryPlan instance related to this Query, and that we're updating.
        """
        from_asts = list()
        key = table.get_keys().one()

        #MANDO|DEPRECATED|        # TO BE REMOVED ?
        #MANDO|DEPRECATED|        # Exploring this tree according to a DFS algorithm leads to a table
        #MANDO|DEPRECATED|        # ordering leading to feasible successive joins
        #MANDO|DEPRECATED|        map_method_bestkey = dict()
        #MANDO|DEPRECATED|#DEPRECATED|LOIC|        map_method_demux   = dict()
        #MANDO|DEPRECATED|
        #MANDO|DEPRECATED|        # XXX I don't understand this -- Jordan
        #MANDO|DEPRECATED|        # Update the key used by a given method
        #MANDO|DEPRECATED|        # The more we iterate, the best the key is
        #MANDO|DEPRECATED|        if key:
        #MANDO|DEPRECATED|            for method, keys in table.map_method_keys.items():
        #MANDO|DEPRECATED|                if key in table.map_method_keys[method]:
        #MANDO|DEPRECATED|                    map_method_bestkey[method] = key

        # For each platform related to the current table, extract the
        # corresponding table and build the corresponding FROM node
        map_method_fields = table.get_annotations()
        for method, fields in map_method_fields.items():
            # The table announced by the platform fits with the 3nf schema
            # Build the corresponding FROM
            #sub_table = Table.make_table_from_platform(table, fields, method.get_platform())

            platform = method.get_platform()
            capabilities = dbgraph.get_capabilities(platform,
                                                    method.get_name())

            map_field_local = {
                f.get_name(): f.is_local()
                for f in table.get_fields()
            }
            selected_fields = set(
                [f for f in fields if not map_field_local[f]])
            selected_fields |= self.keep_root_a

            if not capabilities.projection:
                all_fields = set([f.get_name() for f in table.get_fields()])
                # IN 3NF, this is not necessarily all fields
                selected_fields = all_fields

            # We create 'get' queries by default, this will be overriden in set_ast
            query = Query.action('get',
                                 method.get_name()).select(selected_fields)
            #query = Query.action('get', method.get_name()).select(fields)

            if not platform in allowed_platforms:
                continue

            # The current platform::table might be ONJOIN (no retrieve capability), but we
            # might be able to collect the keys, so we have disabled the following code
            # XXX Improve platform capabilities support
            if self.relation is None and not capabilities.retrieve: continue

            from_ast = AST(user=user).From(platform, query, capabilities, key)
            if from_ast:
                query_plan.add_from(from_ast.get_root())
                self.perform_union((from_ast, dict()), key, allowed_platforms,
                                   dbgraph, user, query_plan)