diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2008-05-02 01:02:23 +0000 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2008-05-02 01:02:23 +0000 |
| commit | e3460573d037e27592995277a19840be13457828 (patch) | |
| tree | 90fbd43479edb50e2cdc12f40fa90bc5368ed846 /lib/sqlalchemy/sql | |
| parent | c407a608c38a8d483e77fb950b21995b16fa05f7 (diff) | |
| download | sqlalchemy-e3460573d037e27592995277a19840be13457828.tar.gz | |
- factored out the logic used by Join to create its join condition
- With declarative, joined table inheritance mappers use a slightly relaxed
function to create the "inherit condition" to the parent
table, so that other foreign keys to not-yet-declared
Table objects don't trigger an error.
Diffstat (limited to 'lib/sqlalchemy/sql')
| -rw-r--r-- | lib/sqlalchemy/sql/expression.py | 32 | ||||
| -rw-r--r-- | lib/sqlalchemy/sql/util.py | 58 |
2 files changed, 61 insertions, 29 deletions
diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py index 94c145613..1143bf8aa 100644 --- a/lib/sqlalchemy/sql/expression.py +++ b/lib/sqlalchemy/sql/expression.py @@ -2308,34 +2308,10 @@ class Join(FromClause): return self.left, self.right, self.onclause def __match_primaries(self, primary, secondary): - crit = [] - constraints = util.Set() - for fk in secondary.foreign_keys: - col = fk.get_referent(primary) - if col: - crit.append(col == fk.parent) - constraints.add(fk.constraint) - if primary is not secondary: - for fk in primary.foreign_keys: - col = fk.get_referent(secondary) - if col: - crit.append(col == fk.parent) - constraints.add(fk.constraint) - if len(crit) == 0: - raise exceptions.ArgumentError( - "Can't find any foreign key relationships " - "between '%s' and '%s'" % (primary.description, secondary.description)) - elif len(constraints) > 1: - raise exceptions.ArgumentError( - "Can't determine join between '%s' and '%s'; " - "tables have more than one foreign key " - "constraint relationship between them. " - "Please specify the 'onclause' of this " - "join explicitly." % (primary.description, secondary.description)) - elif len(crit) == 1: - return (crit[0]) - else: - return and_(*crit) + global sql_util + if not sql_util: + from sqlalchemy.sql import util as sql_util + return sql_util.join_condition(primary, secondary) def select(self, whereclause=None, fold_equivalents=False, **kwargs): """Create a ``Select`` from this ``Join``. diff --git a/lib/sqlalchemy/sql/util.py b/lib/sqlalchemy/sql/util.py index dd29cb42b..0c85cbe4a 100644 --- a/lib/sqlalchemy/sql/util.py +++ b/lib/sqlalchemy/sql/util.py @@ -56,7 +56,63 @@ def find_columns(clause): visitors.traverse(clause, visit_column=visit_column) return cols - +def join_condition(a, b, ignore_nonexistent_tables=False): + """create a join condition between two tables. + + ignore_nonexistent_tables=True allows a join condition to be + determined between two tables which may contain references to + other not-yet-defined tables. In general the NoSuchTableError + raised is only required if the user is trying to join selectables + across multiple MetaData objects (which is an extremely rare use + case). + + """ + crit = [] + constraints = util.Set() + for fk in b.foreign_keys: + try: + col = fk.get_referent(a) + except exceptions.NoSuchTableError: + if ignore_nonexistent_tables: + continue + else: + raise + + if col: + crit.append(col == fk.parent) + constraints.add(fk.constraint) + + if a is not b: + for fk in a.foreign_keys: + try: + col = fk.get_referent(b) + except exceptions.NoSuchTableError: + if ignore_nonexistent_tables: + continue + else: + raise + + if col: + crit.append(col == fk.parent) + constraints.add(fk.constraint) + + if len(crit) == 0: + raise exceptions.ArgumentError( + "Can't find any foreign key relationships " + "between '%s' and '%s'" % (a.description, b.description)) + elif len(constraints) > 1: + raise exceptions.ArgumentError( + "Can't determine join between '%s' and '%s'; " + "tables have more than one foreign key " + "constraint relationship between them. " + "Please specify the 'onclause' of this " + "join explicitly." % (a.description, b.description)) + elif len(crit) == 1: + return (crit[0]) + else: + return and_(*crit) + + def reduce_columns(columns, *clauses): """given a list of columns, return a 'reduced' set based on natural equivalents. |
