From 758828ed544966cd78524f450f877be5b789fee4 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sat, 7 Oct 2006 00:54:14 +0000 Subject: [PATCH] assorted firebird fixes from Lele Gaifax --- CHANGES | 3 +++ lib/sqlalchemy/databases/firebird.py | 18 ++++++++++++++---- test/sql/select.py | 11 ++++++++--- test/testbase.py | 6 ++++-- 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/CHANGES b/CHANGES index 9b2d2af550..3abebef666 100644 --- a/CHANGES +++ b/CHANGES @@ -26,6 +26,9 @@ - Oracle has experimental support for cx_Oracle.TIMESTAMP, which requires a setinputsizes() call on the cursor that is now enabled via the 'auto_setinputsizes' flag to the oracle dialect. + - Firebird: + - aliases do not use "AS" + - correctly raises NoSuchTableError when reflecting non-existent table - Schema: - added autoincrement=True to Column; will disable schema generation of SERIAL/AUTO_INCREMENT/identity seq for postgres/mysql/mssql if diff --git a/lib/sqlalchemy/databases/firebird.py b/lib/sqlalchemy/databases/firebird.py index 67214313f1..a3344418da 100644 --- a/lib/sqlalchemy/databases/firebird.py +++ b/lib/sqlalchemy/databases/firebird.py @@ -117,7 +117,8 @@ class FireBirdDialect(ansisql.ANSIDialect): if isinstance(concurrency_level, types.StringTypes): concurrency_level = int(concurrency_level) - kinterbasdb.init(type_conv=type_conv, concurrency_level=concurrency_level) + if kinterbasdb is not None: + kinterbasdb.init(type_conv=type_conv, concurrency_level=concurrency_level) ansisql.ANSIDialect.__init__(self, **params) def create_connect_args(self, url): @@ -243,9 +244,11 @@ class FireBirdDialect(ansisql.ANSIDialect): return name c = connection.execute(tblqry, [table.name.upper()]) - while True: - row = c.fetchone() - if not row: break + row = c.fetchone() + if not row: + raise exceptions.NoSuchTableError(table.name) + + while row: name = row['FNAME'] args = [lower_if_possible(name)] @@ -257,6 +260,7 @@ class FireBirdDialect(ansisql.ANSIDialect): kw['primary_key'] = name in pkfields table.append_item(schema.Column(*args, **kw)) + row = c.fetchone() # get the foreign keys c = connection.execute(fkqry, ["FOREIGN KEY", table.name.upper()]) @@ -314,6 +318,12 @@ class FBCompiler(ansisql.ANSICompiler): super(FBCompiler, self).__init__(dialect, statement, parameters, **kwargs) + def visit_alias(self, alias): + # Override to not use the AS keyword which FB 1.5 does not like + self.froms[alias] = self.get_from_text(alias.original) + " " + self.preparer.format_alias(alias) + self.strings[alias] = self.get_str(alias.original) + + def visit_column(self, column): return ansisql.ANSICompiler.visit_column(self, column) diff --git a/test/sql/select.py b/test/sql/select.py index ac5af4f3ba..2804da3445 100644 --- a/test/sql/select.py +++ b/test/sql/select.py @@ -1,7 +1,7 @@ from testbase import PersistTest import testbase from sqlalchemy import * -from sqlalchemy.databases import sqlite, postgres, mysql, oracle +from sqlalchemy.databases import sqlite, postgres, mysql, oracle, firebird import unittest, re # the select test now tests almost completely with TableClause/ColumnClause objects, @@ -264,9 +264,14 @@ sq.myothertable_othername AS sq_myothertable_othername FROM (" + sqstring + ") A def testalias(self): # test the alias for a table1. column names stay the same, table name "changes" to "foo". self.runtest( - select([alias(table1, 'foo')]) - ,"SELECT foo.myid, foo.name, foo.description FROM mytable AS foo") + select([alias(table1, 'foo')]) + ,"SELECT foo.myid, foo.name, foo.description FROM mytable AS foo") + self.runtest( + select([alias(table1, 'foo')]) + ,"SELECT foo.myid, foo.name, foo.description FROM mytable foo" + ,dialect=firebird.dialect()) + # create a select for a join of two tables. use_labels means the column names will have # labels tablename_columnname, which become the column keys accessible off the Selectable object. # also, only use one column from the second table and all columns from the first table1. diff --git a/test/testbase.py b/test/testbase.py index d115d400ad..b62f41f6a7 100644 --- a/test/testbase.py +++ b/test/testbase.py @@ -40,7 +40,7 @@ def parse_argv(): parser = optparse.OptionParser(usage = "usage: %prog [options] files...") parser.add_option("--dburi", action="store", dest="dburi", help="database uri (overrides --db)") - parser.add_option("--db", action="store", dest="db", default="sqlite", help="prefab database uri (sqlite, sqlite_file, postgres, mysql, oracle, oracle8, mssql)") + parser.add_option("--db", action="store", dest="db", default="sqlite", help="prefab database uri (sqlite, sqlite_file, postgres, mysql, oracle, oracle8, mssql, firebird)") parser.add_option("--mockpool", action="store_true", dest="mockpool", help="use mock pool") parser.add_option("--verbose", action="store_true", dest="verbose", help="full debug echoing") parser.add_option("--quiet", action="store_true", dest="quiet", help="be totally quiet") @@ -75,9 +75,11 @@ def parse_argv(): opts = {'use_ansi':False} elif DBTYPE == 'mssql': db_uri = 'mssql://scott:tiger@SQUAWK\\SQLEXPRESS/test' + elif DBTYPE == 'firebird': + db_uri = 'firebird://sysdba:s@localhost/tmp/test.fdb' if not db_uri: - raise "Could not create engine. specify --db to test runner." + raise "Could not create engine. specify --db to test runner." if not options.nothreadlocal: __import__('sqlalchemy.mods.threadlocal') -- 2.47.2