summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES3
-rw-r--r--lib/sqlalchemy/databases/firebird.py18
-rw-r--r--test/sql/select.py11
-rw-r--r--test/testbase.py6
4 files changed, 29 insertions, 9 deletions
diff --git a/CHANGES b/CHANGES
index 9b2d2af55..3abebef66 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 67214313f..a3344418d 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 ac5af4f3b..2804da344 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 d115d400a..b62f41f6a 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 <sqlite|sqlite_file|postgres|mysql|oracle|oracle8|mssql> to test runner."
+ raise "Could not create engine. specify --db <sqlite|sqlite_file|postgres|mysql|oracle|oracle8|mssql|firebird> to test runner."
if not options.nothreadlocal:
__import__('sqlalchemy.mods.threadlocal')