Commits

shaib committed 247ecc3

Fix #1269: Make sure character fields are always created null=True on Oracle

  • Participants
  • Parent commits 4d30cf0

Comments (0)

Files changed (2)

south/db/oracle.py

 from django.db.backends.util import truncate_name
 from django.core.management.color import no_style
 from django.db.models.fields import NOT_PROVIDED
-from django.db.models import CharField, TextField
 from django.db.utils import DatabaseError
 
 # In revision r16016 function get_sequence_name has been transformed into
 
         for field_name, field in fields:
             
+            field = self._field_sanity(field)
+
             # avoid default values in CREATE TABLE statements (#925)
             field._suppress_default = True
 
+
             col = self.column_sql(table_name, field_name, field)
             if not col:
                 continue
             'nullity': 'NOT NULL',
             'default': 'NULL'
         }
-        if field.null or (isinstance(field, (CharField,TextField)) and field.empty_strings_allowed):
+        if field.null:
             params['nullity'] = 'NULL'
 
         sql_templates = [
         """
         renamed = self._generate_temp_name(name)
         self.rename_column(table_name, name, renamed)
-        if isinstance(field, TextField):
-            field.null = True # not-null not supported on LOBs
         self.add_column(table_name, name, field, keep_default=False)
         self.execute("UPDATE %s set %s=%s" % (
             self.quote_name(table_name),
 
     @generic.invalidate_table_constraints
     def add_column(self, table_name, name, field, keep_default=False):
+        field = self._field_sanity(field)
         sql = self.column_sql(table_name, name, field)
         sql = self.adj_column_sql(sql)
 
         """
         if isinstance(field, models.BooleanField) and field.has_default():
             field.default = int(field.to_python(field.get_default()))
+        # On Oracle, empty strings are null
+        if isinstance(field, (models.CharField, models.TextField)):
+            field.null = field.empty_strings_allowed
         return field
+
 
     def _default_value_workaround(self, value):
         from datetime import date,time,datetime

south/tests/db.py

         empty = db.execute("SELECT ham FROM test_cd_empty")[0][0]
         self.assertEquals(empty, "", "Empty Default for char field isn't empty string")
         
+    @skipUnless('oracle' in db.backend_name, "Oracle does not differentiate empty trings from null")
+    def test_oracle_strings_null(self):
+        """
+        Test that under Oracle, CherFields are created as null even when specified not-null,
+        because otherwise they would not be able to hold empty strings (which Oracle equates
+        with nulls).
+        Verify fix of #1269.
+        """
+        db.create_table("test_ora_char_nulls", [
+            ('spam', models.CharField(max_length=30, null=True)),
+            ('eggs', models.CharField(max_length=30)),
+        ])
+        db.add_column("test_ora_char_nulls", "ham", models.CharField(max_length=30))
+        db.alter_column("test_ora_char_nulls", "spam", models.CharField(max_length=30, null=False))
+        # So, by the look of it, we should now have three not-null columns
+        db.execute("INSERT INTO test_ora_char_nulls VALUES (NULL, NULL, NULL)")
+        
+
     def test_mysql_defaults(self):
         """
         Test MySQL default handling for BLOB and TEXT.