Commits

Mike Bayer committed 17f4b8f Merge

Merge branch 'master' into rel_0_9

Comments (0)

Files changed (8)

doc/build/changelog/changelog_08.rst

     :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

lib/sqlalchemy/dialects/firebird/base.py

     """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)
                         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)])
 

lib/sqlalchemy/dialects/firebird/kinterbasdb.py

 import decimal
 
 
-class _FBNumeric_kinterbasdb(sqltypes.Numeric):
+class _kinterbasdb_numeric(object):
     def bind_processor(self, dialect):
         def process(value):
             if isinstance(value, decimal.Decimal):
                 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
         FBDialect.colspecs,
         {
             sqltypes.Numeric: _FBNumeric_kinterbasdb,
+            sqltypes.Float: _FBFloat_kinterbasdb,
         }
 
     )

lib/sqlalchemy/testing/requirements.py

         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."""

lib/sqlalchemy/testing/suite/test_insert.py

                 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(
         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(

lib/sqlalchemy/testing/suite/test_reflection.py

     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, \

test/dialect/test_firebird.py

         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'
 
             )
 
     @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.
         """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
         """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):