]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
attempting to get oracle XID to work. not there yet.
authorMike Bayer <mike_mp@zzzcomputing.com>
Sat, 11 Aug 2007 01:08:42 +0000 (01:08 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 11 Aug 2007 01:08:42 +0000 (01:08 +0000)
lib/sqlalchemy/databases/oracle.py
lib/sqlalchemy/engine/base.py
lib/sqlalchemy/engine/default.py
test/engine/transaction.py

index 7bbc63fba7ab2f02d97d9d88d88dc7db6f3bfd7e..78ceddb4ee07b2824587f9d2c4eb38d7a8817831 100644 (file)
@@ -5,7 +5,7 @@
 # the MIT License: http://www.opensource.org/licenses/mit-license.php
 
 
-import re, warnings, operator
+import re, warnings, operator, random
 
 from sqlalchemy import util, sql, schema, ansisql, exceptions, logging
 from sqlalchemy.engine import default, base
@@ -210,10 +210,11 @@ class OracleExecutionContext(default.DefaultExecutionContext):
         return base.ResultProxy(self)
 
 class OracleDialect(ansisql.ANSIDialect):
-    def __init__(self, use_ansi=True, auto_setinputsizes=True, auto_convert_lobs=True, threaded=True, **kwargs):
+    def __init__(self, use_ansi=True, auto_setinputsizes=True, auto_convert_lobs=True, threaded=True, allow_twophase=True, **kwargs):
         ansisql.ANSIDialect.__init__(self, default_paramstyle='named', **kwargs)
         self.use_ansi = use_ansi
         self.threaded = threaded
+        self.allow_twophase = allow_twophase
         self.supports_timestamp = self.dbapi is None or hasattr(self.dbapi, 'TIMESTAMP' )
         self.auto_setinputsizes = auto_setinputsizes
         self.auto_convert_lobs = auto_convert_lobs
@@ -258,7 +259,8 @@ class OracleDialect(ansisql.ANSIDialect):
             user=url.username,
             password=url.password,
             dsn = dsn,
-            threaded = self.threaded
+            threaded = self.threaded,
+            twophase = self.allow_twophase,
             )
         opts.update(url.query)
         util.coerce_kw_type(opts, 'use_ansi', bool)
@@ -280,10 +282,34 @@ class OracleDialect(ansisql.ANSIDialect):
         else:
             return "rowid"
 
+    def create_xid(self):
+        """create a two-phase transaction ID.
+
+        this id will be passed to do_begin_twophase(), do_rollback_twophase(),
+        do_commit_twophase().  its format is unspecified."""
+
+        id = random.randint(0,2**128)
+        return (0x1234, "%032x" % 9, "%032x" % id)
+
     def do_release_savepoint(self, connection, name):
         # Oracle does not support RELEASE SAVEPOINT
         pass
 
+    def do_begin_twophase(self, connection, xid):
+        connection.connection.begin(*xid)
+        
+    def do_prepare_twophase(self, connection, xid):
+        connection.connection.prepare()
+        
+    def do_rollback_twophase(self, connection, xid, is_prepared=True, recover=False):
+        self.do_rollback(connection.connection)
+
+    def do_commit_twophase(self, connection, xid, is_prepared=True, recover=False):
+        self.do_commit(connection.connection)
+
+    def do_recover_twophase(self, connection):
+        pass
+        
     def create_execution_context(self, *args, **kwargs):
         return OracleExecutionContext(self, *args, **kwargs)
 
index 4e4edaced3814d54ddbc843ba3398809020155a6..9f8e8734eed95e2145882d0e3a97a871adcfc11c 100644 (file)
@@ -203,6 +203,14 @@ class Dialect(object):
 
         raise NotImplementedError()
 
+    def create_xid(self):
+        """create a two-phase transaction ID.
+
+        this id will be passed to do_begin_twophase(), do_rollback_twophase(),
+        do_commit_twophase().  its format is unspecified."""
+
+        raise NotImplementedError()
+
     def do_commit(self, connection):
         """Provide an implementation of *connection.commit()*, given a DBAPI connection."""
 
@@ -606,7 +614,7 @@ class Connection(Connectable):
         if self.__transaction is not None:
             raise exceptions.InvalidRequestError("Cannot start a two phase transaction when a transaction is already started.")
         if xid is None:
-            xid = "_sa_%032x" % random.randint(0,2**128)
+            xid = self.__engine.dialect.create_xid();
         self.__transaction = TwoPhaseTransaction(self, xid)
         return self.__transaction
         
index 185387177d3441c762dc0b49960f5f677b51ea1b..db22b8aaa4fa51231b0233991279af01622b3d04 100644 (file)
@@ -7,7 +7,7 @@
 """Provide default implementations of per-dialect sqlalchemy.engine classes"""
 
 from sqlalchemy import schema, exceptions, sql, types, util
-import sys, re
+import sys, re, random
 from sqlalchemy.engine import base
 
 
@@ -87,6 +87,14 @@ class DefaultDialect(base.Dialect):
 
         #print "ENGINE COMMIT ON ", connection.connection
         connection.commit()
+    
+    def create_xid(self):
+        """create a two-phase transaction ID.
+        
+        this id will be passed to do_begin_twophase(), do_rollback_twophase(),
+        do_commit_twophase().  its format is unspecified."""
+        
+        return "_sa_%032x" % random.randint(0,2**128)
         
     def do_savepoint(self, connection, name):
         connection.execute(sql.SavepointClause(name))
index 8c516b19525addac2712f1d14f27ae267985c125..26ec09f0538462ad60738bb6602ae7ac318db6b6 100644 (file)
@@ -173,7 +173,7 @@ class TransactionTest(PersistTest):
         )
         connection.close()
     
-    @testing.supported('postgres', 'mysql', 'oracle')
+    @testing.supported('postgres', 'mysql')
     @testing.exclude('mysql', '<', (5, 0, 3))
     def testtwophasetransaction(self):
         connection = testbase.db.connect()