From: Mike Bayer Date: Sat, 11 Aug 2007 01:08:42 +0000 (+0000) Subject: attempting to get oracle XID to work. not there yet. X-Git-Tag: rel_0_4beta1~10 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=41c734b5a38a615c2f175659a6e8e0c37c482118;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git attempting to get oracle XID to work. not there yet. --- diff --git a/lib/sqlalchemy/databases/oracle.py b/lib/sqlalchemy/databases/oracle.py index 7bbc63fba7..78ceddb4ee 100644 --- a/lib/sqlalchemy/databases/oracle.py +++ b/lib/sqlalchemy/databases/oracle.py @@ -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) diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py index 4e4edaced3..9f8e8734ee 100644 --- a/lib/sqlalchemy/engine/base.py +++ b/lib/sqlalchemy/engine/base.py @@ -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 diff --git a/lib/sqlalchemy/engine/default.py b/lib/sqlalchemy/engine/default.py index 185387177d..db22b8aaa4 100644 --- a/lib/sqlalchemy/engine/default.py +++ b/lib/sqlalchemy/engine/default.py @@ -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)) diff --git a/test/engine/transaction.py b/test/engine/transaction.py index 8c516b1952..26ec09f053 100644 --- a/test/engine/transaction.py +++ b/test/engine/transaction.py @@ -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()