MCPcopy
hub / github.com/sqlalchemy/sqlalchemy / FromLinter

Class FromLinter

lib/sqlalchemy/sql/compiler.py:743–806  ·  view source on GitHub ↗

represents current state for the "cartesian product" detection feature.

Source from the content-addressed store, hash-verified

741
742
743class FromLinter(collections.namedtuple("FromLinter", ["froms", "edges"])):
744 """represents current state for the "cartesian product" detection
745 feature."""
746
747 def lint(self, start=None):
748 froms = self.froms
749 if not froms:
750 return None, None
751
752 edges = set(self.edges)
753 the_rest = set(froms)
754
755 if start is not None:
756 start_with = start
757 the_rest.remove(start_with)
758 else:
759 start_with = the_rest.pop()
760
761 stack = collections.deque([start_with])
762
763 while stack and the_rest:
764 node = stack.popleft()
765 the_rest.discard(node)
766
767 # comparison of nodes in edges here is based on hash equality, as
768 # there are "annotated" elements that match the non-annotated ones.
769 # to remove the need for in-python hash() calls, use native
770 # containment routines (e.g. "node in edge", "edge.index(node)")
771 to_remove = {edge for edge in edges if node in edge}
772
773 # appendleft the node in each edge that is not
774 # the one that matched.
775 stack.extendleft(edge[not edge.index(node)] for edge in to_remove)
776 edges.difference_update(to_remove)
777
778 # FROMS left over? boom
779 if the_rest:
780 return the_rest, start_with
781 else:
782 return None, None
783
784 def warn(self, stmt_type="SELECT"):
785 the_rest, start_with = self.lint()
786
787 # FROMS left over? boom
788 if the_rest:
789 froms = the_rest
790 if froms:
791 template = (
792 "{stmt_type} statement has a cartesian product between "
793 "FROM element(s) {froms} and "
794 'FROM element "{start}". Apply join condition(s) '
795 "between each element to resolve."
796 )
797 froms_str = ", ".join(
798 f'"{self.froms[from_]}"' for from_ in froms
799 )
800 message = template.format(

Callers 3

_compose_select_bodyMethod · 0.85
visit_updateMethod · 0.85
visit_deleteMethod · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected