Change the alias prefix to the next letter in the alphabet in a way that the other query's aliases and this query's aliases will not conflict. Even tables that previously had no alias will get an alias after this call. To prevent changing aliases use the exclude para
(self, other_query, exclude=None)
| 1055 | combined_query.change_aliases(external_change_map) |
| 1056 | |
| 1057 | def bump_prefix(self, other_query, exclude=None): |
| 1058 | """ |
| 1059 | Change the alias prefix to the next letter in the alphabet in a way |
| 1060 | that the other query's aliases and this query's aliases will not |
| 1061 | conflict. Even tables that previously had no alias will get an alias |
| 1062 | after this call. To prevent changing aliases use the exclude parameter. |
| 1063 | """ |
| 1064 | |
| 1065 | def prefix_gen(): |
| 1066 | """ |
| 1067 | Generate a sequence of characters in alphabetical order: |
| 1068 | -> 'A', 'B', 'C', ... |
| 1069 | |
| 1070 | When the alphabet is finished, the sequence will continue with the |
| 1071 | Cartesian product: |
| 1072 | -> 'AA', 'AB', 'AC', ... |
| 1073 | """ |
| 1074 | alphabet = ascii_uppercase |
| 1075 | prefix = chr(ord(self.alias_prefix) + 1) |
| 1076 | yield prefix |
| 1077 | for n in count(1): |
| 1078 | seq = alphabet[alphabet.index(prefix) :] if prefix else alphabet |
| 1079 | for s in product(seq, repeat=n): |
| 1080 | yield "".join(s) |
| 1081 | prefix = None |
| 1082 | |
| 1083 | if self.alias_prefix != other_query.alias_prefix: |
| 1084 | # No clashes between self and outer query should be possible. |
| 1085 | return |
| 1086 | |
| 1087 | # Explicitly avoid infinite loop. The constant divider is based on how |
| 1088 | # much depth recursive subquery references add to the stack. This value |
| 1089 | # might need to be adjusted when adding or removing function calls from |
| 1090 | # the code path in charge of performing these operations. |
| 1091 | local_recursion_limit = sys.getrecursionlimit() // 16 |
| 1092 | for pos, prefix in enumerate(prefix_gen()): |
| 1093 | if prefix not in self.subq_aliases: |
| 1094 | self.alias_prefix = prefix |
| 1095 | break |
| 1096 | if pos > local_recursion_limit: |
| 1097 | raise RecursionError( |
| 1098 | "Maximum recursion depth exceeded: too many subqueries." |
| 1099 | ) |
| 1100 | self.subq_aliases = self.subq_aliases.union([self.alias_prefix]) |
| 1101 | other_query.subq_aliases = other_query.subq_aliases.union(self.subq_aliases) |
| 1102 | if exclude is None: |
| 1103 | exclude = {} |
| 1104 | self.change_aliases( |
| 1105 | { |
| 1106 | alias: "%s%d" % (self.alias_prefix, pos) |
| 1107 | for pos, alias in enumerate(self.alias_map) |
| 1108 | if alias not in exclude |
| 1109 | } |
| 1110 | ) |
| 1111 | |
| 1112 | def get_initial_alias(self): |
| 1113 | """ |
no test coverage detected