From 31b32896e81335108f77cdc44954b3c78c5f62a8 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sun, 18 Nov 2007 06:51:17 +0000 Subject: [PATCH] cut down a good deal of Join construction overhead --- lib/sqlalchemy/ext/activemapper.py | 4 +- lib/sqlalchemy/schema.py | 14 +++--- lib/sqlalchemy/sql/expression.py | 68 +++++++++++++++--------------- test/profiling/zoomark.py | 2 +- 4 files changed, 45 insertions(+), 43 deletions(-) diff --git a/lib/sqlalchemy/ext/activemapper.py b/lib/sqlalchemy/ext/activemapper.py index 2a39fe970a..b28ada0af8 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 856822df75..21e36fe6f8 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 3bb4a75981..fbef02857d 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 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 7a5a4b7c27..4f1a4d2820 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'] -- 2.47.2