summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql/util.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2008-04-04 00:21:28 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2008-04-04 00:21:28 +0000
commit1dbed0b2b4446408f14a87d94f9c0c6b3356fcf2 (patch)
tree2dcd585d8472170cdcfd8bdbd658f60a4728a282 /lib/sqlalchemy/sql/util.py
parent9dd01e52e2e0755bbaf6e08b048e9a48b55879d1 (diff)
downloadsqlalchemy-1dbed0b2b4446408f14a87d94f9c0c6b3356fcf2.tar.gz
- merged sync_simplify branch
- The methodology behind "primaryjoin"/"secondaryjoin" has been refactored. Behavior should be slightly more intelligent, primarily in terms of error messages which have been pared down to be more readable. In a slight number of scenarios it can better resolve the correct foreign key than before. - moved collections unit test from relationships.py to collection.py - PropertyLoader now has "synchronize_pairs" and "equated_pairs" collections which allow easy access to the source/destination parent/child relation between columns (might change names) - factored out ClauseSynchronizer (finally) - added many more tests for priamryjoin/secondaryjoin error checks
Diffstat (limited to 'lib/sqlalchemy/sql/util.py')
-rw-r--r--lib/sqlalchemy/sql/util.py42
1 files changed, 40 insertions, 2 deletions
diff --git a/lib/sqlalchemy/sql/util.py b/lib/sqlalchemy/sql/util.py
index 8ed561e5f..5b9ffd4fa 100644
--- a/lib/sqlalchemy/sql/util.py
+++ b/lib/sqlalchemy/sql/util.py
@@ -1,10 +1,12 @@
-from sqlalchemy import exceptions, schema, topological, util
+from sqlalchemy import exceptions, schema, topological, util, sql
from sqlalchemy.sql import expression, operators, visitors
from itertools import chain
"""Utility functions that build upon SQL and Schema constructs."""
def sort_tables(tables, reverse=False):
+ """sort a collection of Table objects in order of their foreign-key dependency."""
+
tuples = []
class TVisitor(schema.SchemaVisitor):
def visit_foreign_key(_self, fkey):
@@ -24,6 +26,8 @@ def sort_tables(tables, reverse=False):
return sequence
def find_tables(clause, check_columns=False, include_aliases=False):
+ """locate Table objects within the given expression."""
+
tables = []
kwargs = {}
if include_aliases:
@@ -44,6 +48,8 @@ def find_tables(clause, check_columns=False, include_aliases=False):
return tables
def find_columns(clause):
+ """locate Column objects within the given expression."""
+
cols = util.Set()
def visit_column(col):
cols.add(col)
@@ -93,6 +99,38 @@ def reduce_columns(columns, *clauses):
return expression.ColumnSet(columns.difference(omit))
+def criterion_as_pairs(expression, consider_as_foreign_keys=None, consider_as_referenced_keys=None, any_operator=False):
+ """traverse an expression and locate binary criterion pairs."""
+
+ if consider_as_foreign_keys and consider_as_referenced_keys:
+ raise exceptions.ArgumentError("Can only specify one of 'consider_as_foreign_keys' or 'consider_as_referenced_keys'")
+
+ def visit_binary(binary):
+ if not any_operator and binary.operator != operators.eq:
+ return
+ if not isinstance(binary.left, sql.ColumnElement) or not isinstance(binary.right, sql.ColumnElement):
+ return
+
+ if consider_as_foreign_keys:
+ if binary.left in consider_as_foreign_keys:
+ pairs.append((binary.right, binary.left))
+ elif binary.right in consider_as_foreign_keys:
+ pairs.append((binary.left, binary.right))
+ elif consider_as_referenced_keys:
+ if binary.left in consider_as_referenced_keys:
+ pairs.append((binary.left, binary.right))
+ elif binary.right in consider_as_referenced_keys:
+ pairs.append((binary.right, binary.left))
+ else:
+ if isinstance(binary.left, schema.Column) and isinstance(binary.right, schema.Column):
+ if binary.left.references(binary.right):
+ pairs.append((binary.right, binary.left))
+ elif binary.right.references(binary.left):
+ pairs.append((binary.left, binary.right))
+ pairs = []
+ visitors.traverse(expression, visit_binary=visit_binary)
+ return pairs
+
class AliasedRow(object):
def __init__(self, row, map):
@@ -117,7 +155,7 @@ class AliasedRow(object):
return self.row.keys()
def row_adapter(from_, equivalent_columns=None):
- """create a row adapter against a selectable."""
+ """create a row adapter callable against a selectable."""
if equivalent_columns is None:
equivalent_columns = {}