I know that kinterbasdb does not support python3, but there is an alternative driver fdb which does. This is the driver recommended by the firebird project.
<http://pypi.python.org/pypi/fdb/> I copied the kinterbasdb driver in sqlalchemy to a new file fdb.py and made some minimal changes, mostly string replacements . It works for me with python2. I then tried it on a different box which has both py2 and py3. In this case I get a syntax error when calling get_pk_constraint() whereby connection.execute reports too many parameters. File "/usr/lib/python3.2/site-packages/sqlalchemy/dialects/firebird/base.py", line 487, in get_pk_constraint c = connection.execute(keyqry, ["PRIMARY KEY", tablename]) File "/usr/lib/python3.2/site-packages/sqlalchemy/engine/base.py", line 1453, in execute params) File "/usr/lib/python3.2/site-packages/sqlalchemy/engine/base.py", line 1630, in _execute_text statement, parameters File "/usr/lib/python3.2/site-packages/sqlalchemy/engine/base.py", line 1700, in _execute_context context) File "/usr/lib/python3.2/site-packages/sqlalchemy/engine/base.py", line 1846, in _handle_dbapi_exception from e sqlalchemy.exc.ProgrammingError: (ProgrammingError) Statement parameter sequence contains 11 parameters, but only 10 are allowed '\n SELECT se.rdb$field_name AS fname\n FROM rdb$relation_constraints rc\n JOIN rdb$index_segments se ON rc.rdb$index_name=se.rdb$index_name\n WHERE rc.rdb$constraint_type=? AND rc.rdb$relation_name=?\n ' [('P', 'R', 'I', 'M', 'A', 'R', 'Y', ' ', 'K', 'E', 'Y'), ('A', 'C', 'C','O','U','N','T')] I have been testing using the latest checkouts of firebird 2.5 and 3.0 My patches are attached. -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalchemy@googlegroups.com. To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
--- kinterbasdb.py 2012-06-08 11:13:52.000000000 +0200 +++ fdb.py 2012-06-08 11:13:52.000000000 +0200 @@ -1,5 +1,5 @@ -# firebird/kinterbasdb.py -# Copyright (C) 2005-2012 the SQLAlchemy authors and contributors <see AUTHORS file> +# firebird/fdb.py +# Copyright (C) 2005-2011 the SQLAlchemy authors and contributors <see AUTHORS file> # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php @@ -10,8 +10,17 @@ The connection URL is of the form ``firebird[+kinterbasdb]://user:password@host:port/path/to/db[?key=value&key=value...]``. +or +``firebird[+fdb]://user:password@host:port/path/to/db[?key=value&key=value...]``. -Kinterbasedb backend specific keyword arguments are: + + +An alternative interface, also from the Firebird project is fdb.py. This is currently being +enhanced to provide Python3 support as well. +Fdb claims to be mostly compatible with Kinterbasedb. + + +Kinterbasedb/fdb backend specific keyword arguments are: * type_conv - select the kind of mapping done on the types: by default SQLAlchemy uses 200 with Unicode, datetime and decimal support (see @@ -22,10 +31,10 @@ * enable_rowcount - True by default, setting this to False disables the usage of "cursor.rowcount" with the - Kinterbasdb dialect, which SQLAlchemy ordinarily calls upon automatically + fdb dialect, which SQLAlchemy ordinarily calls upon automatically after any UPDATE or DELETE statement. When disabled, SQLAlchemy's ResultProxy will return -1 for result.rowcount. The rationale here is - that Kinterbasdb requires a second round trip to the database when + that fdb requires a second round trip to the database when .rowcount is called - since SQLA's resultproxy automatically closes the cursor after a non-result-returning statement, rowcount must be called, if at all, before the result object is returned. Additionally, @@ -39,6 +48,7 @@ r = conn.execute(stmt) print r.rowcount +__ http://pypi.python.org/pypi/fdb __ http://sourceforge.net/projects/kinterbasdb __ http://firebirdsql.org/index.php?op=devel&sub=python __ http://kinterbasdb.sourceforge.net/dist_docs/usage.html#adv_param_conv_dynamic_type_translation @@ -52,7 +62,7 @@ from re import match -class _FBNumeric_kinterbasdb(sqltypes.Numeric): +class _FBNumeric_fdb(sqltypes.Numeric): def bind_processor(self, dialect): def process(value): if isinstance(value, decimal.Decimal): @@ -61,7 +71,7 @@ return value return process -class FBExecutionContext_kinterbasdb(FBExecutionContext): +class FBExecutionContext_fdb(FBExecutionContext): @property def rowcount(self): if self.execution_options.get('enable_rowcount', @@ -70,34 +80,35 @@ else: return -1 -class FBDialect_kinterbasdb(FBDialect): - driver = 'kinterbasdb' +class FBDialect_fdb(FBDialect): + driver = 'fdb' supports_sane_rowcount = False supports_sane_multi_rowcount = False - execution_ctx_cls = FBExecutionContext_kinterbasdb + execution_ctx_cls = FBExecutionContext_fdb supports_native_decimal = True colspecs = util.update_copy( FBDialect.colspecs, { - sqltypes.Numeric:_FBNumeric_kinterbasdb, + sqltypes.Numeric:_FBNumeric_fdb, } ) def __init__(self, type_conv=200, concurrency_level=1, - enable_rowcount=True, **kwargs): - super(FBDialect_kinterbasdb, self).__init__(**kwargs) + enable_rowcount=True, charset='UTF8', **kwargs): + super(FBDialect_fdb, self).__init__(**kwargs) self.enable_rowcount = enable_rowcount self.type_conv = type_conv self.concurrency_level = concurrency_level + self.charset = charset if enable_rowcount: self.supports_sane_rowcount = True @classmethod def dbapi(cls): - k = __import__('kinterbasdb') + k = __import__('fdb') return k def create_connect_args(self, url): @@ -113,15 +124,6 @@ concurrency_level = opts.pop('concurrency_level', self.concurrency_level) - if self.dbapi is not None: - initialized = getattr(self.dbapi, 'initialized', None) - if initialized is None: - # CVS rev 1.96 changed the name of the attribute: - # http://kinterbasdb.cvs.sourceforge.net/viewvc/kinterbasdb/Kinterbasdb-3.0/__init__.py?r1=1.95&r2=1.96 - initialized = getattr(self.dbapi, '_initialized', False) - if not initialized: - self.dbapi.init(type_conv=type_conv, - concurrency_level=concurrency_level) return ([], opts) def _get_server_version_info(self, connection): @@ -137,8 +139,10 @@ # where the first version is a fake one resembling the old # Interbase signature. + isc_info_firebird_version = 103 + fbconn = connection.connection - version = fbconn.server_version + version = fbconn.db_info(isc_info_firebird_version) return self._parse_version_info(version) @@ -164,4 +168,4 @@ else: return False -dialect = FBDialect_kinterbasdb +dialect = FBDialect_fdb