}
+ischema_names = {
+ 'SHORT': lambda r: FBSmallInteger(),
+ 'LONG': lambda r: FBInteger(),
+ 'QUAD': lambda r: FBFloat(),
+ 'FLOAT': lambda r: FBFloat(),
+ 'DATE': lambda r: FBDate(),
+ 'TIME': lambda r: FBTime(),
+ 'TEXT': lambda r: FBString(r['FLEN']),
+ 'INT64': lambda r: FBNumeric(precision=r['FPREC'], length=r['FSCALE'] * -1), # This generically handles NUMERIC()
+ 'DOUBLE': lambda r: FBFloat(),
+ 'TIMESTAMP': lambda r: FBDateTime(),
+ 'VARYING': lambda r: FBString(r['FLEN']),
+ 'CSTRING': lambda r: FBChar(r['FLEN']),
+ 'BLOB': lambda r: r['STYPE']==1 and FBText() or FBBinary
+ }
+
+
def descriptor():
return {'name':'firebird',
'description':'Firebird',
return False
def reflecttable(self, connection, table, include_columns):
- #TODO: map these better
- column_func = {
- 14 : lambda r: sqltypes.String(r['FLEN']), # TEXT
- 7 : lambda r: sqltypes.Integer(), # SHORT
- 8 : lambda r: r['FPREC']==0 and sqltypes.Integer() or sqltypes.Numeric(precision=r['FPREC'], length=r['FSCALE'] * -1), #INT or NUMERIC
- 9 : lambda r: sqltypes.Float(), # QUAD
- 10 : lambda r: sqltypes.Float(), # FLOAT
- 27 : lambda r: sqltypes.Float(), # DOUBLE
- 35 : lambda r: sqltypes.DateTime(), # TIMESTAMP
- 37 : lambda r: sqltypes.String(r['FLEN']), # VARYING
- 261: lambda r: sqltypes.TEXT(), # BLOB
- 40 : lambda r: sqltypes.Char(r['FLEN']), # CSTRING
- 12 : lambda r: sqltypes.Date(), # DATE
- 13 : lambda r: sqltypes.Time(), # TIME
- 16 : lambda r: sqltypes.Numeric(precision=r['FPREC'], length=r['FSCALE'] * -1) #INT64
- }
tblqry = """
SELECT DISTINCT R.RDB$FIELD_NAME AS FNAME,
R.RDB$NULL_FLAG AS NULL_FLAG,
R.RDB$FIELD_POSITION,
- F.RDB$FIELD_TYPE AS FTYPE,
+ T.RDB$TYPE_NAME AS FTYPE,
F.RDB$FIELD_SUB_TYPE AS STYPE,
F.RDB$FIELD_LENGTH AS FLEN,
F.RDB$FIELD_PRECISION AS FPREC,
F.RDB$FIELD_SCALE AS FSCALE
FROM RDB$RELATION_FIELDS R
- JOIN RDB$FIELDS F ON R.RDB$FIELD_SOURCE=F.RDB$FIELD_NAME
+ JOIN RDB$FIELDS F
+ ON R.RDB$FIELD_SOURCE=F.RDB$FIELD_NAME
+ JOIN RDB$TYPES T
+ ON T.RDB$TYPE=F.RDB$FIELD_TYPE AND T.RDB$FIELD_NAME='RDB$FIELD_TYPE'
WHERE F.RDB$SYSTEM_FLAG=0 and R.RDB$RELATION_NAME=?
ORDER BY R.RDB$FIELD_POSITION"""
keyqry = """
kw = {}
# get the data types and lengths
- coltype = column_func.get(row['FTYPE'], None)
+ coltype = ischema_names.get(row['FTYPE'].rstrip())
if coltype is None:
warnings.warn(RuntimeWarning("Did not recognize type '%s' of column '%s'" % (str(row['FTYPE']), name)))
coltype = sqltypes.NULLTYPE
import testbase
from sqlalchemy import *
from sqlalchemy.databases import firebird
+from sqlalchemy.exceptions import ProgrammingError
from sqlalchemy.sql import table, column
from testlib import *
return True
+class DomainReflectionTest(AssertMixin):
+ "Test Firebird domains"
+
+ @testing.supported('firebird')
+ def setUpAll(self):
+ con = testbase.db.connect()
+ try:
+ con.execute('CREATE DOMAIN int_domain AS INTEGER DEFAULT 42 NOT NULL')
+ con.execute('CREATE DOMAIN str_domain AS VARCHAR(255)')
+ con.execute('CREATE DOMAIN rem_domain AS BLOB SUB_TYPE TEXT')
+ con.execute('CREATE DOMAIN img_domain AS BLOB SUB_TYPE BINARY')
+ except ProgrammingError, e:
+ if not "attempt to store duplicate value" in str(e):
+ raise e
+ con.execute('''CREATE TABLE testtable (question int_domain,
+ answer str_domain,
+ remark rem_domain,
+ photo img_domain,
+ d date,
+ t time,
+ dt timestamp)''')
+
+ @testing.supported('firebird')
+ def tearDownAll(self):
+ con = testbase.db.connect()
+ con.execute('DROP TABLE testtable')
+ con.execute('DROP DOMAIN int_domain')
+ con.execute('DROP DOMAIN str_domain')
+ con.execute('DROP DOMAIN rem_domain')
+ con.execute('DROP DOMAIN img_domain')
+
+ @testing.supported('firebird')
+ def test_table_is_reflected(self):
+ metadata = MetaData(testbase.db)
+ table = Table('testtable', metadata, autoload=True)
+ self.assertEquals(set(table.columns.keys()),
+ set(['question', 'answer', 'remark', 'photo', 'd', 't', 'dt']),
+ "Columns of reflected table didn't equal expected columns")
+ self.assertEquals(table.c.question.type.__class__, firebird.FBInteger)
+ self.assertEquals(table.c.answer.type.__class__, firebird.FBString)
+ self.assertEquals(table.c.remark.type.__class__, firebird.FBText)
+ self.assertEquals(table.c.photo.type.__class__, firebird.FBBinary)
+ # The following assume a Dialect 3 database
+ self.assertEquals(table.c.d.type.__class__, firebird.FBDate)
+ self.assertEquals(table.c.t.type.__class__, firebird.FBTime)
+ self.assertEquals(table.c.dt.type.__class__, firebird.FBDateTime)
+
class CompileTest(SQLCompileTest):
__dialect__ = firebird.FBDialect()