Commits

Mike Bayer committed 34f1e2f

- [bug] Adjusted a very old bugfix which attempted
to work around a SQLite issue that itself was
"fixed" as of sqlite 3.6.14, regarding quotes
surrounding a table name when using
the "foreign_key_list" pragma. The fix has been
adjusted to not interfere with quotes that
are *actually in the name* of a column or table,
to as much a degree as possible; sqlite still
doesn't return the correct result for foreign_key_list()
if the target table actually has quotes surrounding
its name, as *part* of its name (i.e. """mytable""").
[ticket:2568]

Comments (0)

Files changed (3)

     the "name" and "native_enum" flags.  Helps
     Alembic autogenerate.
 
+- sqlite
+  - [bug] Adjusted a very old bugfix which attempted
+    to work around a SQLite issue that itself was
+    "fixed" as of sqlite 3.6.14, regarding quotes
+    surrounding a table name when using
+    the "foreign_key_list" pragma.  The fix has been
+    adjusted to not interfere with quotes that
+    are *actually in the name* of a column or table,
+    to as much a degree as possible; sqlite still
+    doesn't return the correct result for foreign_key_list()
+    if the target table actually has quotes surrounding
+    its name, as *part* of its name (i.e. """mytable""").
+    [ticket:2568]
+
 - mysql
   - [bug] Updated mysqlconnector interface to use
     updated "client flag" and "charset" APIs,

lib/sqlalchemy/dialects/sqlite/base.py

             (name, type_, nullable, default, has_default, primary_key) = \
                 (row[1], row[2].upper(), not row[3],
                 row[4], row[4] is not None, row[5])
-            name = re.sub(r'^\"|\"$', '', name)
             match = re.match(r'(\w+)(\(.*?\))?', type_)
             if match:
                 coltype = match.group(1)
             # was created with REFERENCES <tablename>, no col
             if rcol is None:
                 rcol = lcol
-            rtbl = re.sub(r'^\"|\"$', '', rtbl)
-            lcol = re.sub(r'^\"|\"$', '', lcol)
-            rcol = re.sub(r'^\"|\"$', '', rcol)
+
+            # see http://www.sqlalchemy.org/trac/ticket/2568
+            # as well as http://www.sqlite.org/src/info/600482d161
+            if self.dbapi.sqlite_version_info < (3, 6, 14):
+                rtbl = re.sub(r'^\"|\"$', '', rtbl)
+
             try:
                 fk = fks[numerical_id]
             except KeyError:

test/dialect/test_sqlite.py

         finally:
             meta.drop_all()
 
-    def test_quoted_identifiers(self):
+    @testing.provide_metadata
+    def test_quoted_identifiers_one(self):
         """Tests autoload of tables created with quoted column names."""
 
-        # This is quirky in sqlite.
-
+        metadata = self.metadata
         testing.db.execute("""CREATE TABLE "django_content_type" (
             "id" integer NOT NULL PRIMARY KEY,
             "django_stuff" text NULL
             "change_message" text NOT NULL
         )
         """)
-        try:
-            meta = MetaData(testing.db)
-            table1 = Table('django_admin_log', meta, autoload=True)
-            table2 = Table('django_content_type', meta, autoload=True)
-            j = table1.join(table2)
-            assert j.onclause.compare(table1.c.content_type_id
-                    == table2.c.id)
-        finally:
-            testing.db.execute('drop table django_admin_log')
-            testing.db.execute('drop table django_content_type')
+        table1 = Table('django_admin_log', metadata, autoload=True)
+        table2 = Table('django_content_type', metadata, autoload=True)
+        j = table1.join(table2)
+        assert j.onclause.compare(table1.c.content_type_id
+                == table2.c.id)
+
+    @testing.provide_metadata
+    def test_quoted_identifiers_two(self):
+        """"test the edgiest of edge cases, quoted table/col names
+        that start and end with quotes.
+
+        SQLite claims to have fixed this in
+        http://www.sqlite.org/src/info/600482d161, however
+        it still fails if the FK points to a table name that actually
+        has quotes as part of its name.
+
+        """
+
+        metadata = self.metadata
+        testing.db.execute(r'''CREATE TABLE """a""" (
+            """id""" integer NOT NULL PRIMARY KEY
+        )
+        ''')
+
+        # unfortunately, still can't do this; sqlite quadruples
+        # up the quotes on the table name here for pragma foreign_key_list
+        #testing.db.execute(r'''
+        #CREATE TABLE """b""" (
+        #    """id""" integer NOT NULL PRIMARY KEY,
+        #    """aid""" integer NULL
+        #           REFERENCES """a""" ("""id""")
+        #)
+        #''')
+
+        table1 = Table(r'"a"', metadata, autoload=True)
+        assert '"id"' in table1.c
+
+        #table2 = Table(r'"b"', metadata, autoload=True)
+        #j = table1.join(table2)
+        #assert j.onclause.compare(table1.c['"id"']
+        #        == table2.c['"aid"'])
 
     def test_attached_as_schema(self):
         cx = testing.db.connect()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.