summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2007-11-18 06:51:17 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2007-11-18 06:51:17 +0000
commit31b32896e81335108f77cdc44954b3c78c5f62a8 (patch)
treedd2517687ebdaa86fd77357bf1ad84021615ee78
parent61edeeae4cd74a825f48a1bebe6930227134d5eb (diff)
downloadsqlalchemy-31b32896e81335108f77cdc44954b3c78c5f62a8.tar.gz
cut down a good deal of Join construction overhead
-rw-r--r--lib/sqlalchemy/ext/activemapper.py4
-rw-r--r--lib/sqlalchemy/schema.py14
-rw-r--r--lib/sqlalchemy/sql/expression.py68
-rw-r--r--test/profiling/zoomark.py2
4 files changed, 45 insertions, 43 deletions
diff --git a/lib/sqlalchemy/ext/activemapper.py b/lib/sqlalchemy/ext/activemapper.py
index 2a39fe970..b28ada0af 100644
--- a/lib/sqlalchemy/ext/activemapper.py
+++ b/lib/sqlalchemy/ext/activemapper.py
@@ -142,9 +142,9 @@ def process_relationships(klass, was_deferred=False):
# not able to find any of the related tables
if not defer:
for col in klass.columns:
- if col.foreign_key is not None:
+ if col.foreign_keys:
found = False
- cn = col.foreign_key._colspec
+ cn = col.foreign_keys[0]._colspec
table_name = cn[:cn.rindex('.')]
for other_klass in ActiveMapperMeta.classes.values():
if other_klass.table.fullname.lower() == table_name.lower():
diff --git a/lib/sqlalchemy/schema.py b/lib/sqlalchemy/schema.py
index 856822df7..21e36fe6f 100644
--- a/lib/sqlalchemy/schema.py
+++ b/lib/sqlalchemy/schema.py
@@ -436,7 +436,7 @@ class Column(SchemaItem, expression._ColumnClause):
super(Column, self).__init__(name, None, type_)
self.args = args
self.key = kwargs.pop('key', name)
- self._primary_key = kwargs.pop('primary_key', False)
+ self.primary_key = kwargs.pop('primary_key', False)
self.nullable = kwargs.pop('nullable', not self.primary_key)
self._is_oid = kwargs.pop('_is_oid', False)
self.default = kwargs.pop('default', None)
@@ -446,14 +446,12 @@ class Column(SchemaItem, expression._ColumnClause):
self.onupdate = kwargs.pop('onupdate', None)
self.autoincrement = kwargs.pop('autoincrement', True)
self.constraints = util.Set()
- self._foreign_keys = util.OrderedSet()
+ self.foreign_keys = util.OrderedSet()
if kwargs.get('info'):
self._info = kwargs.pop('info')
if kwargs:
raise exceptions.ArgumentError("Unknown arguments passed to Column: " + repr(kwargs.keys()))
- primary_key = util.SimpleProperty('_primary_key')
- foreign_keys = util.SimpleProperty('_foreign_keys')
columns = property(lambda self:[self])
def __str__(self):
@@ -483,7 +481,7 @@ class Column(SchemaItem, expression._ColumnClause):
kwarg = []
if self.key != self.name:
kwarg.append('key')
- if self._primary_key:
+ if self.primary_key:
kwarg.append('primary_key')
if not self.nullable:
kwarg.append('nullable')
@@ -624,6 +622,12 @@ class ForeignKey(SchemaItem):
return table.corresponding_column(self.column, False) is not None
+ def get_referent(self, table):
+ """return the column in the given table referenced by this ``ForeignKey``, or
+ None if this ``ForeignKey`` does not reference the given table.
+ """
+ return table.corresponding_column(self.column, False)
+
def _init_column(self):
# ForeignKey inits its remote column as late as possible, so tables can
# be defined without dependencies
diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py
index 3bb4a7598..fbef02857 100644
--- a/lib/sqlalchemy/sql/expression.py
+++ b/lib/sqlalchemy/sql/expression.py
@@ -1379,27 +1379,11 @@ class ColumnElement(ClauseElement, _CompareMixin):
objects using Python expressions. See the ``_CompareMixin``
docstring for more details.
"""
-
- primary_key = property(lambda self:getattr(self, '_primary_key', False),
- doc=\
- """Primary key flag. Indicates if this ``Column`` represents part or
- whole of a primary key for its parent table.
- """)
- foreign_keys = property(lambda self:getattr(self, '_foreign_keys', []),
- doc=\
- """Foreign key accessor. References a list of ``ForeignKey`` objects
- which each represent a foreign key placed on this column's ultimate
- ancestor.
- """)
-
- def _one_fkey(self):
- if self._foreign_keys:
- return list(self._foreign_keys)[0]
- else:
- return None
-
- foreign_key = property(_one_fkey)
+ def __init__(self):
+ self.primary_key = False
+ self.foreign_keys = []
+
def base_columns(self):
if hasattr(self, '_base_columns'):
return self._base_columns
@@ -1869,6 +1853,7 @@ class _Null(ColumnElement):
"""
def __init__(self):
+ ColumnElement.__init__(self)
self.type = sqltypes.NULLTYPE
def _get_from_objects(self, **modifiers):
@@ -2025,6 +2010,7 @@ class _Function(_CalculatedClause, FromClause):
class _Cast(ColumnElement):
def __init__(self, clause, totype, **kwargs):
+ ColumnElement.__init__(self)
if not hasattr(clause, 'label'):
clause = literal(clause)
self.type = sqltypes.to_instance(totype)
@@ -2053,6 +2039,7 @@ class _Cast(ColumnElement):
class _UnaryExpression(ColumnElement):
def __init__(self, element, operator=None, modifier=None, type_=None, negate=None):
+ ColumnElement.__init__(self)
self.operator = operator
self.modifier = modifier
@@ -2096,6 +2083,7 @@ class _BinaryExpression(ColumnElement):
"""Represent an expression that is ``LEFT <operator> RIGHT``."""
def __init__(self, left, right, operator, type_=None, negate=None):
+ ColumnElement.__init__(self)
self.left = _literal_as_text(left).self_group(against=operator)
self.right = _literal_as_text(right).self_group(against=operator)
self.operator = operator
@@ -2186,11 +2174,21 @@ class Join(FromClause):
self.onclause = onclause
self.isouter = isouter
self.__folded_equivalents = None
- self._init_primary_key()
- def _init_primary_key(self):
+ def _export_columns(self):
+ if hasattr(self, '_columns'):
+ return
+ self._columns = ColumnCollection()
+ self._foreign_keys = util.Set()
+
+ columns = list(self._flatten_exportable_columns())
+ self.__init_primary_key(columns)
+ for co in columns:
+ cp = self._proxy_column(co)
+
+ def __init_primary_key(self, columns):
from sqlalchemy import schema
- pkcol = util.Set([c for c in self._flatten_exportable_columns() if c.primary_key])
+ pkcol = util.Set([c for c in columns if c.primary_key])
equivs = {}
def add_equiv(a, b):
@@ -2219,18 +2217,15 @@ class Join(FromClause):
omit.add(p)
p = c
- self.__primary_key = ColumnSet([c for c in self._flatten_exportable_columns() if c.primary_key and c not in omit])
-
+ self._primary_key = ColumnSet(pkcol.difference(omit))
+
def description(self):
return "Join object on %s(%d) and %s(%d)" % (self.left.description, id(self.left), self.right.description, id(self.right))
description = property(description)
- primary_key = property(lambda s:s.__primary_key)
-
def self_group(self, against=None):
return _FromGrouping(self)
-
def _exportable_columns(self):
return [c for c in self.left.columns] + [c for c in self.right.columns]
@@ -2246,7 +2241,6 @@ class Join(FromClause):
self.right = clone(self.right)
self.onclause = clone(self.onclause)
self.__folded_equivalents = None
- self._init_primary_key()
def get_children(self, **kwargs):
return self.left, self.right, self.onclause
@@ -2255,16 +2249,16 @@ class Join(FromClause):
crit = []
constraints = util.Set()
for fk in secondary.foreign_keys:
- if fk.references(primary):
- crit.append(primary.corresponding_column(fk.column) == fk.parent)
+ col = fk.get_referent(primary)
+ if col:
+ crit.append(col == fk.parent)
constraints.add(fk.constraint)
- self.foreignkey = fk.parent
if primary is not secondary:
for fk in primary.foreign_keys:
- if fk.references(secondary):
- crit.append(secondary.corresponding_column(fk.column) == fk.parent)
+ col = fk.get_referent(secondary)
+ if col:
+ crit.append(col == fk.parent)
constraints.add(fk.constraint)
- self.foreignkey = fk.parent
if len(crit) == 0:
raise exceptions.ArgumentError(
"Can't find any foreign key relationships "
@@ -2432,6 +2426,7 @@ class _ColumnElementAdapter(ColumnElement):
"""
def __init__(self, elem):
+ ColumnElement.__init__(self)
self.elem = elem
self.type = getattr(elem, 'type', None)
@@ -2511,6 +2506,8 @@ class _Label(ColumnElement):
proxies = property(lambda s:s.obj.proxies)
base_columns = property(lambda s:s.obj.base_columns)
proxy_set = property(lambda s:s.obj.proxy_set)
+ primary_key = property(lambda s:s.obj.primary_key)
+ foreign_keys = property(lambda s:s.obj.foreign_keys)
def expression_element(self):
return self.obj
@@ -2561,6 +2558,7 @@ class _ColumnClause(ColumnElement):
"""
def __init__(self, text, selectable=None, type_=None, _is_oid=False, is_literal=False):
+ ColumnElement.__init__(self)
self.key = self.name = text
self.table = selectable
self.type = sqltypes.to_instance(type_)
diff --git a/test/profiling/zoomark.py b/test/profiling/zoomark.py
index 7a5a4b7c2..4f1a4d282 100644
--- a/test/profiling/zoomark.py
+++ b/test/profiling/zoomark.py
@@ -274,7 +274,7 @@ class ZooMarkTest(testing.AssertMixin):
assert SDZ['Founded'] == datetime.date(1935, 9, 13)
@testing.supported('postgres')
- @profiling.profiled('multiview', call_range=(2720, 3055), always=True)
+ @profiling.profiled('multiview', call_range=(2400, 2600), always=True)
def test_7_multiview(self):
Zoo = metadata.tables['Zoo']
Animal = metadata.tables['Animal']