From 73c98a67ef4ed605cf69e0d212934c4dc1f3eb8e Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 19 Jul 2011 13:42:18 +0200 Subject: New design for NULL semantics Now, instead of being specified as part of the SQL type with the type pragma, there are separate null and not_null pragmas. The not_null pragma was used to control NULL-ness of object pointers. Now the two pragmas are used consistently for object pointers and simple values (and in the future will work for composite values and containers). --- odb/relational/type-processor.cxx | 93 +++++++++++++++++++++++++++++---------- 1 file changed, 69 insertions(+), 24 deletions(-) (limited to 'odb/relational/type-processor.cxx') diff --git a/odb/relational/type-processor.cxx b/odb/relational/type-processor.cxx index f7b0b2a..0f1c1d2 100644 --- a/odb/relational/type-processor.cxx +++ b/odb/relational/type-processor.cxx @@ -131,14 +131,7 @@ namespace relational type = idt.get ("type"); if (type.empty ()) - { - column_type_flags f (ctf_none); - - if (null_pointer (m)) - f |= ctf_default_null; - - type = database_type (idt, id.belongs ().hint (), id, f); - } + type = database_type (idt, id.belongs ().hint (), true); } else { @@ -149,12 +142,22 @@ namespace relational type = t.get ("type"); if (type.empty ()) - type = database_type (t, m.belongs ().hint (), m, ctf_none); + type = database_type (t, m.belongs ().hint (), m.count ("id")); } if (!type.empty ()) { m.set ("column-type", type); + + // Issue a warning if we are relaxing null-ness. + // + if (m.count ("null") && m.type ().count ("not-null")) + { + os << m.file () << ":" << m.line () << ":" << m.column () << ":" + << " warning: data member declared null while its type is " + << "declared not null" << endl; + } + return; } @@ -221,14 +224,7 @@ namespace relational type = idt.get ("type"); if (type.empty ()) - { - column_type_flags f (ctf_none); - - if (null_pointer (m, prefix)) - f |= ctf_default_null; - - type = database_type (idt, id.belongs ().hint (), id, f); - } + type = database_type (idt, id.belongs ().hint (), true); } else { @@ -236,7 +232,7 @@ namespace relational type = t.get ("type"); if (type.empty ()) - type = database_type (t, hint, m, ctf_none); + type = database_type (t, hint, false); } if (!type.empty ()) @@ -366,6 +362,10 @@ namespace relational t.set ("container-kind", ck); + // Mark id column as not null. + // + t.set ("id-not-null", string ()); + // Get the value type. // try @@ -404,6 +404,33 @@ namespace relational t.set ("value-tree-type", vt); t.set ("value-tree-hint", vh); + // If we have a set container, automatically mark the value + // column as not null. If we already have an explicit null for + // this column, issue an error. + // + if (ck == ck_set) + { + if (t.count ("value-null")) + { + os << t.file () << ":" << t.line () << ":" << t.column () << ":" + << " error: set container cannot contain null values" << endl; + + throw generation_failed (); + } + else + t.set ("value-not-null", string ()); + } + + // Issue a warning if we are relaxing null-ness in the + // container type. + // + if (t.count ("value-null") && vt->count ("not-null")) + { + os << t.file () << ":" << t.line () << ":" << t.column () << ":" + << " warning: container value declared null while its type " + << "is declared not null" << endl; + } + // Get the index type for ordered containers. // if (ck == ck_ordered) @@ -443,6 +470,7 @@ namespace relational t.set ("index-tree-type", it); t.set ("index-tree-hint", ih); + t.set ("index-not-null", string ()); } // Get the key type for maps. @@ -484,6 +512,7 @@ namespace relational t.set ("key-tree-type", kt); t.set ("key-tree-hint", kh); + t.set ("key-not-null", string ()); } } @@ -507,6 +536,28 @@ namespace relational if (ck == ck_ordered && m.count ("value-inverse")) m.set ("unordered", string ()); // Keep compatible with pragma. + // Issue an error if we have a null column in a set container. + // This can only happen if the value is declared as null in + // the member. + // + if (ck == ck_set && m.count ("value-null")) + { + os << m.file () << ":" << m.line () << ":" << m.column () << ":" + << " error: set container cannot contain null values" << endl; + + throw generation_failed (); + } + + // Issue a warning if we are relaxing null-ness in the member. + // + if (m.count ("value-null") && + (t.count ("value-not-null") || vt->count ("not-null"))) + { + os << m.file () << ":" << m.line () << ":" << m.column () << ":" + << " warning: container value declared null while the container " + << "type or value type declares it as not null" << endl; + } + return true; } @@ -729,12 +780,6 @@ namespace relational throw generation_failed (); } - if (m.count ("not-null") && !kp.empty ()) - { - m.remove ("not-null"); - m.set (kp + "-not-null", string ()); // Keep compatible with pragma. - } - // See if this is the inverse side of a bidirectional relationship. // If so, then resolve the member and cache it in the context. // -- cgit v1.1