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[Any]] = None,
ambiguous_table_name_map: Optional[_AmbiguousTableNameMap] = None,
)
| 4883 | |
| 4884 | @classmethod |
| 4885 | def _normalize_froms( |
| 4886 | cls, |
| 4887 | iterable_of_froms: Iterable[FromClause], |
| 4888 | check_statement: Optional[Select[Any]] = None, |
| 4889 | ambiguous_table_name_map: Optional[_AmbiguousTableNameMap] = None, |
| 4890 | ) -> List[FromClause]: |
| 4891 | """given an iterable of things to select FROM, reduce them to what |
| 4892 | would actually render in the FROM clause of a SELECT. |
| 4893 | |
| 4894 | This does the job of checking for JOINs, tables, etc. that are in fact |
| 4895 | overlapping due to cloning, adaption, present in overlapping joins, |
| 4896 | etc. |
| 4897 | |
| 4898 | """ |
| 4899 | seen: Set[FromClause] = set() |
| 4900 | froms: List[FromClause] = [] |
| 4901 | |
| 4902 | for item in iterable_of_froms: |
| 4903 | if is_subquery(item) and item.element is check_statement: |
| 4904 | raise exc.InvalidRequestError( |
| 4905 | "select() construct refers to itself as a FROM" |
| 4906 | ) |
| 4907 | |
| 4908 | if not seen.intersection(item._cloned_set): |
| 4909 | froms.append(item) |
| 4910 | seen.update(item._cloned_set) |
| 4911 | |
| 4912 | if froms: |
| 4913 | toremove = set( |
| 4914 | itertools.chain.from_iterable( |
| 4915 | [_expand_cloned(f._hide_froms) for f in froms] |
| 4916 | ) |
| 4917 | ) |
| 4918 | if toremove: |
| 4919 | # filter out to FROM clauses not in the list, |
| 4920 | # using a list to maintain ordering |
| 4921 | froms = [f for f in froms if f not in toremove] |
| 4922 | |
| 4923 | if ambiguous_table_name_map is not None: |
| 4924 | ambiguous_table_name_map.update( |
| 4925 | ( |
| 4926 | fr.name, |
| 4927 | _anonymous_label.safe_construct( |
| 4928 | hash(fr.name), fr.name |
| 4929 | ), |
| 4930 | ) |
| 4931 | for item in froms |
| 4932 | for fr in item._from_objects |
| 4933 | if is_table(fr) |
| 4934 | and fr.schema |
| 4935 | and fr.name not in ambiguous_table_name_map |
| 4936 | ) |
| 4937 | |
| 4938 | return froms |
| 4939 | |
| 4940 | def _get_display_froms( |
| 4941 | self, |
no test coverage detected