summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2013-12-27 13:40:55 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2013-12-27 13:40:55 -0500
commit17f4b8f829df4bd6e65dd845fde6a75fe9178561 (patch)
tree31bd99b1047e3d582242818041f0aa517eee214b
parentff47daf233894fdc3735c78b1a1170f96cfcd7e8 (diff)
parent92a1426c06c49f5b3db8cc41afe0ed92e8631972 (diff)
downloadsqlalchemy-17f4b8f829df4bd6e65dd845fde6a75fe9178561.tar.gz
Merge branch 'master' into rel_0_9
-rw-r--r--doc/build/changelog/changelog_08.rst24
-rw-r--r--lib/sqlalchemy/dialects/firebird/base.py3
-rw-r--r--lib/sqlalchemy/dialects/firebird/kinterbasdb.py9
-rw-r--r--lib/sqlalchemy/testing/requirements.py14
-rw-r--r--lib/sqlalchemy/testing/suite/test_insert.py16
-rw-r--r--lib/sqlalchemy/testing/suite/test_reflection.py6
-rw-r--r--test/dialect/test_firebird.py9
-rw-r--r--test/requirements.py32
8 files changed, 105 insertions, 8 deletions
diff --git a/doc/build/changelog/changelog_08.rst b/doc/build/changelog/changelog_08.rst
index 0f3737d53..2e6bc153c 100644
--- a/doc/build/changelog/changelog_08.rst
+++ b/doc/build/changelog/changelog_08.rst
@@ -12,6 +12,30 @@
:version: 0.8.5
.. change::
+ :tags: bug, firebird
+ :versions: 0.9.0b2
+ :tickets: 2897
+
+ The firebird dialect will quote identifiers which begin with an
+ underscore. Courtesy Treeve Jelbert.
+
+ .. change::
+ :tags: bug, firebird
+ :versions: 0.9.0b2
+
+ Fixed bug in Firebird index reflection where the columns within the
+ index were not sorted correctly; they are now sorted
+ in order of RDB$FIELD_POSITION.
+
+ .. change::
+ :tags: bug, firebird
+ :versions: 0.9.0b2
+
+ The "asdecimal" flag used with the :class:`.Float` type will now
+ work with Firebird dialects; previously the decimal conversion was
+ not occurring.
+
+ .. change::
:tags: bug, mssql, pymssql
:versions: 0.9.0b2
:pullreq: github:51
diff --git a/lib/sqlalchemy/dialects/firebird/base.py b/lib/sqlalchemy/dialects/firebird/base.py
index dcaa68f4e..777d3ce26 100644
--- a/lib/sqlalchemy/dialects/firebird/base.py
+++ b/lib/sqlalchemy/dialects/firebird/base.py
@@ -359,6 +359,7 @@ class FBIdentifierPreparer(sql.compiler.IdentifierPreparer):
"""Install Firebird specific reserved words."""
reserved_words = RESERVED_WORDS
+ illegal_initial_characters = compiler.ILLEGAL_INITIAL_CHARACTERS.union(['_'])
def __init__(self, dialect):
super(FBIdentifierPreparer, self).__init__(dialect, omit_schema=True)
@@ -700,7 +701,7 @@ class FBDialect(default.DefaultDialect):
ic.rdb$index_name
WHERE ix.rdb$relation_name=? AND ix.rdb$foreign_key IS NULL
AND rdb$relation_constraints.rdb$constraint_type IS NULL
- ORDER BY index_name, field_name
+ ORDER BY index_name, ic.rdb$field_position
"""
c = connection.execute(qry, [self.denormalize_name(table_name)])
diff --git a/lib/sqlalchemy/dialects/firebird/kinterbasdb.py b/lib/sqlalchemy/dialects/firebird/kinterbasdb.py
index c8d8e986f..4b083deeb 100644
--- a/lib/sqlalchemy/dialects/firebird/kinterbasdb.py
+++ b/lib/sqlalchemy/dialects/firebird/kinterbasdb.py
@@ -42,7 +42,7 @@ from re import match
import decimal
-class _FBNumeric_kinterbasdb(sqltypes.Numeric):
+class _kinterbasdb_numeric(object):
def bind_processor(self, dialect):
def process(value):
if isinstance(value, decimal.Decimal):
@@ -51,6 +51,12 @@ class _FBNumeric_kinterbasdb(sqltypes.Numeric):
return value
return process
+class _FBNumeric_kinterbasdb(_kinterbasdb_numeric, sqltypes.Numeric):
+ pass
+
+class _FBFloat_kinterbasdb(_kinterbasdb_numeric, sqltypes.Float):
+ pass
+
class FBExecutionContext_kinterbasdb(FBExecutionContext):
@property
@@ -74,6 +80,7 @@ class FBDialect_kinterbasdb(FBDialect):
FBDialect.colspecs,
{
sqltypes.Numeric: _FBNumeric_kinterbasdb,
+ sqltypes.Float: _FBFloat_kinterbasdb,
}
)
diff --git a/lib/sqlalchemy/testing/requirements.py b/lib/sqlalchemy/testing/requirements.py
index e48fa2c00..3e48ba026 100644
--- a/lib/sqlalchemy/testing/requirements.py
+++ b/lib/sqlalchemy/testing/requirements.py
@@ -139,6 +139,20 @@ class SuiteRequirements(Requirements):
return exclusions.open()
@property
+ def fetch_rows_post_commit(self):
+ """target platform will allow cursor.fetchone() to proceed after a
+ COMMIT.
+
+ Typically this refers to an INSERT statement with RETURNING which
+ is invoked within "autocommit". If the row can be returned
+ after the autocommit, then this rule can be open.
+
+ """
+
+ return exclusions.open()
+
+
+ @property
def empty_inserts(self):
"""target platform supports INSERT with no values, i.e.
INSERT DEFAULT VALUES or equivalent."""
diff --git a/lib/sqlalchemy/testing/suite/test_insert.py b/lib/sqlalchemy/testing/suite/test_insert.py
index 21141f244..deda63b24 100644
--- a/lib/sqlalchemy/testing/suite/test_insert.py
+++ b/lib/sqlalchemy/testing/suite/test_insert.py
@@ -172,7 +172,8 @@ class ReturningTest(fixtures.TablesTest):
Column('data', String(50))
)
- def test_explicit_returning_pk(self):
+ @requirements.fetch_rows_post_commit
+ def test_explicit_returning_pk_autocommit(self):
engine = config.db
table = self.tables.autoinc_pk
r = engine.execute(
@@ -184,6 +185,19 @@ class ReturningTest(fixtures.TablesTest):
fetched_pk = config.db.scalar(select([table.c.id]))
eq_(fetched_pk, pk)
+ def test_explicit_returning_pk_no_autocommit(self):
+ engine = config.db
+ table = self.tables.autoinc_pk
+ with engine.begin() as conn:
+ r = conn.execute(
+ table.insert().returning(
+ table.c.id),
+ data="some data"
+ )
+ pk = r.first()[0]
+ fetched_pk = config.db.scalar(select([table.c.id]))
+ eq_(fetched_pk, pk)
+
def test_autoincrement_on_insert_implcit_returning(self):
config.db.execute(
diff --git a/lib/sqlalchemy/testing/suite/test_reflection.py b/lib/sqlalchemy/testing/suite/test_reflection.py
index 5a8a54c46..228bf44ce 100644
--- a/lib/sqlalchemy/testing/suite/test_reflection.py
+++ b/lib/sqlalchemy/testing/suite/test_reflection.py
@@ -180,6 +180,12 @@ class ComponentReflectionTest(fixtures.TablesTest):
def test_get_view_names_with_schema(self):
self._test_get_table_names('test_schema', table_type='view')
+ @testing.requires.table_reflection
+ @testing.requires.view_reflection
+ def test_get_tables_and_views(self):
+ self._test_get_table_names()
+ self._test_get_table_names(table_type='view')
+
def _test_get_columns(self, schema=None, table_type='table'):
meta = MetaData(testing.db)
users, addresses, dingalings = self.tables.users, \
diff --git a/test/dialect/test_firebird.py b/test/dialect/test_firebird.py
index 4a71b7d05..222e34b93 100644
--- a/test/dialect/test_firebird.py
+++ b/test/dialect/test_firebird.py
@@ -352,6 +352,15 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL):
for type_, args, kw, res in columns:
self.assert_compile(type_(*args, **kw), res)
+ def test_quoting_initial_chars(self):
+ self.assert_compile(
+ column("_somecol"),
+ '"_somecol"'
+ )
+ self.assert_compile(
+ column("$somecol"),
+ '"$somecol"'
+ )
class TypesTest(fixtures.TestBase):
__only_on__ = 'firebird'
diff --git a/test/requirements.py b/test/requirements.py
index b6fca06ed..b90591a80 100644
--- a/test/requirements.py
+++ b/test/requirements.py
@@ -123,6 +123,18 @@ class DefaultRequirements(SuiteRequirements):
)
@property
+ def insert_from_select(self):
+ return skip_if(
+ ["firebird"], "crashes for unknown reason"
+ )
+
+ @property
+ def fetch_rows_post_commit(self):
+ return skip_if(
+ ["firebird"], "not supported"
+ )
+
+ @property
def binary_comparisons(self):
"""target database/driver can allow BLOB/BINARY fields to be compared
against a bound parameter value.
@@ -503,10 +515,10 @@ class DefaultRequirements(SuiteRequirements):
"""target backend supports Decimal() objects using E notation
to represent very large values."""
- return fails_if(
- ("sybase+pyodbc", None, None,
+ return skip_if(
+ [("sybase+pyodbc", None, None,
"Don't know how do get these values through FreeTDS + Sybase"),
- ("firebird", None, None, "Precision must be from 1 to 18"),
+ ("firebird", None, None, "Precision must be from 1 to 18"),]
)
@property
@@ -545,11 +557,21 @@ class DefaultRequirements(SuiteRequirements):
"""target backend will return native floating point numbers with at
least seven decimal places when using the generic Float type."""
- return fails_if('mysql', 'mysql FLOAT type only returns 4 decimals')
+ return fails_if([
+ ('mysql', None, None,
+ 'mysql FLOAT type only returns 4 decimals'),
+ ('firebird', None, None,
+ "firebird FLOAT type isn't high precision"),
+ ])
@property
def floats_to_four_decimals(self):
- return fails_if("mysql+oursql", "Floating point error")
+ return fails_if([
+ ("mysql+oursql", None, None, "Floating point error"),
+ ("firebird", None, None,
+ "Firebird still has FP inaccuracy even "
+ "with only four decimal places")
+ ])
@property
def python2(self):