Commits

Andrew Godwin committed 916f747

Fix tests and SQLite backend for alter_column behaviour and boolean defaults.

Comments (0)

Files changed (2)

south/db/sqlite3.py

     # SQLite ignores several constraints. I wish I could.
     supports_foreign_keys = False
     has_check_constraints = False
+    has_booleans = False
 
     def add_column(self, table_name, name, field, *args, **kwds):
         """
                 type += " NOT NULL"
             if indexes[name]['unique'] and name not in uniques_deleted:
                 type += " UNIQUE"
-
             if column_info['dflt_value'] is not None:
                 type += " DEFAULT " + column_info['dflt_value']
-
             # Deal with a rename
             if name in renames:
                 name = renames[name]
             # Add to the defs
             definitions[name] = type
         # Add on altered columns
-        definitions.update(altered)
+        for name, type in altered.items():
+            print name, type
+            if (primary_key_override and primary_key_override == name) or \
+               (not primary_key_override and indexes[name]['primary_key']):
+                type += " PRIMARY KEY"
+            if indexes[name]['unique'] and name not in uniques_deleted:
+                type += " UNIQUE"
+            definitions[name] = type
         # Add on the new columns
-        definitions.update(added)
+        for name, type in added.items():
+            if (primary_key_override and primary_key_override == name):
+                type += " PRIMARY KEY"
+            definitions[name] = type
         # Alright, Make the table
         self.execute("CREATE TABLE %s (%s)" % (
             self.quote_name(temp_name),
                 self._create_unique(table_name, columns)
     
     def _column_sql_for_create(self, table_name, name, field, explicit_name=True):
-        "Given a field and its name, returns the full type for the CREATE TABLE."
+        "Given a field and its name, returns the full type for the CREATE TABLE (without unique/pk)"
         field.set_attributes_from_name(name)
         if not explicit_name:
             name = field.db_column
         else:
             field.column = name
         sql = self.column_sql(table_name, name, field, with_name=False, field_prepared=True)
-        #if field.primary_key:
-        #    sql += " PRIMARY KEY"
-        #if field.unique:
-        #    sql += " UNIQUE"
+        # Remove keywords we don't want (this should be type only, not constraint)
+        sql = sql.replace("PRIMARY KEY", "")
         return sql
     
     def alter_column(self, table_name, name, field, explicit_name=True, ignore_constraints=False):
     # No cascades on deletes
     def delete_table(self, table_name, cascade=True):
         generic.DatabaseOperations.delete_table(self, table_name, False)
+
+    def _default_value_workaround(self, default):
+        if default == True:
+            default = 1
+        elif default == False:
+            default = 0
+        return default

south/tests/db.py

     
     def test_primary_key_implicit(self):
         """
-        Tests changing primary key implicitly.
+        Tests that changing primary key implicitly fails.
         """
-        
-        # This is ONLY important for SQLite. It's not a feature we support, but
-        # not implementing it means SQLite fails (due to the table-copying weirdness).
-        if db.backend_name != "sqlite3":
-            return
-        
         db.create_table("test_pki", [
             ('id', models.IntegerField(primary_key=True)),
             ('new_pkey', models.IntegerField()),
             ('eggs', models.IntegerField(unique=True)),
         ])
         db.execute_deferred_sql()
-        # Remove the default primary key, and make eggs it
+        # Fiddle with alter_column to attempt to make it remove the primary key
         db.alter_column("test_pki", "id", models.IntegerField())
         db.alter_column("test_pki", "new_pkey", models.IntegerField(primary_key=True))
-        # Try inserting a now-valid row pair
+        # Try inserting a should-be-valid row pair
         db.execute("INSERT INTO test_pki (id, new_pkey, eggs) VALUES (1, 2, 3)")
-        db.execute("INSERT INTO test_pki (id, new_pkey, eggs) VALUES (1, 3, 4)")
+        db.execute("INSERT INTO test_pki (id, new_pkey, eggs) VALUES (2, 2, 4)")
         db.delete_table("test_pki")
     
     def test_add_columns(self):
         db.execute_deferred_sql()
         
         # Make sure the unique constraint is created
-        db.execute('INSERT INTO test_alter_unique VALUES (0, 42)')
+        db.execute('INSERT INTO test_alter_unique (spam, eggs) VALUES (0, 42)')
         db.commit_transaction()
         db.start_transaction()
         try:
-            db.execute("INSERT INTO test_alter_unique VALUES (1, 42)")
+            db.execute("INSERT INTO test_alter_unique (spam, eggs) VALUES (1, 42)")
         except:
             pass
         else:
         # Insertion should still fail
         db.start_transaction()
         try:
-            db.execute("INSERT INTO test_alter_unique VALUES (1, 42)")
+            db.execute("INSERT INTO test_alter_unique (spam, eggs) VALUES (1, 42)")
         except:
             pass
         else:
         Tests that the value constraint of PositiveIntegerField is enforced on
         the database level.
         """
+        if not db.has_check_constraints:
+            return
+        
         db.create_table("test_column_constraint", [
             ('spam', models.PositiveIntegerField()),
         ])
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.