From: Mike Bayer Date: Fri, 18 Dec 2009 20:41:34 +0000 (+0000) Subject: - added _with_options() to Connection. not publicizing this yet. X-Git-Tag: rel_0_6beta1~123 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=404be6e76155a5ef48f3d4a2c1a7e5538de135e9;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - added _with_options() to Connection. not publicizing this yet. - updated oursql driver with latest fixes using options. [ticket:1613] - all the MySQL drivers get a shoutout in the docs - marked tests that OurSQL has problems with (only three), passes 100% now --- diff --git a/doc/build/reference/dialects/mysql.rst b/doc/build/reference/dialects/mysql.rst index 839b8cae07..c310f6c524 100644 --- a/doc/build/reference/dialects/mysql.rst +++ b/doc/build/reference/dialects/mysql.rst @@ -138,11 +138,26 @@ MySQL Column Types :members: __init__ :show-inheritance: -MySQLdb Notes +MySQL-Python Notes -------------- .. automodule:: sqlalchemy.dialects.mysql.mysqldb +OurSQL Notes +-------------- + +.. automodule:: sqlalchemy.dialects.mysql.oursql + +MyConnPY Notes +-------------- + +.. automodule:: sqlalchemy.dialects.mysql.myconnpy + +pyodbc Notes +-------------- + +.. automodule:: sqlalchemy.dialects.mysql.pyodbc + zxjdbc Notes -------------- diff --git a/lib/sqlalchemy/dialects/mysql/oursql.py b/lib/sqlalchemy/dialects/mysql/oursql.py index 79a36f535b..70bec53a3c 100644 --- a/lib/sqlalchemy/dialects/mysql/oursql.py +++ b/lib/sqlalchemy/dialects/mysql/oursql.py @@ -31,10 +31,6 @@ from sqlalchemy.sql import operators as sql_operators from sqlalchemy import exc, log, schema, sql, types as sqltypes, util -class _PlainQuery(unicode): - pass - - class _oursqlNumeric(NUMERIC): def result_processor(self, dialect, coltype): if self.asdecimal: @@ -53,12 +49,21 @@ class _oursqlBIT(BIT): return None + +class MySQL_oursqlExecutionContext(MySQLExecutionContext): + + @property + def plain_query(self): + return self._connection.options.get('plain_query', False) + + class MySQL_oursql(MySQLDialect): driver = 'oursql' supports_unicode_statements = True supports_unicode_binds = True supports_sane_rowcount = True supports_sane_multi_rowcount = True + execution_ctx_cls = MySQL_oursqlExecutionContext colspecs = util.update_copy( MySQLDialect.colspecs, @@ -76,7 +81,7 @@ class MySQL_oursql(MySQLDialect): def do_execute(self, cursor, statement, parameters, context=None): """Provide an implementation of *cursor.execute(statement, parameters)*.""" - if context and not context.compiled and isinstance(context.statement, _PlainQuery): + if context and context.plain_query: cursor.execute(statement, plain_query=True) else: cursor.execute(statement, parameters) @@ -85,7 +90,7 @@ class MySQL_oursql(MySQLDialect): connection.cursor().execute('BEGIN', plain_query=True) def _xa_query(self, connection, query, xid): - connection.execute(_PlainQuery(query % connection.connection._escape_string(xid))) + connection._with_options(plain_query=True).execute(query % connection.connection._escape_string(xid)) # Because mysql is bad, these methods have to be reimplemented to use _PlainQuery. Basically, some queries # refuse to return any data if they're run through the parameterized query API, or refuse to be parameterized @@ -110,49 +115,13 @@ class MySQL_oursql(MySQLDialect): self._xa_query(connection, 'XA COMMIT "%s"', xid) def has_table(self, connection, table_name, schema=None): - full_name = '.'.join(self.identifier_preparer._quote_free_identifiers( - schema, table_name)) - - st = "DESCRIBE %s" % full_name - rs = None - try: - try: - rs = connection.execute(_PlainQuery(st)) - have = rs.rowcount > 0 - rs.close() - return have - except exc.SQLError, e: - if self._extract_error_code(e) == 1146: - return False - raise - finally: - if rs: - rs.close() + return MySQLDialect.has_table(self, connection._with_options(plain_query=True), table_name, schema) def _show_create_table(self, connection, table, charset=None, full_name=None): - """Run SHOW CREATE TABLE for a ``Table``.""" - - if full_name is None: - full_name = self.identifier_preparer.format_table(table) - st = "SHOW CREATE TABLE %s" % full_name - - rp = None - try: - try: - rp = connection.execute(_PlainQuery(st)) - except exc.SQLError, e: - if self._extract_error_code(e) == 1146: - raise exc.NoSuchTableError(full_name) - else: - raise - row = rp.fetchone() - if not row: - raise exc.NoSuchTableError(full_name) - return row[1].strip() - finally: - if rp: - rp.close() + return MySQLDialect._show_create_table(self, + connection.contextual_connect(close_with_result=True)._with_options(plain_query=True), + table, charset, full_name) def is_disconnect(self, e): if isinstance(e, self.dbapi.ProgrammingError): # if underlying connection is closed, this is the error you get diff --git a/lib/sqlalchemy/dialects/mysql/pyodbc.py b/lib/sqlalchemy/dialects/mysql/pyodbc.py index 96171ee0b5..7cb2f36428 100644 --- a/lib/sqlalchemy/dialects/mysql/pyodbc.py +++ b/lib/sqlalchemy/dialects/mysql/pyodbc.py @@ -1,3 +1,7 @@ +"""Support for the MySQL database via the pyodbc adapter. + +""" + from sqlalchemy.dialects.mysql.base import MySQLDialect, MySQLExecutionContext from sqlalchemy.connectors.pyodbc import PyODBCConnector from sqlalchemy.engine import base as engine_base diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py index ddf2602c2d..3fbc23312b 100644 --- a/lib/sqlalchemy/engine/base.py +++ b/lib/sqlalchemy/engine/base.py @@ -706,9 +706,10 @@ class Connection(Connectable): .. index:: single: thread safety; Connection """ - + options = {} + def __init__(self, engine, connection=None, close_with_result=False, - _branch=False): + _branch=False, _options=None): """Construct a new Connection. Connection objects are typically constructed by an @@ -723,6 +724,8 @@ class Connection(Connectable): self.__savepoint_seq = 0 self.__branch = _branch self.__invalid = False + if _options: + self.options = _options def _branch(self): """Return a new Connection which references this Connection's @@ -734,7 +737,22 @@ class Connection(Connectable): """ return self.engine.Connection(self.engine, self.__connection, _branch=True) - + + def _with_options(self, **opt): + """Add keyword options to a Connection generatively. + + Experimental. May change the name/signature at + some point. + + If made public, strongly consider the name + "options()" so as to be consistent with + orm.Query.options(). + + """ + return self.engine.Connection( + self.engine, self.__connection, + _branch=self.__branch, _options=opt) + @property def dialect(self): "Dialect used by this Connection." diff --git a/test/engine/test_transaction.py b/test/engine/test_transaction.py index 82b767b0eb..c51623f2cd 100644 --- a/test/engine/test_transaction.py +++ b/test/engine/test_transaction.py @@ -279,6 +279,7 @@ class TransactionTest(TestBase): connection.close() @testing.requires.two_phase_transactions + @testing.crashes('mysql+oursql', 'Times out in full test runs only, causing subsequent tests to fail') @testing.crashes('mysql+zxjdbc', 'Deadlocks, causing subsequent tests to fail') @testing.fails_on('mysql', 'FIXME: unknown') def test_two_phase_recover(self): diff --git a/test/orm/test_unitofwork.py b/test/orm/test_unitofwork.py index 6b628d8264..85a0eae821 100644 --- a/test/orm/test_unitofwork.py +++ b/test/orm/test_unitofwork.py @@ -200,6 +200,7 @@ class UnicodeTest(_base.MappedTest): class Test2(_base.BasicEntity): pass + @testing.fails_on('mysql+oursql', 'raises a warning') @testing.resolve_artifact_names def test_basic(self): mapper(Test, uni_t1) @@ -213,7 +214,8 @@ class UnicodeTest(_base.MappedTest): session.commit() self.assert_(t1.txt == txt) - + + @testing.fails_on('mysql+oursql', 'raises a warning') @testing.resolve_artifact_names def test_relation(self): mapper(Test, uni_t1, properties={