]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- another heap of inlinings and now I really have to be done with this
authorMike Bayer <mike_mp@zzzcomputing.com>
Wed, 22 Dec 2010 02:37:52 +0000 (21:37 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Wed, 22 Dec 2010 02:37:52 +0000 (21:37 -0500)
16 files changed:
lib/sqlalchemy/engine/base.py
lib/sqlalchemy/engine/default.py
lib/sqlalchemy/orm/events.py
lib/sqlalchemy/orm/identity.py
lib/sqlalchemy/orm/instrumentation.py
lib/sqlalchemy/orm/mapper.py
lib/sqlalchemy/orm/query.py
lib/sqlalchemy/orm/session.py
lib/sqlalchemy/orm/state.py
lib/sqlalchemy/sql/compiler.py
lib/sqlalchemy/util/_collections.py
test/aaa_profiling/test_compiler.py
test/aaa_profiling/test_orm.py
test/aaa_profiling/test_resultset.py
test/aaa_profiling/test_zoomark.py
test/aaa_profiling/test_zoomark_orm.py

index 1e5285b3552a939e52a0765608a621782b8e5e6a..c1f9905b675f649df6325a0778120447cfb41441 100644 (file)
@@ -25,6 +25,7 @@ from itertools import izip
 from sqlalchemy import exc, schema, util, types, log, interfaces, \
     event, events
 from sqlalchemy.sql import expression
+from sqlalchemy import processors
 
 class Dialect(object):
     """Define the behavior of a specific database and DB-API combination.
@@ -2225,7 +2226,7 @@ class ResultMetaData(object):
             coltype = rec[1]
             
             if dialect.description_encoding:
-                colname = colname.decode(dialect.description_encoding)
+                colname = dialect._description_decoder(colname)
 
             if context.result_map:
                 try:
index 757e42d0323ef7d38c5aab4e105fa2ae68a982a1..9efb5e5f40eba27db866abf790baa1ffab7d00cf 100644 (file)
@@ -15,7 +15,8 @@ as the base class for their own corresponding classes.
 import re, random
 from sqlalchemy.engine import base, reflection
 from sqlalchemy.sql import compiler, expression
-from sqlalchemy import exc, types as sqltypes, util, pool
+from sqlalchemy import exc, types as sqltypes, util, pool, processors
+import codecs
 import weakref
 
 AUTOCOMMIT_REGEXP = re.compile(
@@ -142,6 +143,12 @@ class DefaultDialect(base.Dialect):
                                             self, 
                                             'description_encoding', 
                                             encoding)
+        
+        self._description_decoder = processors.to_unicode_processor_factory(
+                                            self.description_encoding
+                                    )
+        self._encoder = codecs.getencoder(self.encoding)
+        self._decoder = processors.to_unicode_processor_factory(self.encoding)
     
     @util.memoized_property
     def _type_memos(self):
@@ -345,7 +352,7 @@ class DefaultExecutionContext(base.ExecutionContext):
 
         if not dialect.supports_unicode_statements:
             self.unicode_statement = unicode(compiled)
-            self.statement = self.unicode_statement.encode(self.dialect.encoding)
+            self.statement = dialect._encoder(self.unicode_statement)[0]
         else:
             self.statement = self.unicode_statement = unicode(compiled)
             
@@ -434,13 +441,12 @@ class DefaultExecutionContext(base.ExecutionContext):
             for compiled_params in self.compiled_parameters:
                 param = {}
                 if encode:
-                    encoding = dialect.encoding
                     for key in compiled_params:
                         if key in processors:
-                            param[key.encode(encoding)] = \
+                            param[dialect._encoder(key)[0]] = \
                                         processors[key](compiled_params[key])
                         else:
-                            param[key.encode(encoding)] = compiled_params[key]
+                            param[dialect._encoder(key)[0]] = compiled_params[key]
                 else:
                     for key in compiled_params:
                         if key in processors:
@@ -477,7 +483,7 @@ class DefaultExecutionContext(base.ExecutionContext):
                 self.parameters = parameters
             else:
                 self.parameters= [
-                            dict((k.encode(dialect.encoding), d[k]) for k in d)
+                            dict((dialect._encoder(k)[0], d[k]) for k in d)
                             for d in parameters
                         ] or [{}]
         else:
@@ -488,7 +494,7 @@ class DefaultExecutionContext(base.ExecutionContext):
         
         if not dialect.supports_unicode_statements and isinstance(statement, unicode):
             self.unicode_statement = statement
-            self.statement = statement.encode(self.dialect.encoding)
+            self.statement = dialect._encoder(statement)[0]
         else:
             self.statement = self.unicode_statement = statement
             
@@ -538,7 +544,7 @@ class DefaultExecutionContext(base.ExecutionContext):
         conn = self.root_connection
         if isinstance(stmt, unicode) and \
             not self.dialect.supports_unicode_statements:
-            stmt = stmt.encode(self.dialect.encoding)
+            stmt = self.dialect._encoder(stmt)[0]
 
         if self.dialect.positional:
             default_params = self.dialect.execute_sequence_format()
@@ -674,7 +680,7 @@ class DefaultExecutionContext(base.ExecutionContext):
                 if dbtype is not None and (not exclude_types or dbtype not in exclude_types):
                     if translate:
                         key = translate.get(key, key)
-                    inputsizes[key.encode(self.dialect.encoding)] = dbtype
+                    inputsizes[self.dialect._encoder(key)[0]] = dbtype
             try:
                 self.cursor.setinputsizes(**inputsizes)
             except Exception, e:
index 718a18606aec91f2156bf20d375c18c31b8ecb64..6d1e8f713742030dabd21e48019937a585d84151 100644 (file)
@@ -96,6 +96,11 @@ class InstanceEvents(event.Events):
     @classmethod
     def remove(cls, identifier, target, fn):
         raise NotImplementedError("Removal of instance events not yet implemented")
+
+    def on_first_init(self, manager, cls):
+        """Called when the first instance of a particular mapping is called.
+
+        """
         
     def on_init(self, target, args, kwargs):
         """Receive an instance when it's constructor is called.
index f1400a8c6b1d63b34cb9b3f1b0220056851b809b..c55db39dc5917476117bc2ef6e99f4721842bb8b 100644 (file)
@@ -151,7 +151,9 @@ class WeakInstanceDict(IdentityMap):
         self._remove_mutex.acquire()
         try:
             if dict.pop(self, state.key) is not state:
-                raise AssertionError("State %s is not present in this identity map" % state)
+                raise AssertionError(
+                        "State %s is not present in this "
+                        "identity map" % state)
         finally:
             self._remove_mutex.release()
             
@@ -245,15 +247,20 @@ class StrongInstanceDict(IdentityMap):
 
     def add(self, state):
         if state.key in self:
-            if attributes.instance_state(dict.__getitem__(self, state.key)) is not state:
-                raise AssertionError("A conflicting state is already present in the identity map for key %r" % (state.key, ))
+            if attributes.instance_state(dict.__getitem__(self,
+                    state.key)) is not state:
+                raise AssertionError('A conflicting state is already '
+                        'present in the identity map for key %r'
+                        % (state.key, ))
         else:
             dict.__setitem__(self, state.key, state.obj())
             self._manage_incoming_state(state)
         
     def remove(self, state):
-        if attributes.instance_state(dict.pop(self, state.key)) is not state:
-            raise AssertionError("State %s is not present in this identity map" % state)
+        if attributes.instance_state(dict.pop(self, state.key)) \
+            is not state:
+            raise AssertionError('State %s is not present in this '
+                                 'identity map' % state)
         self._manage_removed_state(state)
     
     def discard(self, state):
index dba3a683072742af101b8844b2c71939eb5b74f2..9876dde3f0c4d2b2388063f3df80155e09eeb073 100644 (file)
@@ -166,11 +166,13 @@ class ClassManager(dict):
             self.uninstall_member('__init__')
             self.new_init = None
     
-    def _create_instance_state(self, instance):
+    @util.memoized_property
+    def _state_constructor(self):
+        self.dispatch.on_first_init(self, self.class_)
         if self.mutable_attributes:
-            return state.MutableAttrInstanceState(instance, self)
+            return state.MutableAttrInstanceState
         else:
-            return state.InstanceState(instance, self)
+            return state.InstanceState
         
     def manage(self):
         """Mark this instance as the manager for its class."""
@@ -290,12 +292,12 @@ class ClassManager(dict):
     def new_instance(self, state=None):
         instance = self.class_.__new__(self.class_)
         setattr(instance, self.STATE_ATTR, 
-                    state or self._create_instance_state(instance))
+                    state or self._state_constructor(instance, self))
         return instance
 
     def setup_instance(self, instance, state=None):
         setattr(instance, self.STATE_ATTR, 
-                    state or self._create_instance_state(instance))
+                    state or self._state_constructor(instance, self))
     
     def teardown_instance(self, instance):
         delattr(instance, self.STATE_ATTR)
@@ -318,7 +320,7 @@ class ClassManager(dict):
             return self._subclass_manager(instance.__class__).\
                         _new_state_if_none(instance)
         else:
-            state = self._create_instance_state(instance)
+            state = self._state_constructor(instance, self)
             setattr(instance, self.STATE_ATTR, state)
             return state
     
@@ -421,7 +423,7 @@ class _ClassInstrumentationAdapter(ClassManager):
         self._adapted.initialize_instance_dict(self.class_, instance)
         
         if state is None:
-            state = self._create_instance_state(instance)
+            state = self._state_constructor(instance, self)
             
         # the given instance is assumed to have no state
         self._adapted.install_state(self.class_, instance, state)
index 9bb84e86c385d258da93568b3772d9105754243a..91d512ad0d0ae9aca13c4fb8388c08bec5a35920 100644 (file)
@@ -400,6 +400,7 @@ class Mapper(object):
         if manager.info.get(_INSTRUMENTOR, False):
             return
 
+        event.listen(manager, 'on_first_init', _event_on_first_init, raw=True)
         event.listen(manager, 'on_init', _event_on_init, raw=True)
         event.listen(manager, 'on_resurrect', _event_on_resurrect, raw=True)
         
@@ -2455,17 +2456,22 @@ def _event_on_load(state):
     instrumenting_mapper = state.manager.info[_INSTRUMENTOR]
     if instrumenting_mapper._reconstructor:
         instrumenting_mapper._reconstructor(state.obj())
-        
-def _event_on_init(state, args, kwargs):
-    """Trigger mapper compilation and run init_instance hooks."""
 
-    instrumenting_mapper = state.manager.info.get(_INSTRUMENTOR)
+def _event_on_first_init(manager, cls):
+    """Trigger mapper compilation."""
+
+    instrumenting_mapper = manager.info.get(_INSTRUMENTOR)
     if instrumenting_mapper:
         if _new_mappers:
             configure_mappers()
-        
-        if instrumenting_mapper._set_polymorphic_identity:
-            instrumenting_mapper._set_polymorphic_identity(state)
+    
+def _event_on_init(state, args, kwargs):
+    """Run init_instance hooks."""
+
+    instrumenting_mapper = state.manager.info.get(_INSTRUMENTOR)
+    if instrumenting_mapper and \
+        instrumenting_mapper._set_polymorphic_identity:
+        instrumenting_mapper._set_polymorphic_identity(state)
 
 def _event_on_resurrect(state):
     # re-populate the primary key elements
index 9c0381f755e2dc28d145762050cf0b7ce737c8d2..74678a8d2d27feb4d12f4e4b43f982b0a8382640 100644 (file)
@@ -1721,9 +1721,10 @@ class Query(object):
         return self._execute_and_instances(context)
 
     def _execute_and_instances(self, querycontext):
-        result = self.session.execute(
-                        querycontext.statement, params=self._params,
-                        mapper=self._mapper_zero_or_none())
+        result = self.session.connection(
+                        mapper = self._mapper_zero_or_none(),
+                        clause = querycontext.statement,
+                        close_with_result=True).execute(querycontext.statement, self._params)
         return self.instances(result, querycontext)
     
     @property
@@ -1795,7 +1796,7 @@ class Query(object):
 
         if filtered:
             if single_entity:
-                filter = lambda x: util.unique_list(x, util.IdentitySet)
+                filter = lambda x: util.unique_list(x, id)
             else:
                 filter = util.unique_list
         else:
index 325a94643a777d52bb6cddbcce717fc68cc0c4bf..eba4ace8c0d1b1de47fd3cb45cefc990236ea1ad 100644 (file)
@@ -635,7 +635,8 @@ class Session(object):
 
         self.transaction.prepare()
 
-    def connection(self, mapper=None, clause=None):
+    def connection(self, mapper=None, clause=None, 
+                        close_with_result=False, **kw):
         """Return the active Connection.
 
         Retrieves the ``Connection`` managing the current transaction.  Any
@@ -657,7 +658,8 @@ class Session(object):
           Optional, any ``ClauseElement``
 
         """
-        return self._connection_for_bind(self.get_bind(mapper, clause))
+        return self._connection_for_bind(self.get_bind(mapper, clause, **kw), 
+                                        close_with_result=close_with_result)
 
     def _connection_for_bind(self, engine, **kwargs):
         if self.transaction is not None:
index 909977cc47c6dc704ac248f4bc0884b8083814dc..52cde3a30454c7404d1f98893f197c9b17d072bd 100644 (file)
@@ -52,11 +52,7 @@ class InstanceState(object):
         return bool(self.key)
         
     def detach(self):
-        if self.session_id:
-            try:
-                del self.session_id
-            except AttributeError:
-                pass
+        self.session_id = None
 
     def dispose(self):
         self.detach()
@@ -70,15 +66,8 @@ class InstanceState(object):
             except AssertionError:
                 pass
                 
-        # remove possible cycles
-        self.callables.clear()
-        
-        # inlining of self.dispose()
-        if self.session_id:
-            try:
-                del self.session_id
-            except AttributeError:
-                pass
+        self.callables = {}
+        self.session_id = None
         del self.obj
         
     def obj(self):
@@ -102,14 +91,9 @@ class InstanceState(object):
 
         manager.dispatch.on_init(self, args, kwargs)
             
-        # LESSTHANIDEAL:
-        # adjust for the case where the InstanceState was created before
-        # mapper compilation, and this actually needs to be a MutableAttrInstanceState
-        if manager.mutable_attributes and self.__class__ is not MutableAttrInstanceState:
-            self.__class__ = MutableAttrInstanceState
-            self.obj = weakref.ref(self.obj(), self._cleanup)
-            self.mutable_dict = {}
-            
+        #if manager.mutable_attributes:
+        #    assert self.__class__ is MutableAttrInstanceState
+
         try:
             return manager.original_init(*mixed[1:], **kwargs)
         except:
index 3b43386d5445f0f18c18e10121fc21db46b40a5f..d5540ff835f5f6c445dcbb1a552838de6d63f244 100644 (file)
@@ -324,7 +324,7 @@ class SQLCompiler(engine.Compiled):
         return ""
 
     def visit_grouping(self, grouping, asfrom=False, **kwargs):
-        return "(" + self.process(grouping.element, **kwargs) + ")"
+        return "(" + grouping.element._compiler_dispatch(self, **kwargs) + ")"
 
     def visit_label(self, label, result_map=None, 
                             within_label_clause=False, 
@@ -343,14 +343,14 @@ class SQLCompiler(engine.Compiled):
                         (label.name, (label, label.element, labelname),\
                         label.type)
 
-            return self.process(label.element
+            return label.element._compiler_dispatch(self
                                     within_columns_clause=True,
                                     within_label_clause=True, 
                                     **kw) + \
                         OPERATORS[operators.as_] + \
                         self.preparer.format_label(label, labelname)
         else:
-            return self.process(label.element
+            return label.element._compiler_dispatch(self
                                     within_columns_clause=False, 
                                     **kw)
     
@@ -359,33 +359,35 @@ class SQLCompiler(engine.Compiled):
         if name is None:
             raise exc.CompileError("Cannot compile Column object until "
                                    "it's 'name' is assigned.")
-            
-        if not column.is_literal and isinstance(name, sql._generated_label):
+        
+        is_literal = column.is_literal
+        if not is_literal and isinstance(name, sql._generated_label):
             name = self._truncated_identifier("colident", name)
 
         if result_map is not None:
             result_map[name.lower()] = (name, (column, ), column.type)
         
-        if column.is_literal:
+        if is_literal:
             name = self.escape_literal_column(name)
         else:
             name = self.preparer.quote(name, column.quote)
-
-        if column.table is None or not column.table.named_with_column:
+        
+        table = column.table
+        if table is None or not table.named_with_column:
             return name
         else:
-            if column.table.schema:
+            if table.schema:
                 schema_prefix = self.preparer.quote_schema(
-                                    column.table.schema, 
-                                    column.table.quote_schema) + '.'
+                                    table.schema, 
+                                    table.quote_schema) + '.'
             else:
                 schema_prefix = ''
-            tablename = column.table.name
+            tablename = table.name
             if isinstance(tablename, sql._generated_label):
                 tablename = self._truncated_identifier("alias", tablename)
             
             return schema_prefix + \
-                    self.preparer.quote(tablename, column.table.quote) + \
+                    self.preparer.quote(tablename, table.quote) + \
                     "." + name
 
     def escape_literal_column(self, text):
@@ -435,31 +437,33 @@ class SQLCompiler(engine.Compiled):
             sep = OPERATORS[clauselist.operator]
         return sep.join(
                     s for s in 
-                    (self.process(c, **kwargs) 
+                    (c._compiler_dispatch(self, **kwargs) 
                     for c in clauselist.clauses)
                     if s is not None)
 
     def visit_case(self, clause, **kwargs):
         x = "CASE "
         if clause.value is not None:
-            x += self.process(clause.value, **kwargs) + " "
+            x += clause.value._compiler_dispatch(self, **kwargs) + " "
         for cond, result in clause.whens:
-            x += "WHEN " + self.process(cond, **kwargs) + \
-                            " THEN " + self.process(result, **kwargs) + " "
+            x += "WHEN " + cond._compiler_dispatch(self, **kwargs) + \
+                            " THEN " + \
+                            result._compiler_dispatch(self, **kwargs) + " "
         if clause.else_ is not None:
-            x += "ELSE " + self.process(clause.else_, **kwargs) + " "
+            x += "ELSE " + clause.else_._compiler_dispatch(self, **kwargs) + \
+                                        " "
         x += "END"
         return x
 
     def visit_cast(self, cast, **kwargs):
         return "CAST(%s AS %s)" % \
-                    (self.process(cast.clause, **kwargs),
-                    self.process(cast.typeclause, **kwargs))
+                    (cast.clause._compiler_dispatch(self, **kwargs),
+                    cast.typeclause._compiler_dispatch(self, **kwargs))
 
     def visit_extract(self, extract, **kwargs):
         field = self.extract_map.get(extract.field, extract.field)
         return "EXTRACT(%s FROM %s)" % (field, 
-                            self.process(extract.expr, **kwargs))
+                            extract.expr._compiler_dispatch(self, **kwargs))
 
     def visit_function(self, func, result_map=None, **kwargs):
         if result_map is not None:
@@ -474,7 +478,7 @@ class SQLCompiler(engine.Compiled):
                             {'expr':self.function_argspec(func, **kwargs)}
 
     def function_argspec(self, func, **kwargs):
-        return self.process(func.clause_expr, **kwargs)
+        return func.clause_expr._compiler_dispatch(self, **kwargs)
 
     def visit_compound_select(self, cs, asfrom=False, 
                             parens=True, compound_index=1, **kwargs):
@@ -484,12 +488,14 @@ class SQLCompiler(engine.Compiled):
         keyword = self.compound_keywords.get(cs.keyword)
         
         text = (" " + keyword + " ").join(
-                            (self.process(c, asfrom=asfrom, parens=False, 
+                            (c._compiler_dispatch(self, 
+                                            asfrom=asfrom, parens=False, 
                                             compound_index=i, **kwargs)
                             for i, c in enumerate(cs.selects))
                         )
                         
-        group_by = self.process(cs._group_by_clause, asfrom=asfrom, **kwargs)
+        group_by = cs._group_by_clause._compiler_dispatch(
+                                self, asfrom=asfrom, **kwargs)
         if group_by:
             text += " GROUP BY " + group_by
 
@@ -504,7 +510,7 @@ class SQLCompiler(engine.Compiled):
             return text
 
     def visit_unary(self, unary, **kw):
-        s = self.process(unary.element, **kw)
+        s = unary.element._compiler_dispatch(self, **kw)
         if unary.operator:
             s = OPERATORS[unary.operator] + s
         if unary.modifier:
@@ -520,17 +526,18 @@ class SQLCompiler(engine.Compiled):
             
         return self._operator_dispatch(binary.operator,
                     binary,
-                    lambda opstr: self.process(binary.left, **kw) + 
+                    lambda opstr: binary.left._compiler_dispatch(self, **kw) + 
                                         opstr + 
-                                    self.process(binary.right, **kw),
+                                    binary.right._compiler_dispatch(
+                                            self, **kw),
                     **kw
         )
 
     def visit_like_op(self, binary, **kw):
         escape = binary.modifiers.get("escape", None)
         return '%s LIKE %s' % (
-                                    self.process(binary.left, **kw), 
-                                    self.process(binary.right, **kw)) \
+                            binary.left._compiler_dispatch(self, **kw), 
+                            binary.right._compiler_dispatch(self, **kw)) \
             + (escape and 
                     (' ESCAPE ' + self.render_literal_value(escape, None))
                     or '')
@@ -538,8 +545,8 @@ class SQLCompiler(engine.Compiled):
     def visit_notlike_op(self, binary, **kw):
         escape = binary.modifiers.get("escape", None)
         return '%s NOT LIKE %s' % (
-                                    self.process(binary.left, **kw), 
-                                    self.process(binary.right, **kw)) \
+                            binary.left._compiler_dispatch(self, **kw), 
+                            binary.right._compiler_dispatch(self, **kw)) \
             + (escape and 
                     (' ESCAPE ' + self.render_literal_value(escape, None))
                     or '')
@@ -547,8 +554,8 @@ class SQLCompiler(engine.Compiled):
     def visit_ilike_op(self, binary, **kw):
         escape = binary.modifiers.get("escape", None)
         return 'lower(%s) LIKE lower(%s)' % (
-                                        self.process(binary.left, **kw), 
-                                        self.process(binary.right, **kw)) \
+                            binary.left._compiler_dispatch(self, **kw), 
+                            binary.right._compiler_dispatch(self, **kw)) \
             + (escape and 
                     (' ESCAPE ' + self.render_literal_value(escape, None))
                     or '')
@@ -556,8 +563,8 @@ class SQLCompiler(engine.Compiled):
     def visit_notilike_op(self, binary, **kw):
         escape = binary.modifiers.get("escape", None)
         return 'lower(%s) NOT LIKE lower(%s)' % (
-                                    self.process(binary.left, **kw), 
-                                    self.process(binary.right, **kw)) \
+                            binary.left._compiler_dispatch(self, **kw), 
+                            binary.right._compiler_dispatch(self, **kw)) \
             + (escape and 
                     (' ESCAPE ' + self.render_literal_value(escape, None))
                     or '')
@@ -678,7 +685,8 @@ class SQLCompiler(engine.Compiled):
     def bindparam_string(self, name):
         if self.positional:
             self.positiontup.append(name)
-            return self.bindtemplate % {'name':name, 'position':len(self.positiontup)}
+            return self.bindtemplate % {
+                        'name':name, 'position':len(self.positiontup)}
         else:
             return self.bindtemplate % {'name':name}
 
@@ -693,7 +701,8 @@ class SQLCompiler(engine.Compiled):
         if ashint:
             return self.preparer.format_alias(alias, alias_name)
         elif asfrom:
-            ret = self.process(alias.original, asfrom=True, **kwargs) + \
+            ret = alias.original._compiler_dispatch(self, 
+                                asfrom=True, **kwargs) + \
                                 " AS " + \
                     self.preparer.format_alias(alias, alias_name)
                     
@@ -704,7 +713,7 @@ class SQLCompiler(engine.Compiled):
             
             return ret
         else:
-            return self.process(alias.original, **kwargs)
+            return alias.original._compiler_dispatch(self, **kwargs)
 
     def label_select_column(self, select, column, asfrom):
         """label columns present in a select()."""
@@ -712,10 +721,10 @@ class SQLCompiler(engine.Compiled):
         if isinstance(column, sql._Label):
             return column
 
-        if select is not None and select.use_labels and column._label:
+        elif select is not None and select.use_labels and column._label:
             return _CompileLabel(column, column._label)
 
-        if \
+        elif \
             asfrom and \
             isinstance(column, sql.ColumnClause) and \
             not column.is_literal and \
@@ -765,10 +774,10 @@ class SQLCompiler(engine.Compiled):
         # the actual list of columns to print in the SELECT column list.
         inner_columns = [
             c for c in [
-                self.process(
-                    self.label_select_column(select, co, asfrom=asfrom), 
-                    within_columns_clause=True,
-                    **column_clause_args) 
+                self.label_select_column(select, co, asfrom=asfrom).\
+                    _compiler_dispatch(self,
+                        within_columns_clause=True,
+                        **column_clause_args) 
                 for co in util.unique_list(select.inner_columns)
             ]
             if c is not None
@@ -779,7 +788,9 @@ class SQLCompiler(engine.Compiled):
         if select._hints:
             byfrom = dict([
                             (from_, hinttext % {
-                                'name':self.process(from_, ashint=True)}) 
+                                'name':from_._compiler_dispatch(
+                                    self, ashint=True)
+                            }) 
                             for (from_, dialect), hinttext in 
                             select._hints.iteritems() 
                             if dialect in ('*', self.dialect.name)
@@ -790,7 +801,7 @@ class SQLCompiler(engine.Compiled):
                 
         if select._prefixes:
             text += " ".join(
-                            self.process(x, **kwargs) 
+                            x._compiler_dispatch(self, **kwargs) 
                             for x in select._prefixes) + " "
         text += self.get_select_precolumns(select)
         text += ', '.join(inner_columns)
@@ -799,29 +810,30 @@ class SQLCompiler(engine.Compiled):
             text += " \nFROM "
             
             if select._hints:
-                text += ', '.join([self.process(f, 
+                text += ', '.join([f._compiler_dispatch(self, 
                                     asfrom=True, fromhints=byfrom, 
                                     **kwargs) 
                                 for f in froms])
             else:
-                text += ', '.join([self.process(f, 
+                text += ', '.join([f._compiler_dispatch(self, 
                                     asfrom=True, **kwargs) 
                                 for f in froms])
         else:
             text += self.default_from()
 
         if select._whereclause is not None:
-            t = self.process(select._whereclause, **kwargs)
+            t = select._whereclause._compiler_dispatch(self, **kwargs)
             if t:
                 text += " \nWHERE " + t
 
         if select._group_by_clause.clauses:
-            group_by = self.process(select._group_by_clause, **kwargs)
+            group_by = select._group_by_clause._compiler_dispatch(
+                                        self, **kwargs)
             if group_by:
                 text += " GROUP BY " + group_by
 
         if select._having is not None:
-            t = self.process(select._having, **kwargs)
+            t = select._having._compiler_dispatch(self, **kwargs)
             if t:
                 text += " \nHAVING " + t
 
@@ -847,7 +859,7 @@ class SQLCompiler(engine.Compiled):
         return select._distinct and "DISTINCT " or ""
 
     def order_by_clause(self, select, **kw):
-        order_by = self.process(select._order_by_clause, **kw)
+        order_by = select._order_by_clause._compiler_dispatch(self, **kw)
         if order_by:
             return " ORDER BY " + order_by
         else:
@@ -888,10 +900,13 @@ class SQLCompiler(engine.Compiled):
             return ""
 
     def visit_join(self, join, asfrom=False, **kwargs):
-        return (self.process(join.left, asfrom=True, **kwargs) + \
-                (join.isouter and " LEFT OUTER JOIN " or " JOIN ") + \
-            self.process(join.right, asfrom=True, **kwargs) + " ON " + \
-            self.process(join.onclause, **kwargs))
+        return (
+            join.left._compiler_dispatch(self, asfrom=True, **kwargs) + 
+            (join.isouter and " LEFT OUTER JOIN " or " JOIN ") + 
+            join.right._compiler_dispatch(self, asfrom=True, **kwargs) + 
+            " ON " + 
+            join.onclause._compiler_dispatch(self, **kwargs)
+        )
 
     def visit_sequence(self, seq):
         return None
index 4ab52c3d6fecc3fb3124f407fdb0a8f797cf240b..2735f5e80c575b32b1dfd179f434b76011072283 100644 (file)
@@ -583,9 +583,16 @@ column_dict = dict
 ordered_column_set = OrderedSet
 populate_column_dict = PopulateDict
 
-def unique_list(seq, compare_with=set):
-    seen = compare_with()
-    return [x for x in seq if x not in seen and not seen.add(x)]    
+def unique_list(seq, hashfunc=None):
+    seen = {}
+    if not hashfunc:
+        return [x for x in seq 
+                if x not in seen 
+                and not seen.__setitem__(x, True)]
+    else:
+        return [x for x in seq 
+                if hashfunc(x) not in seen 
+                and not seen.__setitem__(hashfunc(x), True)]
 
 class UniqueAppender(object):
     """Appends items to a collection ensuring uniqueness.
@@ -596,19 +603,19 @@ class UniqueAppender(object):
 
     def __init__(self, data, via=None):
         self.data = data
-        self._unique = IdentitySet()
+        self._unique = {}
         if via:
             self._data_appender = getattr(data, via)
         elif hasattr(data, 'append'):
             self._data_appender = data.append
         elif hasattr(data, 'add'):
-            # TODO: we think its a set here.  bypass unneeded uniquing logic ?
             self._data_appender = data.add
 
     def append(self, item):
-        if item not in self._unique:
+        id_ = id(item)
+        if id_ not in self._unique:
             self._data_appender(item)
-            self._unique.add(item)
+            self._unique[id_] = True
 
     def __iter__(self):
         return iter(self.data)
index c0f8a151f647aa58fc3088a1c9410f442ebe210b..5d32ee58120c5349693a8ff65ceb564e894e8f62 100644 (file)
@@ -1,6 +1,6 @@
 from sqlalchemy import *
 from test.lib import *
-
+from sqlalchemy.engine import default
 
 class CompileTest(TestBase, AssertsExecutionResults):
     @classmethod
@@ -29,23 +29,25 @@ class CompileTest(TestBase, AssertsExecutionResults):
         from sqlalchemy import types
         for t in types._type_map.values():
             t._type_affinity
-            
-    @profiling.function_call_count(69, {'2.4': 44, 
+        
+        cls.dialect = default.DefaultDialect()
+        
+    @profiling.function_call_count(58, {'2.4': 44, 
                                             '3.0':77, '3.1':77})
     def test_insert(self):
-        t1.insert().compile()
+        t1.insert().compile(dialect=self.dialect)
 
-    @profiling.function_call_count(69, {'2.4': 45})
+    @profiling.function_call_count(49, {'2.4': 45})
     def test_update(self):
-        t1.update().compile()
+        t1.update().compile(dialect=self.dialect)
 
-    @profiling.function_call_count(129, {'2.4': 81, '3':132})
+    @profiling.function_call_count(110, {'2.4': 81, '3':132})
     def test_update_whereclause(self):
-        t1.update().where(t1.c.c2==12).compile()
+        t1.update().where(t1.c.c2==12).compile(dialect=self.dialect)
 
-    @profiling.function_call_count(178, versions={'2.4':105, 
+    @profiling.function_call_count(148, versions={'2.4':105, 
                                                 '3.0':208, '3.1':208})
     def test_select(self):
         s = select([t1], t1.c.c2==t2.c.c1)
-        s.compile()
+        s.compile(dialect=self.dialect)
 
index 0881ab183bd809f7ad9561cbbb1168f42dd04d75..9f03b9cdddeaed13b7da855370c706ba341de46d 100644 (file)
@@ -53,7 +53,7 @@ class MergeTest(_base.MappedTest):
         # down from 185 on this this is a small slice of a usually
         # bigger operation so using a small variance
 
-        @profiling.function_call_count(86, variance=0.05,
+        @profiling.function_call_count(80, variance=0.05,
                 versions={'2.4': 64, '2.5':94, '3': 89})
         def go():
             return sess2.merge(p1, load=False)
@@ -80,8 +80,8 @@ class MergeTest(_base.MappedTest):
         # (py2.6)
 
         @profiling.function_call_count(1067, 
-                                versions={'2.5':1191, '2.6':1191,
-                                        '2.6+cextension':1194
+                                versions={'2.5':1050, '2.6':1050,
+                                        '2.6+cextension':1041
                                         '2.4': 763}
                             )
         def go():
@@ -160,7 +160,7 @@ class LoadManyToOneFromIdentityTest(_base.MappedTest):
         parents = sess.query(Parent).all()
         
         
-        @profiling.function_call_count(138289, variance=.2)
+        @profiling.function_call_count(108019, variance=.2)
         def go():
             for p in parents:
                 p.child
index d7f2beeb4c77fd4374aacab9d120eeb88975a8aa..e46411bdb1c04d7e75484f815b8d673d72dc4acb 100644 (file)
@@ -34,15 +34,16 @@ class ResultSetTest(TestBase, AssertsExecutionResults):
         metadata.drop_all()
 
     @profiling.function_call_count(14416, versions={'2.4': 13214,
-                                   '2.6+cextension': 410, '2.7+cextension':401})
+                                   '2.6+cextension': 385,
+                                   '2.7+cextension':401})
     def test_string(self):
         [tuple(row) for row in t.select().execute().fetchall()]
 
     # sqlite3 returns native unicode.  so shouldn't be an increase here.
 
     @profiling.function_call_count(14396, versions={'2.4': 13214,
-                                   '2.6+cextension': 409
-                                   '2.7+cextension':409})
+                                   '2.6+cextension': 385
+                                   '2.7+cextension':385})
     def test_unicode(self):
         [tuple(row) for row in t2.select().execute().fetchall()]
 
index 5a93bda9a9b47739ffb908e721cfb54a1b22877c..c4cffa87ad4dcb0886c3036974269824c7c9adfb 100644 (file)
@@ -361,7 +361,7 @@ class ZooMarkTest(TestBase):
     def test_profile_1_create_tables(self):
         self.test_baseline_1_create_tables()
 
-    @profiling.function_call_count(5045, {'2.6':5371, '2.4': 3650})
+    @profiling.function_call_count(5045, {'2.6':5099, '2.4': 3650})
     def test_profile_1a_populate(self):
         self.test_baseline_1a_populate()
 
@@ -369,29 +369,31 @@ class ZooMarkTest(TestBase):
     def test_profile_2_insert(self):
         self.test_baseline_2_insert()
 
-    @profiling.function_call_count(3886, {'2.4': 2158})
+    @profiling.function_call_count(3596, {'2.4': 2158})
     def test_profile_3_properties(self):
         self.test_baseline_3_properties()
 
-    @profiling.function_call_count(13341, {'2.4': 7963, '2.6+cextension'
+    @profiling.function_call_count(11624, {'2.4': 7963, '2.6+cextension'
                                    : 12447, '2.7+cextension': 12447},
                                    variance=0.10)
     def test_profile_4_expressions(self):
         self.test_baseline_4_expressions()
 
-    @profiling.function_call_count(1311, {'2.4': 904, '2.6+cextension'
-                                   : 1226, '2.7+cextension': 1226},
+    @profiling.function_call_count(1059, {'2.4': 904, '2.6+cextension'
+                                   : 1027, '2.7+cextension': 1027},
                                    variance=0.10)
     def test_profile_5_aggregates(self):
         self.test_baseline_5_aggregates()
 
-    @profiling.function_call_count(1904, {'2.4': 1118})
+    @profiling.function_call_count(1788, {'2.4': 1118})
     def test_profile_6_editing(self):
         self.test_baseline_6_editing()
 
-    @profiling.function_call_count(2598, {'2.4': 1673, 
-                                            '2.7+cextension':2431, 
-                                            '2.6+cextension': 2502})
+    @profiling.function_call_count(2252, {'2.4': 1673, 
+                                            '2.6':2412,
+                                            '2.7':2412,
+                                            '2.7+cextension':2252, 
+                                            '2.6+cextension': 2252})
     def test_profile_7_multiview(self):
         self.test_baseline_7_multiview()
 
index 615c7472b0b97cdc751a42f62025f4cd6be93edc..c4dd0ae9fb22484f6413644c319667c4040bfa20 100644 (file)
@@ -335,7 +335,7 @@ class ZooMarkTest(TestBase):
     def test_profile_1_create_tables(self):
         self.test_baseline_1_create_tables()
 
-    @profiling.function_call_count(6347)
+    @profiling.function_call_count(6324, {'2.7+cextension':5992, '2.6+cextension':5992})
     def test_profile_1a_populate(self):
         self.test_baseline_1a_populate()
 
@@ -346,17 +346,17 @@ class ZooMarkTest(TestBase):
     # this number...
 
     @profiling.function_call_count(6783, {
-        '2.6': 7094,
-        '2.7': 6250,
-        '2.7+cextension': 6170,
-        '2.6+cextension': 7184,
+        '2.6': 6058,
+        '2.7': 5922,
+        '2.7+cextension': 5714,
+        '2.6+cextension': 6058,
         })
     def test_profile_3_properties(self):
         self.test_baseline_3_properties()
 
     # and this number go down slightly when using the C extensions
 
-    @profiling.function_call_count(19335, {'2.6': 22775, '2.7':20299})
+    @profiling.function_call_count(17698, {'2.7+cextension':17698, '2.6': 18943, '2.7':19110})
     def test_profile_4_expressions(self):
         self.test_baseline_4_expressions()
 
@@ -366,7 +366,7 @@ class ZooMarkTest(TestBase):
     def test_profile_5_aggregates(self):
         self.test_baseline_5_aggregates()
 
-    @profiling.function_call_count(2550)
+    @profiling.function_call_count(2417)
     def test_profile_6_editing(self):
         self.test_baseline_6_editing()