given an iterable of things to select FROM, reduce them to what would actually render in the FROM clause of a SELECT. This does the job of checking for JOINs, tables, etc. that are in fact overlapping due to cloning, adaption, present in overlapping joins, etc.
(
cls,
iterable_of_froms: Iterable[FromClause],
check_statement: Optional[Select[Unpack[TupleAny]]] = None,
ambiguous_table_name_map: Optional[_AmbiguousTableNameMap] = None,
)
| 5009 | |
| 5010 | @classmethod |
| 5011 | def _normalize_froms( |
| 5012 | cls, |
| 5013 | iterable_of_froms: Iterable[FromClause], |
| 5014 | check_statement: Optional[Select[Unpack[TupleAny]]] = None, |
| 5015 | ambiguous_table_name_map: Optional[_AmbiguousTableNameMap] = None, |
| 5016 | ) -> List[FromClause]: |
| 5017 | """given an iterable of things to select FROM, reduce them to what |
| 5018 | would actually render in the FROM clause of a SELECT. |
| 5019 | |
| 5020 | This does the job of checking for JOINs, tables, etc. that are in fact |
| 5021 | overlapping due to cloning, adaption, present in overlapping joins, |
| 5022 | etc. |
| 5023 | |
| 5024 | """ |
| 5025 | seen: Set[FromClause] = set() |
| 5026 | froms: List[FromClause] = [] |
| 5027 | |
| 5028 | for item in iterable_of_froms: |
| 5029 | if is_subquery(item) and item.element is check_statement: |
| 5030 | raise exc.InvalidRequestError( |
| 5031 | "select() construct refers to itself as a FROM" |
| 5032 | ) |
| 5033 | |
| 5034 | if not seen.intersection(item._cloned_set): |
| 5035 | froms.append(item) |
| 5036 | seen.update(item._cloned_set) |
| 5037 | |
| 5038 | if froms: |
| 5039 | toremove = set( |
| 5040 | itertools.chain.from_iterable( |
| 5041 | [_expand_cloned(f._hide_froms) for f in froms] |
| 5042 | ) |
| 5043 | ) |
| 5044 | if toremove: |
| 5045 | # filter out to FROM clauses not in the list, |
| 5046 | # using a list to maintain ordering |
| 5047 | froms = [f for f in froms if f not in toremove] |
| 5048 | |
| 5049 | if ambiguous_table_name_map is not None: |
| 5050 | ambiguous_table_name_map.update( |
| 5051 | ( |
| 5052 | fr.name, |
| 5053 | _anonymous_label.safe_construct( |
| 5054 | hash(fr.name), fr.name |
| 5055 | ), |
| 5056 | ) |
| 5057 | for item in froms |
| 5058 | for fr in item._from_objects |
| 5059 | if is_table(fr) |
| 5060 | and fr.schema |
| 5061 | and fr.name not in ambiguous_table_name_map |
| 5062 | ) |
| 5063 | |
| 5064 | return froms |
| 5065 | |
| 5066 | def _get_display_froms( |
| 5067 | self, |
no test coverage detected