]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Removed the 'properties' attribute of the
authorMike Bayer <mike_mp@zzzcomputing.com>
Sun, 9 Nov 2008 19:32:25 +0000 (19:32 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sun, 9 Nov 2008 19:32:25 +0000 (19:32 +0000)
Connection object, Connection.info should be used.
- Method consoliation in Connection, ExecutionContext

CHANGES
lib/sqlalchemy/engine/base.py
lib/sqlalchemy/engine/default.py
lib/sqlalchemy/sql/compiler.py
lib/sqlalchemy/sql/expression.py
test/profiling/zoomark.py
test/profiling/zoomark_orm.py
test/sql/constraints.py
test/testlib/testing.py

diff --git a/CHANGES b/CHANGES
index c59eb826ae76ee59b79a7aa5e3b76974f4fe5cf3..d71fd226eae94336dcbd670826a4331902387608 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -29,6 +29,10 @@ CHANGES
     - Query.get() returns a more informative
       error message when executed against multiple entities.
       [ticket:1220]
+
+- sql
+    - Removed the 'properties' attribute of the 
+      Connection object, Connection.info should be used.
       
 - access
     - Added support for Currency type.
index b810f5f67b57c18e58c64504e869e1587043ffce..832903a735b8c3ebf8f2fca380de1c5bd2c1fcda 100644 (file)
@@ -324,7 +324,7 @@ class ExecutionContext(object):
 
         raise NotImplementedError()
 
-    def pre_execution(self):
+    def pre_exec(self):
         """Called before an execution of a compiled statement.
 
         If a compiled statement was passed to this ExecutionContext,
@@ -334,7 +334,7 @@ class ExecutionContext(object):
 
         raise NotImplementedError()
 
-    def post_execution(self):
+    def post_exec(self):
         """Called after the execution of a compiled statement.
 
         If a compiled statement was passed to this ExecutionContext,
@@ -352,11 +352,6 @@ class ExecutionContext(object):
 
         raise NotImplementedError()
 
-    def should_autocommit_compiled(self, compiled):
-        """return True if the given Compiled object refers to a "committable" statement."""
-
-        raise NotImplementedError()
-
     def should_autocommit_text(self, statement):
         """Parse the given textual statement and return True if it refers to a "committable" statement"""
 
@@ -425,6 +420,7 @@ class Compiled(object):
 
         bind
           Optional Engine or Connection to compile this statement against.
+          
         """
         self.dialect = dialect
         self.statement = statement
@@ -502,6 +498,7 @@ class Connection(Connectable):
     a begin method to return Transaction objects.
 
     The Connection object is **not** threadsafe.
+    
     """
 
     def __init__(self, engine, connection=None, close_with_result=False,
@@ -511,6 +508,7 @@ class Connection(Connectable):
         Connection objects are typically constructed by an
         [sqlalchemy.engine#Engine], see the ``connect()`` and
         ``contextual_connect()`` methods of Engine.
+        
         """
 
         self.engine = engine
@@ -528,6 +526,7 @@ class Connection(Connectable):
 
         This is used to execute "sub" statements within a single execution,
         usually an INSERT statement.
+        
         """
         return self.engine.Connection(self.engine, self.__connection, _branch=True)
 
@@ -568,8 +567,8 @@ class Connection(Connectable):
     def should_close_with_result(self):
         """Indicates if this Connection should be closed when a corresponding
         ResultProxy is closed; this is essentially an auto-release mode.
+        
         """
-
         return self.__close_with_result
 
     @property
@@ -577,16 +576,14 @@ class Connection(Connectable):
         """A collection of per-DB-API connection instance properties."""
         return self.connection.info
 
-    properties = property(info, doc="""An alias for the .info collection, will be removed in 0.5.""")
-
     def connect(self):
         """Returns self.
 
         This ``Connectable`` interface method returns self, allowing
         Connections to be used interchangably with Engines in most
         situations that require a bind.
-        """
 
+        """
         return self
 
     def contextual_connect(self, **kwargs):
@@ -595,8 +592,8 @@ class Connection(Connectable):
         This ``Connectable`` interface method returns self, allowing
         Connections to be used interchangably with Engines in most
         situations that require a bind.
-        """
 
+        """
         return self
 
     def invalidate(self, exception=None):
@@ -636,8 +633,8 @@ class Connection(Connectable):
         [sqlalchemy.interfaces#PoolListener] for a mechanism to modify
         connection state when connections leave and return to their
         connection pool.
-        """
 
+        """
         self.__connection.detach()
 
     def begin(self):
@@ -648,8 +645,8 @@ class Connection(Connectable):
         outermost transaction may ``commit``.  Calls to ``commit`` on
         inner transactions are ignored.  Any transaction in the
         hierarchy may ``rollback``, however.
-        """
 
+        """
         if self.__transaction is None:
             self.__transaction = RootTransaction(self)
         else:
@@ -774,20 +771,6 @@ class Connection(Connectable):
             self.engine.dialect.do_commit_twophase(self, xid, is_prepared)
         self.__transaction = None
 
-    def _autocommit(self, context):
-        """Possibly issue a commit.
-
-        When no Transaction is present, this is called after statement
-        execution to provide "autocommit" behavior.  Dialects may
-        inspect the statement to determine if a commit is actually
-        required.
-        """
-
-        # TODO: have the dialect determine if autocommit can be set on
-        # the connection directly without this extra step
-        if not self.in_transaction() and context.should_autocommit:
-            self._commit_impl()
-
     def _autorollback(self):
         if not self.in_transaction():
             self._rollback_impl()
@@ -824,16 +807,6 @@ class Connection(Connectable):
         else:
             raise exc.InvalidRequestError("Unexecutable object type: " + str(type(object)))
 
-    def _execute_default(self, default, multiparams=None, params=None):
-        return self.engine.dialect.defaultrunner(self.__create_execution_context()).traverse_single(default)
-
-    def _execute_text(self, statement, multiparams, params):
-        parameters = self.__distill_params(multiparams, params)
-        context = self.__create_execution_context(statement=statement, parameters=parameters)
-        self.__execute_raw(context)
-        self._autocommit(context)
-        return context.get_result_proxy()
-
     def __distill_params(self, multiparams, params):
         """given arguments from the calling form *multiparams, **params, return a list
         of bind parameter structures, usually a list of dictionaries.
@@ -847,15 +820,16 @@ class Connection(Connectable):
             else:
                 return [{}]
         elif len(multiparams) == 1:
-            if isinstance(multiparams[0], (list, tuple)):
-                if not multiparams[0] or isinstance(multiparams[0][0], (list, tuple, dict)):
-                    return multiparams[0]
+            zero = multiparams[0]
+            if isinstance(zero, (list, tuple)):
+                if not zero or isinstance(zero[0], (list, tuple, dict)):
+                    return zero
                 else:
-                    return [multiparams[0]]
-            elif isinstance(multiparams[0], dict):
-                return [multiparams[0]]
+                    return [zero]
+            elif isinstance(zero, dict):
+                return [zero]
             else:
-                return [[multiparams[0]]]
+                return [[zero]]
         else:
             if isinstance(multiparams[0], (list, tuple, dict)):
                 return multiparams
@@ -865,35 +839,49 @@ class Connection(Connectable):
     def _execute_function(self, func, multiparams, params):
         return self.execute_clauseelement(func.select(), multiparams, params)
 
+    def _execute_default(self, default, multiparams=None, params=None):
+        return self.engine.dialect.defaultrunner(self.__create_execution_context()).traverse_single(default)
+
     def execute_clauseelement(self, elem, multiparams=None, params=None):
         params = self.__distill_params(multiparams, params)
         if params:
             keys = params[0].keys()
         else:
             keys = None
-        return self._execute_compiled(elem.compile(dialect=self.dialect, column_keys=keys, inline=len(params) > 1), distilled_params=params)
 
-    def _execute_compiled(self, compiled, multiparams=None, params=None, distilled_params=None):
-        """Execute a sql.Compiled object."""
-        if not compiled.can_execute:
-            raise exc.ArgumentError("Not an executable clause: %s" % (str(compiled)))
+        context = self.__create_execution_context(
+                        compiled=elem.compile(dialect=self.dialect, column_keys=keys, inline=len(params) > 1), 
+                        parameters=params
+                    )
+        return self.__execute_context(context)
 
-        if distilled_params is None:
-            distilled_params = self.__distill_params(multiparams, params)
-        context = self.__create_execution_context(compiled=compiled, parameters=distilled_params)
+    def _execute_compiled(self, compiled, multiparams=None, params=None):
+        """Execute a sql.Compiled object."""
 
-        context.pre_execution()
-        self.__execute_raw(context)
-        context.post_execution()
-        self._autocommit(context)
-        return context.get_result_proxy()
+        context = self.__create_execution_context(
+                    compiled=compiled, 
+                    parameters=self.__distill_params(multiparams, params)
+                )
+        return self.__execute_context(context)
 
-    def __execute_raw(self, context):
+    def _execute_text(self, statement, multiparams, params):
+        parameters = self.__distill_params(multiparams, params)
+        context = self.__create_execution_context(statement=statement, parameters=parameters)
+        return self.__execute_context(context)
+    
+    def __execute_context(self, context):
+        if context.compiled:
+            context.pre_exec()
         if context.executemany:
             self._cursor_executemany(context.cursor, context.statement, context.parameters, context=context)
         else:
             self._cursor_execute(context.cursor, context.statement, context.parameters[0], context=context)
-
+        if context.compiled:
+            context.post_exec()
+        if context.should_autocommit and not self.in_transaction():
+            self._commit_impl()
+        return context.get_result_proxy()
+        
     def _execute_ddl(self, ddl, params, multiparams):
         if params:
             schema_item, params = params[0], params[1:]
index ec15313e4251bf67e9a3eb5b24d09053a60ddce6..251cf8b2c20c93f4e461272b799db84738709710 100644 (file)
@@ -136,6 +136,9 @@ class DefaultExecutionContext(base.ExecutionContext):
             # compiled clauseelement.  process bind params, process table defaults,
             # track collections used by ResultProxy to target and process results
 
+            if not compiled.can_execute:
+                raise exc.ArgumentError("Not an executable clause: %s" % compiled)
+
             self.processors = dict(
                 (key, value) for key, value in
                 ( (compiled.bind_names[bindparam],
@@ -152,10 +155,9 @@ class DefaultExecutionContext(base.ExecutionContext):
 
             self.isinsert = compiled.isinsert
             self.isupdate = compiled.isupdate
+            self.should_autocommit = compiled.statement._autocommit
             if isinstance(compiled.statement, expression._TextClause):
-                self.should_autocommit = compiled.statement._autocommit or self.should_autocommit_text(self.statement)
-            else:
-                self.should_autocommit = getattr(compiled.statement, '_autocommit', False) or self.should_autocommit_compiled(compiled)
+                self.should_autocommit = self.should_autocommit or self.should_autocommit_text(self.statement)
 
             if not parameters:
                 self.compiled_parameters = [compiled.construct_params()]
@@ -248,21 +250,12 @@ class DefaultExecutionContext(base.ExecutionContext):
                 parameters.append(param)
         return parameters
 
-    def should_autocommit_compiled(self, compiled):
-        return isinstance(compiled.statement, expression._UpdateBase)
-
     def should_autocommit_text(self, statement):
         return AUTOCOMMIT_REGEXP.match(statement)
 
     def create_cursor(self):
         return self._connection.connection.cursor()
 
-    def pre_execution(self):
-        self.pre_exec()
-
-    def post_execution(self):
-        self.post_exec()
-
     def pre_exec(self):
         pass
 
index 80a4d7f52a964ae09abe15daed902d5368971197..b83c9ab20979777e1bc4f73b4bc12f67aeaecceb 100644 (file)
@@ -134,6 +134,10 @@ class DefaultCompiler(engine.Compiled):
     operators = OPERATORS
     functions = FUNCTIONS
 
+    # if we are insert/update/delete. 
+    # set to true when we visit an INSERT, UPDATE or DELETE
+    isdelete = isinsert = isupdate = False
+
     def __init__(self, dialect, statement, column_keys=None, inline=False, **kwargs):
         """Construct a new ``DefaultCompiler`` object.
 
@@ -148,10 +152,7 @@ class DefaultCompiler(engine.Compiled):
           statement.
 
         """
-        super(DefaultCompiler, self).__init__(dialect, statement, column_keys, **kwargs)
-
-        # if we are insert/update/delete.  set to true when we visit an INSERT, UPDATE or DELETE
-        self.isdelete = self.isinsert = self.isupdate = False
+        engine.Compiled.__init__(self, dialect, statement, column_keys, **kwargs)
 
         # compile INSERT/UPDATE defaults/sequences inlined (no pre-execute)
         self.inline = inline or getattr(statement, 'inline', False)
index 2fa3fc36f939d0f8503b7fe8a700bd5698ce3cb2..9b847c78b497973c389a54be3ccff756137c4087 100644 (file)
@@ -2551,6 +2551,8 @@ class Alias(FromClause):
             baseselectable = baseselectable.element
         self.original = baseselectable
         self.supports_execution = baseselectable.supports_execution
+        if self.supports_execution:
+            self._autocommit = baseselectable._autocommit
         self.element = selectable
         if alias is None:
             if self.original.named_with_column:
@@ -3453,7 +3455,8 @@ class _UpdateBase(ClauseElement):
     """Form the base for ``INSERT``, ``UPDATE``, and ``DELETE`` statements."""
 
     supports_execution = True
-
+    _autocommit = True
+    
     def _generate(self):
         s = self.__class__.__new__(self.__class__)
         s.__dict__ = self.__dict__.copy()
@@ -3606,6 +3609,7 @@ class Delete(_UpdateBase):
 
 class _IdentifiedClause(ClauseElement):
     supports_execution = True
+    _autocommit = False
     quote = None
     
     def __init__(self, ident):
index a91539d5a05262b7eda694374123ff636ceecdbf..79c954688fc1ef094a0e7d13e0226a10db2f4d33 100644 (file)
@@ -340,7 +340,7 @@ class ZooMarkTest(TestBase):
     def test_profile_4_expressions(self):
         self.test_baseline_4_expressions()
 
-    @profiling.function_call_count(1442, {'2.4': 1001})
+    @profiling.function_call_count(1347, {'2.4': 1001})
     def test_profile_5_aggregates(self):
         self.test_baseline_5_aggregates()
 
@@ -348,7 +348,7 @@ class ZooMarkTest(TestBase):
     def test_profile_6_editing(self):
         self.test_baseline_6_editing()
 
-    @profiling.function_call_count(3110, {'2.4': 1998})
+    @profiling.function_call_count(2994, {'2.4': 1998})
     def test_profile_7_multiview(self):
         self.test_baseline_7_multiview()
 
index 7af72b25862d4b286d0c1ec954c2482156eab98d..edf37ba0400f94ae3237a6d5a6925fdbab522e40 100644 (file)
@@ -306,7 +306,7 @@ class ZooMarkTest(TestBase):
     def test_profile_4_expressions(self):
         self.test_baseline_4_expressions()
 
-    @profiling.function_call_count(1426)
+    @profiling.function_call_count(1331)
     def test_profile_5_aggregates(self):
         self.test_baseline_5_aggregates()
 
index b719ac93d36d5a8c5f79688f5975af78269432a7..b7208532c5b8ca4179f12f1714fa4189cd39ee3c 100644 (file)
@@ -175,12 +175,12 @@ class ConstraintTest(TestBase, AssertsExecutionResults):
         capt = []
         connection = testing.db.connect()
         # TODO: hacky, put a real connection proxy in
-        ex = connection._Connection__execute_raw
+        ex = connection._Connection__execute_context
         def proxy(context):
             capt.append(context.statement)
             capt.append(repr(context.parameters))
             ex(context)
-        connection._Connection__execute_raw = proxy
+        connection._Connection__execute_context = proxy
         schemagen = testing.db.dialect.schemagenerator(testing.db.dialect, connection)
         schemagen.traverse(events)
 
index cc77369379f16d0fa3ce0603d2cbb7c7a136dd56..b38968964f9a6554fb816fa8eaed887eae412525 100644 (file)
@@ -486,7 +486,7 @@ class ExecutionContextWrapper(object):
         setattr(self.ctx, key, value)
 
     trailing_underscore_pattern = re.compile(r'(\W:[\w_#]+)_\b',re.MULTILINE)
-    def post_execution(self):
+    def post_exec(self):
         ctx = self.ctx
         statement = unicode(ctx.compiled)
         statement = re.sub(r'\n', '', ctx.statement)
@@ -540,7 +540,7 @@ class ExecutionContextWrapper(object):
             testdata.unittest.assert_(equivalent,
                     "Testing for query '%s' params %s, received '%s' with params %s" % (query, repr(params), statement, repr(parameters)))
         testdata.sql_count += 1
-        self.ctx.post_execution()
+        self.ctx.post_exec()
 
     def convert_statement(self, query):
         paramstyle = self.ctx.dialect.paramstyle