]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Composite PK table on InnoDB where the "autoincrement" column
authorMike Bayer <mike_mp@zzzcomputing.com>
Mon, 22 Feb 2010 19:28:25 +0000 (19:28 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Mon, 22 Feb 2010 19:28:25 +0000 (19:28 +0000)
isn't first will emit an explicit "KEY" phrase within
CREATE TABLE thereby avoiding errors, [ticket:1496]

CHANGES
lib/sqlalchemy/dialects/mysql/base.py
lib/sqlalchemy/sql/compiler.py
test/dialect/test_mysql.py

diff --git a/CHANGES b/CHANGES
index e8582ebf653c684c61b971c03bb8c94d56b20480..41761c207f3988dd77bf57f521c588d8c218d3b1 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -146,6 +146,10 @@ CHANGES
 
   - Further fixes for the mysql-connector dialect.  [ticket:1668]
   
+  - Composite PK table on InnoDB where the "autoincrement" column
+    isn't first will emit an explicit "KEY" phrase within 
+    CREATE TABLE thereby avoiding errors, [ticket:1496]
+    
 - mssql
   - Re-established initial support for pymssql.
  
index 686e3da6271752138d13e72b221d1587e1e63f56..4a4648076c48064654b1acd204e611ec9e8219be 100644 (file)
@@ -1269,6 +1269,26 @@ class MySQLCompiler(compiler.SQLCompiler):
 #       creation of foreign key constraints fails."
 
 class MySQLDDLCompiler(compiler.DDLCompiler):
+    def create_table_constraints(self, table):
+        """Get table constraints."""
+        constraint_string = super(MySQLDDLCompiler, self).create_table_constraints(table)
+        
+        is_innodb = table.kwargs.has_key('mysql_engine') and \
+                    table.kwargs['mysql_engine'].lower() == 'innodb'
+
+        auto_inc_column = table._autoincrement_column
+
+        if is_innodb and \
+                auto_inc_column is not None and \
+                auto_inc_column is not list(table.primary_key)[0]:
+            if constraint_string:
+                constraint_string += ", \n\t"
+            constraint_string += "KEY `idx_autoinc_%s`(`%s`)" % (auto_inc_column.name, \
+                            self.preparer.format_column(auto_inc_column))
+        
+        return constraint_string
+
+
     def get_column_specification(self, column, **kw):
         """Builds column DDL."""
 
index 187b4d26f02561998f487bc527bf588643325af7..32aa2a9920674ae795426a23048e467420549bb1 100644 (file)
@@ -1004,17 +1004,26 @@ class DDLCompiler(engine.Compiled):
             if const:
                 text += " " + const
 
+        const = self.create_table_constraints(table)
+        if const:
+            text += ", \n\t" + const
+
+        text += "\n)%s\n\n" % self.post_create_table(table)
+        return text
+
+    def create_table_constraints(self, table):
+        
         # On some DB order is significant: visit PK first, then the
         # other constraints (engine.ReflectionTest.testbasic failed on FB2)
+        constraints = []
         if table.primary_key:
-            pk = self.process(table.primary_key)
-            if pk:
-                text += ", \n\t" + pk
+            constraints.append(table.primary_key)
+            
+        constraints.extend([c for c in table.constraints if c is not table.primary_key])
         
-        const = ", \n\t".join(p for p in 
-                        (self.process(constraint) for constraint in table.constraints 
-                        if constraint is not table.primary_key
-                        and (
+        return ", \n\t".join(p for p in
+                        (self.process(constraint) for constraint in constraints 
+                        if (
                             constraint._create_rule is None or
                             constraint._create_rule(self))
                         and (
@@ -1022,11 +1031,6 @@ class DDLCompiler(engine.Compiled):
                             not getattr(constraint, 'use_alter', False)
                         )) if p is not None
                 )
-        if const:
-            text += ", \n\t" + const
-        
-        text += "\n)%s\n\n" % self.post_create_table(table)
-        return text
         
     def visit_drop_table(self, drop):
         ret = "\nDROP TABLE " + self.preparer.format_table(drop.element)
index 9fe859f1db2c6b42e384aca0842351bcd5fbe3aa..1bfaef317fde28e2fa61399e9b66521ba8cb7133 100644 (file)
@@ -1123,6 +1123,38 @@ class SQLTest(TestBase, AssertsCompiledSQL):
             select([extract('milliseconds', t.c.col1)]),
             "SELECT EXTRACT(millisecond FROM t.col1) AS anon_1 FROM t")
 
+    def test_innodb_autoincrement(self):
+        t1 = Table('sometable', MetaData(),
+                Column('assigned_id', Integer(), primary_key=True, autoincrement=False),
+                Column('id', Integer(), primary_key=True, autoincrement=True),
+                mysql_engine='InnoDB'
+        )
+
+        self.assert_compile(
+            schema.CreateTable(t1),
+            "CREATE TABLE sometable ("
+            "assigned_id INTEGER NOT NULL, "
+            "id INTEGER NOT NULL AUTO_INCREMENT, "
+            "PRIMARY KEY (assigned_id, id), "
+            "KEY `idx_autoinc_id`(`id`)"
+            ")ENGINE=InnoDB"
+        )
+
+        t1 = Table('sometable', MetaData(),
+                Column('assigned_id', Integer(), primary_key=True, autoincrement=True),
+                Column('id', Integer(), primary_key=True, autoincrement=False),
+                mysql_engine='InnoDB'
+        )
+
+        self.assert_compile(
+            schema.CreateTable(t1),
+            "CREATE TABLE sometable ("
+            "assigned_id INTEGER NOT NULL AUTO_INCREMENT, "
+            "id INTEGER NOT NULL, "
+            "PRIMARY KEY (assigned_id, id)"
+            ")ENGINE=InnoDB"
+        )
+
 
 class RawReflectionTest(TestBase):
     def setup(self):