]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Support for three levels of column nullability: NULL, NOT NULL, and the database...
authorMichael Trier <mtrier@gmail.com>
Fri, 12 Dec 2008 04:49:24 +0000 (04:49 +0000)
committerMichael Trier <mtrier@gmail.com>
Fri, 12 Dec 2008 04:49:24 +0000 (04:49 +0000)
The default Column configuration (nullable=True) will now generate NULL in the DDL. Previously no specification was emitted and the database default would take effect (usually NULL, but not always).  To explicitly request the database default, configure columns with nullable=None and no specification will be emitted in DDL. Fixes #1243.

CHANGES
lib/sqlalchemy/databases/mssql.py
test/dialect/mssql.py

diff --git a/CHANGES b/CHANGES
index 007766a7af35faa87ca1a5ff81ee3825036e051e..3f97dc797d4676a2810c89d04dfe964be5c7bafb 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -169,6 +169,15 @@ CHANGES
     - Added experimental support of savepoints. It
       currently does not work fully with sessions.
 
+    - Support for three levels of column nullability: NULL, NOT NULL,
+      and the database's configured default.  The default Column
+      configuration (nullable=True) will now generate NULL in the DDL.
+      Previously no specification was emitted and the database default
+      would take effect (usually NULL, but not always).  To explicitly
+      request the database default, configure columns with
+      nullable=None and no specification will be emitted in DDL. This
+      is backwards incompatible behavior. [ticket:1243]
+
 - postgres
     - Calling alias.execute() in conjunction with
       server_side_cursors won't raise AttributeError.
index c4a773426fbe366d9755a8c295c27d1b9c9b6d55..5fb4361b99fd59dfafae976d7960c6703b1e9feb 100644 (file)
@@ -14,7 +14,7 @@
 
    CREATE TABLE test (
      id INTEGER NOT NULL IDENTITY(100,10) PRIMARY KEY,
-     name VARCHAR(20)
+     name VARCHAR(20) NULL,
      )
 
   Note that the start & increment values for sequences are optional
 
 * Experimental implemention of LIMIT / OFFSET with row_number()
 
+* Support for three levels of column nullability provided. The default
+  nullability allows nulls::
+
+    name VARCHAR(20) NULL
+
+  If ``nullable=None`` is specified then no specification is made. In other
+  words the database's configured default is used. This will render::
+
+    name VARCHAR(20)
+
+  If ``nullable`` is True or False then the column will be ``NULL` or
+  ``NOT NULL`` respectively.
+
 Known issues / TODO:
 
 * No support for more than one ``IDENTITY`` column per table
@@ -1069,8 +1082,11 @@ class MSSQLSchemaGenerator(compiler.SchemaGenerator):
             if column.default is None or (isinstance(column.default, schema.Sequence) and column.default.optional):
                 column.sequence = schema.Sequence(column.name + '_seq')
 
-        if not column.nullable:
-            colspec += " NOT NULL"
+        if column.nullable is not None:
+            if not column.nullable:
+                colspec += " NOT NULL"
+            else:
+                colspec += " NULL"
 
         if hasattr(column, 'sequence'):
             column.table.has_sequence = column
index 5a4b38f6e9137e8a80229b7fb59677fd9dba028c..5d97cf1484363b04ea07c75d8a161f9caf4d1aec 100755 (executable)
@@ -247,6 +247,48 @@ class GenerativeQueryTest(TestBase):
         assert list(query[:10]) == orig[:10]
         assert list(query[:10]) == orig[:10]
 
+
+class SchemaTest(TestBase):
+
+    def setUp(self):
+        self.column = Column('test_column', Integer)
+
+    def test_that_mssql_default_nullability_emits_null(self):
+        schemagenerator = \
+            mssql.MSSQLDialect().schemagenerator(mssql.MSSQLDialect(), None)
+        column_specification = \
+            schemagenerator.get_column_specification(self.column)
+        assert "test_column INTEGER NULL" == column_specification, \
+               column_specification
+
+    def test_that_mssql_none_nullability_does_not_emit_nullability(self):
+        schemagenerator = \
+            mssql.MSSQLDialect().schemagenerator(mssql.MSSQLDialect(), None)
+        self.column.nullable = None
+        column_specification = \
+            schemagenerator.get_column_specification(self.column)
+        assert "test_column INTEGER" == column_specification, \
+               column_specification
+
+    def test_that_mssql_specified_nullable_emits_null(self):
+        schemagenerator = \
+            mssql.MSSQLDialect().schemagenerator(mssql.MSSQLDialect(), None)
+        self.column.nullable = True
+        column_specification = \
+            schemagenerator.get_column_specification(self.column)
+        assert "test_column INTEGER NULL" == column_specification, \
+               column_specification
+
+    def test_that_mssql_specified_not_nullable_emits_not_null(self):
+        schemagenerator = \
+            mssql.MSSQLDialect().schemagenerator(mssql.MSSQLDialect(), None)
+        self.column.nullable = False
+        column_specification = \
+            schemagenerator.get_column_specification(self.column)
+        assert "test_column INTEGER NOT NULL" == column_specification, \
+               column_specification
+
+
 def full_text_search_missing():
     """Test if full text search is not implemented and return False if 
     it is and True otherwise."""