diff options
author | Alexandre Fayolle <alexandre.fayolle@logilab.fr> | 2010-02-17 14:21:50 -0800 |
---|---|---|
committer | Alexandre Fayolle <alexandre.fayolle@logilab.fr> | 2010-02-17 14:21:50 -0800 |
commit | c16ccecd24c6e8a92cae4b8844d3be66efea30d0 (patch) | |
tree | 00617089c41c8a4d0094627bfa77b905b0f56097 | |
parent | 9dfc9dee10f4ec15db2e94fd87d3ea6e87fc5563 (diff) | |
download | logilab-common-c16ccecd24c6e8a92cae4b8844d3be66efea30d0.tar.gz |
various improvements and fixes concerning logilab.common.db support of SQLServer
-rw-r--r-- | _pyodbcwrap.py | 70 | ||||
-rw-r--r-- | adbh.py | 3 | ||||
-rw-r--r-- | db.py | 12 |
3 files changed, 61 insertions, 24 deletions
diff --git a/_pyodbcwrap.py b/_pyodbcwrap.py index f8f3674..4852170 100644 --- a/_pyodbcwrap.py +++ b/_pyodbcwrap.py @@ -24,19 +24,18 @@ import sys import subprocess from cPickle import dumps, loads, HIGHEST_PROTOCOL import struct # if we need binary protocol +from exceptions import * if sys.platform == 'win32': #pylint:disable-msg=F0401 import pyodbc as dbapimodule from pyodbc import * + import pyodbc else: import psycopg2 as dbapimodule from psycopg2 import * from psycopg2 import _psycopg -sys.stderr.write('*!'*80 + '\n') - - class ProtocolError(OperationalError): pass @@ -95,7 +94,9 @@ class Proxy(object): if answer_head[0] == 'VAL': return value else: # 'EXC': - raise value + exc_class_name, args = value + exc = globals()[exc_class_name](*args) + raise exc except IOError, exc: raise ProtocolError('IOError %s' % exc) @@ -126,7 +127,9 @@ class Proxy(object): else: # exception data = pipe.stdout.read(length) value = loads(data) - raise value + exc_class_name, args = value + exc = globals()[exc_class_name](*args) + raise exc except IOError, exc: raise ProtocolError('IOError %s' % exc) @@ -146,7 +149,7 @@ class ConnectionProxy(Proxy): remote_class = 'RemoteConnection' @classmethod def _new_connection(cls, *args, **kwargs): - cmd = [sys.executable, __file__] + cmd = [sys.executable, '-u', __file__] pipe = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, @@ -171,10 +174,10 @@ class ConnectionProxy(Proxy): class CursorProxy(Proxy): - def execute(self, sql, params=None): + def execute(self, sql, params=()): self._call('execute', (sql, params)) - def executemany(self, sql, params=None): + def executemany(self, sql, params=()): self._call('executemany', (sql, params)) def fetchone(self): @@ -194,8 +197,22 @@ class CursorProxy(Proxy): def close(self): return self._call('close') + + # pyodbc specific + def tables(self): + return self._call('tables') class RowProxy(Proxy): + def __iter__(self): + i = 0 + while True: + try: + col = self[i] + except IndexError: + break + yield col + i += 1 + def __getitem__(self, index): return self._call('__getitem__', (index,), proxy_class=BinaryProxy) @@ -204,13 +221,23 @@ class BinaryProxy(Proxy): return self._call('getvalue') class RowListProxy(Proxy): + def __iter__(self): + i = 0 + while True: + try: + row = self[i] + except IndexError: + break + yield row + i += 1 + def __getitem__(self, index): return self._call('__getitem__', (index,), proxy_class=RowProxy) if __name__ == '__main__': - sys.stderr.write('-%'*80 + '\n') import os #log = open('/dev/null', 'a') + log = sys.stderr import traceback from logilab.common._pyodbcwrap import Binary # otherwise the isinstance test below will fail @@ -271,8 +298,9 @@ if __name__ == '__main__': msg_data = dumps(result) msg_head = 'VAL %d\r\n' % len(msg_data) except Exception, exc: - #traceback.print_exc(file=sys.stderr) - msg_data = dumps(exc) + if not isinstance(exc, IndexError): + traceback.print_exc(file=sys.stderr) + msg_data = dumps((exc.__class__.__name__, exc.args)) msg_head = 'EXC %d\r\n' % len(msg_data) #print >> log, 'EXC' elif command == 'NEW': @@ -283,8 +311,8 @@ if __name__ == '__main__': msg_head = 'REF 0 %d\r\n' % result.obj_id msg_data = '' except Exception, exc: - #traceback.print_exc(file=sys.stderr) - msg_data = dumps(exc) + traceback.print_exc(file=sys.stderr) + msg_data = dumps((exc.__class__.__name__, exc.args)) msg_head = 'EXC %d\r\n' % len(msg_data) elif command == 'DEL': @@ -293,11 +321,14 @@ if __name__ == '__main__': msg_data = None if msg_head is not None: - self.output.write(msg_head) - self.output.flush() - if msg_data: - self.output.write(msg_data) + try: + self.output.write(msg_head) self.output.flush() + if msg_data: + self.output.write(msg_data) + self.output.flush() + except IOError: + break #print >> log, 'STATS:', len(self.objects), 'objs alive' class RemoteWrapper(object): @@ -330,6 +361,7 @@ if __name__ == '__main__': super(RemoteCursor, self).__init__(cursor) def _require_row_wrap(self): + return True for col_desc in self.wrapped.description: if col_desc[1] == dbapimodule.BINARY: #print >> log, 'require wrap' @@ -374,6 +406,10 @@ if __name__ == '__main__': return RemoteRowList(rows) else: return rows + + def tables(self): + self.wrapped.tables() + class RemoteRow(RemoteWrapper): def __init__(self, row): @@ -602,7 +602,8 @@ class _SqlServer2005FuncHelper(_GenericAdvFuncHelper): def list_tables(self, cursor): """return the list of tables of a database""" - return [row.table_name for row in cursor.tables()] + cursor.tables() + return [row.table_name for row in cursor.fetchall()] def binary_value(self, value): return StringIO.StringIO(value) @@ -774,9 +774,9 @@ class _PyodbcAdapterMT(_PyodbcAdapter): return unicode(value, encoding, 'replace') elif typecode == self.BINARY: # value is a python buffer if binarywrap is not None: - return binarywrap(value.value) + return binarywrap(value.getbinary()) else: - return value.value + return value.getbinary() elif typecode == self.UNKNOWN: # may occurs on constant selection for instance (e.g. SELECT 'hop') # with postgresql at least @@ -789,19 +789,19 @@ class _PyodbcSqlServer2000Adapter(_PyodbcAdapter): driver = "SQL Server" class _PyodbcSqlServer2005Adapter(_PyodbcAdapter): - driver = "SQL Native Client" + driver = "SQL Server Native Client 10.0" class _PyodbcSqlServer2008Adapter(_PyodbcAdapter): - driver = "SQL Native Client 10.0" + driver = "SQL Server Native Client 10.0" class _PyodbcSqlServer2000AdapterMT(_PyodbcAdapterMT): driver = "SQL Server" class _PyodbcSqlServer2005AdapterMT(_PyodbcAdapterMT): - driver = "SQL Native Client 10.0" + driver = "SQL Server Native Client 10.0" class _PyodbcSqlServer2008AdapterMT(_PyodbcAdapterMT): - driver = "SQL Native Client 10.0" + driver = "SQL Server Native Client 10.0" ## Drivers, Adapters and helpers registries ################################### |