"""
opts = url.translate_connect_args(username='user')
opts.update(url.query)
- args = opts['host'],
- kwargs = {'user':opts['user'],
- 'password': opts['password']}
- return args, kwargs
+ args = opts.pop('host')
+ opts.pop('port', None)
+ opts.pop('database', None)
+ return (args,), opts
def is_disconnect(self, e):
# eGenix recommends checking connection.closed here,
return tuple(version)
def do_execute(self, cursor, statement, parameters, context=None):
- # temporary workaround until a more comprehensive solution can
- # be found for controlling when to use executedirect
- try:
- cursor.execute(statement, parameters)
- except (InterfaceError, ProgrammingError), e:
- warnings.warn("cursor.execute failed; falling back to executedirect")
+ if context:
+ native_odbc_execute = context.execution_options.\
+ get('native_odbc_execute', 'auto')
+ if native_odbc_execute is True:
+ # user specified native_odbc_execute=True
+ cursor.execute(statement, parameters)
+ elif native_odbc_execute is False:
+ # user specified native_odbc_execute=False
+ cursor.executedirect(statement, parameters)
+ elif context.is_crud:
+ # statement is UPDATE, DELETE, INSERT
+ cursor.execute(statement, parameters)
+ else:
+ # all other statements
+ cursor.executedirect(statement, parameters)
+ else:
cursor.executedirect(statement, parameters)
--- /dev/null
+from sqlalchemy import *
+from sqlalchemy.test.testing import eq_, TestBase
+from sqlalchemy.test import engines
+
+# TODO: we should probably build mock bases for
+# these to share with test_reconnect, test_parseconnect
+class MockDBAPI(object):
+ paramstyle = 'qmark'
+ def __init__(self):
+ self.log = []
+ def connect(self, *args, **kwargs):
+ return MockConnection(self)
+
+class MockConnection(object):
+ def __init__(self, parent):
+ self.parent = parent
+ def cursor(self):
+ return MockCursor(self)
+ def close(self):
+ pass
+ def rollback(self):
+ pass
+ def commit(self):
+ pass
+
+class MockCursor(object):
+ description = None
+ rowcount = None
+ def __init__(self, parent):
+ self.parent = parent
+ def execute(self, *args, **kwargs):
+ self.parent.parent.log.append('execute')
+ def executedirect(self, *args, **kwargs):
+ self.parent.parent.log.append('executedirect')
+ def close(self):
+ pass
+
+
+class MxODBCTest(TestBase):
+ def test_native_odbc_execute(self):
+ t1 = Table('t1', MetaData(), Column('c1', Integer))
+
+ dbapi = MockDBAPI()
+ engine = engines.testing_engine(
+ 'mssql+mxodbc://localhost',
+ options={'module':dbapi,
+ '_initialize':False}
+ )
+ conn = engine.connect()
+
+ # crud: uses execute
+ conn.execute(t1.insert().values(c1='foo'))
+ conn.execute(t1.delete().where(t1.c.c1=='foo'))
+ conn.execute(t1.update().where(t1.c.c1=='foo').values(c1='bar'))
+
+ # select: uses executedirect
+ conn.execute(t1.select())
+
+ # manual flagging
+ conn.execution_options(native_odbc_execute=True).execute(t1.select())
+ conn.execution_options(native_odbc_execute=False).execute(t1.insert().values(c1='foo'))
+
+ eq_(
+ dbapi.log,
+ ['execute', 'execute', 'execute',
+ 'executedirect', 'execute', 'executedirect']
+ )
+
+
\ No newline at end of file