示例#1
0
 def _handle_alias(self, alias_info, dialect, queries):
     select_info_target = SelectCrawler.get(
         alias_info.from_expression_element, queries, dialect)
     if isinstance(select_info_target, str):
         # It's an alias to an external table whose
         # number of columns could vary without our
         # knowledge. Thus, warn.
         self.logger.debug(
             f"Query target {select_info_target} is external. Generating warning."
         )
         raise RuleFailure()
     else:
         # Handle nested SELECT.
         self._analyze_result_columns(select_info_target, dialect, queries)
示例#2
0
 def _analyze_result_columns(
     self,
     select_info_list: List[SelectCrawler],
     dialect: Dialect,
     queries: Dict[str, List[SelectCrawler]],
 ):
     """Given info on a list of SELECTs, determine whether to warn."""
     # Recursively walk from the given query (select_info_list) to any
     # wildcard columns in the select targets. If every wildcard evdentually
     # resolves to a query without wildcards, all is well. Otherwise, warn.
     for select_info in select_info_list:
         self.logger.debug(
             f"Analyzing query: {select_info.select_statement.raw}")
         for wildcard in select_info.get_wildcard_info():
             if wildcard.tables:
                 for wildcard_table in wildcard.tables:
                     self.logger.debug(
                         f"Wildcard: {wildcard.segment.raw} has target {wildcard_table}"
                     )
                     # Is it an alias?
                     alias_info = select_info.find_alias(wildcard_table)
                     if alias_info:
                         # Found the alias matching the wildcard. Recurse,
                         # analyzing the query associated with that alias.
                         self._handle_alias(alias_info, dialect, queries)
                     else:
                         # Not an alias. Is it a CTE?
                         if wildcard_table in queries:
                             # Wildcard refers to a CTE. Analyze it.
                             self._analyze_result_columns(
                                 queries.pop(wildcard_table), dialect,
                                 queries)
                         else:
                             # Not CTE, not table alias. Presumably an
                             # external table. Warn.
                             self.logger.debug(
                                 f"Query target {wildcard_table} is external. Generating warning."
                             )
                             raise RuleFailure()
             else:
                 # No table was specified with the wildcard. Assume we're
                 # querying from a nested select in FROM.
                 select_info_target = SelectCrawler.get(
                     select_info.select_statement, queries, dialect)
                 assert isinstance(select_info_target, list)
                 self._analyze_result_columns(
                     select_info_target,
                     dialect,
                     queries,
                 )
示例#3
0
 def _analyze_result_columns(self, query: Query):
     """Given info on a list of SELECTs, determine whether to warn."""
     # Recursively walk from the given query (select_info_list) to any
     # wildcard columns in the select targets. If every wildcard evdentually
     # resolves to a query without wildcards, all is well. Otherwise, warn.
     if not query.selectables:
         return
     for selectable in query.selectables:
         self.logger.debug(f"Analyzing query: {selectable.selectable.raw}")
         for wildcard in selectable.get_wildcard_info():
             if wildcard.tables:
                 for wildcard_table in wildcard.tables:
                     self.logger.debug(
                         f"Wildcard: {wildcard.segment.raw} has target "
                         "{wildcard_table}")
                     # Is it an alias?
                     alias_info = selectable.find_alias(wildcard_table)
                     if alias_info:
                         # Found the alias matching the wildcard. Recurse,
                         # analyzing the query associated with that alias.
                         self._handle_alias(selectable, alias_info, query)
                     else:
                         # Not an alias. Is it a CTE?
                         cte = query.lookup_cte(wildcard_table)
                         if cte:
                             # Wildcard refers to a CTE. Analyze it.
                             self._analyze_result_columns(cte)
                         else:
                             # Not CTE, not table alias. Presumably an
                             # external table. Warn.
                             self.logger.debug(
                                 f"Query target {wildcard_table} is external. "
                                 "Generating warning.")
                             raise RuleFailure(selectable.selectable)
             else:
                 # No table was specified with the wildcard. Assume we're
                 # querying from a nested select in FROM.
                 query_list = SelectCrawler.get(
                     query, query.selectables[0].selectable)
                 for o in query_list:
                     if isinstance(o, Query):
                         self._analyze_result_columns(o)
                         return
                 self.logger.debug(
                     f'Query target "{query.selectables[0].selectable.raw}" has no '
                     "targets. Generating warning.")
                 raise RuleFailure(query.selectables[0].selectable)