MCPcopy Create free account
hub / github.com/sqlalchemy/sqlalchemy / FromLinter

Class FromLinter

lib/sqlalchemy/sql/compiler.py:709–772  ·  view source on GitHub ↗

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

Source from the content-addressed store, hash-verified

707
708
709class FromLinter(collections.namedtuple("FromLinter", ["froms", "edges"])):
710 """represents current state for the "cartesian product" detection
711 feature."""
712
713 def lint(self, start=None):
714 froms = self.froms
715 if not froms:
716 return None, None
717
718 edges = set(self.edges)
719 the_rest = set(froms)
720
721 if start is not None:
722 start_with = start
723 the_rest.remove(start_with)
724 else:
725 start_with = the_rest.pop()
726
727 stack = collections.deque([start_with])
728
729 while stack and the_rest:
730 node = stack.popleft()
731 the_rest.discard(node)
732
733 # comparison of nodes in edges here is based on hash equality, as
734 # there are "annotated" elements that match the non-annotated ones.
735 # to remove the need for in-python hash() calls, use native
736 # containment routines (e.g. "node in edge", "edge.index(node)")
737 to_remove = {edge for edge in edges if node in edge}
738
739 # appendleft the node in each edge that is not
740 # the one that matched.
741 stack.extendleft(edge[not edge.index(node)] for edge in to_remove)
742 edges.difference_update(to_remove)
743
744 # FROMS left over? boom
745 if the_rest:
746 return the_rest, start_with
747 else:
748 return None, None
749
750 def warn(self, stmt_type="SELECT"):
751 the_rest, start_with = self.lint()
752
753 # FROMS left over? boom
754 if the_rest:
755 froms = the_rest
756 if froms:
757 template = (
758 "{stmt_type} statement has a cartesian product between "
759 "FROM element(s) {froms} and "
760 'FROM element "{start}". Apply join condition(s) '
761 "between each element to resolve."
762 )
763 froms_str = ", ".join(
764 f'"{self.froms[from_]}"' for from_ in froms
765 )
766 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