aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2012-09-04 11:22:07 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2012-09-04 11:22:07 +0200
commitc1877f84f3596f67245abe6658b08c050bd1e686 (patch)
tree57ae8ba5818a752abc763b1510b296a4a46d1ad4
parente288ee241317773c77d954c8c286f53a963e7c19 (diff)
NULL handling improvements
Add support for specifying NULL-ness for types with built-in mapping. Handle Oracle [N]VARCHAR2 and SQLite FLOAT oddities using this mechanism instead of overriding it at the schema generation level. Also use the is_null argument that is passed to value_traits::init_image() to indicate whether the value can be NULL.
-rw-r--r--doc/manual.xhtml26
-rw-r--r--odb/context.cxx77
-rw-r--r--odb/context.hxx26
-rw-r--r--odb/relational/mssql/context.cxx48
-rw-r--r--odb/relational/mysql/context.cxx44
-rw-r--r--odb/relational/oracle/context.cxx46
-rw-r--r--odb/relational/oracle/schema.cxx44
-rw-r--r--odb/relational/pgsql/context.cxx44
-rw-r--r--odb/relational/source.hxx6
-rw-r--r--odb/relational/sqlite/context.cxx42
10 files changed, 217 insertions, 186 deletions
diff --git a/doc/manual.xhtml b/doc/manual.xhtml
index ab0ab65..a1e0360 100644
--- a/doc/manual.xhtml
+++ b/doc/manual.xhtml
@@ -13878,13 +13878,13 @@ class object
<tr>
<td><code>float</code></td>
<td><code>REAL</code></td>
- <td><code>NOT NULL</code></td>
+ <td><code>NULL</code></td>
</tr>
<tr>
<td><code>double</code></td>
<td><code>REAL</code></td>
- <td><code>NOT NULL</code></td>
+ <td><code>NULL</code></td>
</tr>
<tr>
@@ -13894,6 +13894,14 @@ class object
</tr>
</table>
+ <p>SQLite represents <code>NaN</code> <code>FLOAT</code> values
+ as <code>NULL</code> values. As a result, columns of the
+ <code>float</code> and <code>double</code> types are by default
+ declared as <code>NULL</code>. However, you can override this by
+ explicitly declaring them as <code>NOT NULL</code> with the
+ <code>db&nbsp;not_null</code> pragma (<a href="#12.4.6">Section
+ 12.4.6, "<code>null/not_null</code>"</a>).</p>
+
<p>The SQLite ODB runtime library also provides support for mapping the
<code>std::vector&lt;char></code>,
<code>std::vector&lt;unsigned&nbsp;char></code>,
@@ -15344,13 +15352,13 @@ class object
<p>In Oracle empty <code>VARCHAR2</code> and <code>NVARCHAR2</code>
strings are represented as <code>NULL</code> values. As a result,
- in the generated schema, columns of these types are declared as
- <code>NULL</code> even if explicitly declared as
- <code>NOT NULL</code> with the <code>db&nbsp;not_null</code> pragma
- (<a href="#12.4.6">Section 12.4.6, "<code>null/not_null</code>"</a>),
- except for primary key columns. This also means that for object ids
- that are mapped to these Oracle types, an empty string is an invalid
- value.</p>
+ columns of the <code>std::string</code> type are by default declared
+ as <code>NULL</code> except for primary key columns. However, you
+ can override this by explicitly declaring them as <code>NOT NULL</code>
+ with the <code>db&nbsp;not_null</code> pragma (<a href="#12.4.6">Section
+ 12.4.6, "<code>null/not_null</code>"</a>). This also means that for
+ object ids that are mapped to these Oracle types, an empty string is
+ an invalid value.</p>
<p>The Oracle ODB runtime library also provides support for mapping the
<code>std::string</code> type to the Oracle <code>CHAR</code>,
diff --git a/odb/context.cxx b/odb/context.cxx
index 6b59033..fab5432 100644
--- a/odb/context.cxx
+++ b/odb/context.cxx
@@ -580,7 +580,7 @@ readonly (semantics::data_member& m)
}
bool context::
-null (data_member_path const& mp)
+null (data_member_path const& mp) const
{
// Outer members can override the null-ability of the inner ones. So
// start from the most outer member.
@@ -595,9 +595,10 @@ null (data_member_path const& mp)
}
bool context::
-null (semantics::data_member& m)
+null (semantics::data_member& m) const
{
- semantics::type& t (utype (m));
+ semantics::names* hint;
+ semantics::type& t (utype (m, hint));
if (object_pointer (t))
{
@@ -612,9 +613,7 @@ null (semantics::data_member& m)
return true;
if (!t.count ("not-null"))
- {
return true;
- }
}
return false;
@@ -633,6 +632,8 @@ null (semantics::data_member& m)
if (!t.count ("not-null"))
{
+ semantics::type* pt;
+
// Check if this type is a wrapper.
//
if (t.get<bool> ("wrapper"))
@@ -645,9 +646,25 @@ null (semantics::data_member& m)
// Otherwise, check the wrapped type.
//
- if (t.get<semantics::type*> ("wrapper-type")->count ("null"))
+ pt = t.get<semantics::type*> ("wrapper-type");
+ hint = t.get<semantics::names*> ("wrapper-hint");
+ pt = &utype (*pt, hint);
+
+ if (pt->count ("null"))
return true;
+
+ if (pt->count ("not-null"))
+ return false;
}
+ else
+ pt = &t;
+
+ // See if this is one of the types with built-in mapping.
+ //
+ type_map_type::const_iterator i (data_->type_map_.find (*pt, hint));
+
+ if (i != data_->type_map_.end ())
+ return i->second.null;
}
}
@@ -656,13 +673,14 @@ null (semantics::data_member& m)
}
bool context::
-null (semantics::data_member& m, string const& kp)
+null (semantics::data_member& m, string const& kp) const
{
if (kp.empty ())
return null (m);
semantics::type& c (utype (m));
semantics::type& t (member_utype (m, kp));
+ semantics::names* hint (0); // No hint for container elements.
if (object_pointer (t))
{
@@ -705,6 +723,8 @@ null (semantics::data_member& m, string const& kp)
if (!t.count ("not-null"))
{
+ semantics::type* pt;
+
// Check if this type is a wrapper.
//
if (t.get<bool> ("wrapper"))
@@ -717,12 +737,25 @@ null (semantics::data_member& m, string const& kp)
// Otherwise, check the wrapped type.
//
- semantics::type& wt (
- utype (*t.get<semantics::type*> ("wrapper-type")));
+ pt = t.get<semantics::type*> ("wrapper-type");
+ hint = t.get<semantics::names*> ("wrapper-hint");
+ pt = &utype (*pt, hint);
- if (wt.count ("null"))
+ if (pt->count ("null"))
return true;
+
+ if (pt->count ("not-null"))
+ return false;
}
+ else
+ pt = &t;
+
+ // See if this is one of the types with built-in mapping.
+ //
+ type_map_type::const_iterator i (data_->type_map_.find (*pt, hint));
+
+ if (i != data_->type_map_.end ())
+ return i->second.null;
}
}
}
@@ -1511,28 +1544,36 @@ column_options (semantics::data_member& m, string const& kp)
return r;
}
-string context::
-database_type_impl (semantics::type& t, semantics::names* hint, bool id)
+context::type_map_type::const_iterator context::type_map_type::
+find (semantics::type& t, semantics::names* hint)
{
- type_map_type::const_iterator end (data_->type_map_.end ()), i (end);
+ const_iterator e (end ()), i (e);
// First check the hinted name. This allows us to handle things like
// size_t which is nice to map to the same type irrespective of the
// actual type. Since this type can be an alias for the one we are
// interested in, go into nested hints.
//
- for (; hint != 0 && i == end; hint = hint->hint ())
+ for (; hint != 0 && i == e; hint = hint->hint ())
{
- i = data_->type_map_.find (t.fq_name (hint));
+ i = base::find (t.fq_name (hint));
}
// If the hinted name didn't work, try the primary name (e.g.,
// ::std::string) instead of a user typedef (e.g., my_string).
//
- if (i == end)
- i = data_->type_map_.find (t.fq_name ());
+ if (i == e)
+ i = base::find (t.fq_name ());
+
+ return i;
+}
+
+string context::
+database_type_impl (semantics::type& t, semantics::names* hint, bool id)
+{
+ type_map_type::const_iterator i (data_->type_map_.find (t, hint));
- if (i != end)
+ if (i != data_->type_map_.end ())
return id ? i->second.id_type : i->second.type;
else
return string ();
diff --git a/odb/context.hxx b/odb/context.hxx
index 3651344..dc5eb05 100644
--- a/odb/context.hxx
+++ b/odb/context.hxx
@@ -502,14 +502,14 @@ public:
// Null-able.
//
- static bool
- null (data_member_path const&);
+ bool
+ null (data_member_path const&) const;
- static bool
- null (semantics::data_member&);
+ bool
+ null (semantics::data_member&) const;
- static bool
- null (semantics::data_member&, string const& key_prefix);
+ bool
+ null (semantics::data_member&, string const& key_prefix) const;
// Optimistic concurrency.
//
@@ -911,15 +911,23 @@ public:
struct db_type_type
{
db_type_type () {}
- db_type_type (string const& t, string const& it)
- : type (t), id_type (it)
+ db_type_type (string const& t, string const& it, bool n)
+ : type (t), id_type (it), null (n)
{
}
string type;
string id_type;
+ bool null;
+ };
+
+ struct type_map_type: std::map<string, db_type_type>
+ {
+ typedef std::map<string, db_type_type> base;
+
+ const_iterator
+ find (semantics::type&, semantics::names* hint);
};
- typedef std::map<string, db_type_type> type_map_type;
protected:
struct data
diff --git a/odb/relational/mssql/context.cxx b/odb/relational/mssql/context.cxx
index efd8f2f..df6d6fc 100644
--- a/odb/relational/mssql/context.cxx
+++ b/odb/relational/mssql/context.cxx
@@ -20,43 +20,44 @@ namespace relational
{
struct type_map_entry
{
- const char* const cxx_type;
- const char* const db_type;
- const char* const db_id_type;
+ char const* const cxx_type;
+ char const* const db_type;
+ char const* const db_id_type;
+ bool const null;
};
type_map_entry type_map[] =
{
- {"bool", "BIT", 0},
+ {"bool", "BIT", 0, false},
- {"char", "TINYINT", 0},
- {"signed char", "TINYINT", 0},
- {"unsigned char", "TINYINT", 0},
+ {"char", "TINYINT", 0, false},
+ {"signed char", "TINYINT", 0, false},
+ {"unsigned char", "TINYINT", 0, false},
- {"short int", "SMALLINT", 0},
- {"short unsigned int", "SMALLINT", 0},
+ {"short int", "SMALLINT", 0, false},
+ {"short unsigned int", "SMALLINT", 0, false},
- {"int", "INT", 0},
- {"unsigned int", "INT", 0},
+ {"int", "INT", 0, false},
+ {"unsigned int", "INT", 0, false},
- {"long int", "BIGINT", 0},
- {"long unsigned int", "BIGINT", 0},
+ {"long int", "BIGINT", 0, false},
+ {"long unsigned int", "BIGINT", 0, false},
- {"long long int", "BIGINT", 0},
- {"long long unsigned int", "BIGINT", 0},
+ {"long long int", "BIGINT", 0, false},
+ {"long long unsigned int", "BIGINT", 0, false},
- {"float", "REAL", 0},
- {"double", "FLOAT", 0},
+ {"float", "REAL", 0, false},
+ {"double", "FLOAT", 0, false},
- {"::std::string", "VARCHAR(512)", "VARCHAR(256)"},
- {"::std::wstring", "NVARCHAR(512)", "NVARCHAR(256)"},
+ {"::std::string", "VARCHAR(512)", "VARCHAR(256)", false},
+ {"::std::wstring", "NVARCHAR(512)", "NVARCHAR(256)", false},
- {"::size_t", "BIGINT", 0},
- {"::std::size_t", "BIGINT", 0},
+ {"::size_t", "BIGINT", 0, false},
+ {"::std::size_t", "BIGINT", 0, false},
// Windows GUID/UUID (typedef struct _GUID {...} GUID, UUID;).
//
- {"::_GUID", "UNIQUEIDENTIFIER", 0}
+ {"::_GUID", "UNIQUEIDENTIFIER", 0, false}
};
}
@@ -97,7 +98,8 @@ namespace relational
type_map_type::value_type v (
e.cxx_type,
- db_type_type (e.db_type, e.db_id_type ? e.db_id_type : e.db_type));
+ db_type_type (
+ e.db_type, e.db_id_type ? e.db_id_type : e.db_type, e.null));
data_->type_map_.insert (v);
}
diff --git a/odb/relational/mysql/context.cxx b/odb/relational/mysql/context.cxx
index 1e44b34..8bf700e 100644
--- a/odb/relational/mysql/context.cxx
+++ b/odb/relational/mysql/context.cxx
@@ -21,38 +21,39 @@ namespace relational
{
struct type_map_entry
{
- const char* const cxx_type;
- const char* const db_type;
- const char* const db_id_type;
+ char const* const cxx_type;
+ char const* const db_type;
+ char const* const db_id_type;
+ bool const null;
};
type_map_entry type_map[] =
{
- {"bool", "TINYINT(1)", 0},
+ {"bool", "TINYINT(1)", 0, false},
- {"char", "TINYINT", 0},
- {"signed char", "TINYINT", 0},
- {"unsigned char", "TINYINT UNSIGNED", 0},
+ {"char", "TINYINT", 0, false},
+ {"signed char", "TINYINT", 0, false},
+ {"unsigned char", "TINYINT UNSIGNED", 0, false},
- {"short int", "SMALLINT", 0},
- {"short unsigned int", "SMALLINT UNSIGNED", 0},
+ {"short int", "SMALLINT", 0, false},
+ {"short unsigned int", "SMALLINT UNSIGNED", 0, false},
- {"int", "INT", 0},
- {"unsigned int", "INT UNSIGNED", 0},
+ {"int", "INT", 0, false},
+ {"unsigned int", "INT UNSIGNED", 0, false},
- {"long int", "BIGINT", 0},
- {"long unsigned int", "BIGINT UNSIGNED", 0},
+ {"long int", "BIGINT", 0, false},
+ {"long unsigned int", "BIGINT UNSIGNED", 0, false},
- {"long long int", "BIGINT", 0},
- {"long long unsigned int", "BIGINT UNSIGNED", 0},
+ {"long long int", "BIGINT", 0, false},
+ {"long long unsigned int", "BIGINT UNSIGNED", 0, false},
- {"float", "FLOAT", 0},
- {"double", "DOUBLE", 0},
+ {"float", "FLOAT", 0, false},
+ {"double", "DOUBLE", 0, false},
- {"::std::string", "TEXT", "VARCHAR(255)"},
+ {"::std::string", "TEXT", "VARCHAR(255)", false},
- {"::size_t", "BIGINT UNSIGNED", 0},
- {"::std::size_t", "BIGINT UNSIGNED", 0}
+ {"::size_t", "BIGINT UNSIGNED", 0, false},
+ {"::std::size_t", "BIGINT UNSIGNED", 0, false}
};
}
@@ -94,7 +95,8 @@ namespace relational
type_map_type::value_type v (
e.cxx_type,
- db_type_type (e.db_type, e.db_id_type ? e.db_id_type : e.db_type));
+ db_type_type (
+ e.db_type, e.db_id_type ? e.db_id_type : e.db_type, e.null));
data_->type_map_.insert (v);
}
diff --git a/odb/relational/oracle/context.cxx b/odb/relational/oracle/context.cxx
index 01b690a..4ba8659 100644
--- a/odb/relational/oracle/context.cxx
+++ b/odb/relational/oracle/context.cxx
@@ -20,38 +20,41 @@ namespace relational
{
struct type_map_entry
{
- const char* const cxx_type;
- const char* const db_type;
- const char* const db_id_type;
+ char const* const cxx_type;
+ char const* const db_type;
+ char const* const db_id_type;
+ bool const null;
};
type_map_entry type_map[] =
{
- {"bool", "NUMBER(1)", 0},
+ {"bool", "NUMBER(1)", 0, false},
- {"char", "NUMBER(3)", 0},
- {"signed char", "NUMBER(3)", 0},
- {"unsigned char", "NUMBER(3)", 0},
+ {"char", "NUMBER(3)", 0, false},
+ {"signed char", "NUMBER(3)", 0, false},
+ {"unsigned char", "NUMBER(3)", 0, false},
- {"short int", "NUMBER(5)", 0},
- {"short unsigned int", "NUMBER(5)", 0},
+ {"short int", "NUMBER(5)", 0, false},
+ {"short unsigned int", "NUMBER(5)", 0, false},
- {"int", "NUMBER(10)", 0},
- {"unsigned int", "NUMBER(10)", 0},
+ {"int", "NUMBER(10)", 0, false},
+ {"unsigned int", "NUMBER(10)", 0, false},
- {"long int", "NUMBER(19)", 0},
- {"long unsigned int", "NUMBER(20)", 0},
+ {"long int", "NUMBER(19)", 0, false},
+ {"long unsigned int", "NUMBER(20)", 0, false},
- {"long long int", "NUMBER(19)", 0},
- {"long long unsigned int", "NUMBER(20)", 0},
+ {"long long int", "NUMBER(19)", 0, false},
+ {"long long unsigned int", "NUMBER(20)", 0, false},
- {"float", "BINARY_FLOAT", 0},
- {"double", "BINARY_DOUBLE", 0},
+ {"float", "BINARY_FLOAT", 0, false},
+ {"double", "BINARY_DOUBLE", 0, false},
- {"::std::string", "VARCHAR2(512)", 0},
+ // Oracle treats empty VARCHAR2 (and NVARCHAR2) strings as NULL.
+ //
+ {"::std::string", "VARCHAR2(512)", 0, true},
- {"::size_t", "NUMBER(20)", 0},
- {"::std::size_t", "NUMBER(20)", 0}
+ {"::size_t", "NUMBER(20)", 0, false},
+ {"::std::size_t", "NUMBER(20)", 0, false}
};
}
@@ -92,7 +95,8 @@ namespace relational
type_map_type::value_type v (
e.cxx_type,
- db_type_type (e.db_type, e.db_id_type ? e.db_id_type : e.db_type));
+ db_type_type (
+ e.db_type, e.db_id_type ? e.db_id_type : e.db_type, e.null));
data_->type_map_.insert (v);
}
diff --git a/odb/relational/oracle/schema.cxx b/odb/relational/oracle/schema.cxx
index 29c1130..f07e0d6 100644
--- a/odb/relational/oracle/schema.cxx
+++ b/odb/relational/oracle/schema.cxx
@@ -159,50 +159,6 @@ namespace relational
};
entry<create_table> create_table_;
- struct create_column: relational::create_column, context
- {
- create_column (base const& x): base (x) {}
-
- virtual void
- null (sema_rel::column& c)
- {
- // Oracle interprets empty VARCHAR2 and NVARCHAR2 strings as
- // NULL. As an empty string is valid within the C++ context,
- // VARCHAR2 and NVARCHAR2 columns are always specified as
- // nullable, except when are a part of a primary key.
- //
- if (!c.null ())
- {
- // This should never fail since we have already parsed this.
- //
- sql_type const& t (parse_sql_type (c.type ()));
-
- if (t.type == sql_type::VARCHAR2 || t.type == sql_type::NVARCHAR2)
- {
- // See if this column is a part of a primary key.
- //
- bool pk (false);
-
- for (sema_rel::column::contained_iterator i (
- c.contained_begin ()); i != c.contained_end (); ++i)
- {
- if (i->key ().is_a<sema_rel::primary_key> ())
- {
- pk = true;
- break;
- }
- }
-
- if (!pk)
- return;
- }
- }
-
- base::null (c);
- }
- };
- entry<create_column> create_column_;
-
struct create_foreign_key: relational::create_foreign_key, context
{
create_foreign_key (schema_format f, relational::create_table& ct)
diff --git a/odb/relational/pgsql/context.cxx b/odb/relational/pgsql/context.cxx
index bed0d1a..391c65e 100644
--- a/odb/relational/pgsql/context.cxx
+++ b/odb/relational/pgsql/context.cxx
@@ -21,38 +21,39 @@ namespace relational
{
struct type_map_entry
{
- const char* const cxx_type;
- const char* const db_type;
- const char* const db_id_type;
+ char const* const cxx_type;
+ char const* const db_type;
+ char const* const db_id_type;
+ bool const null;
};
type_map_entry type_map[] =
{
- {"bool", "BOOLEAN", 0},
+ {"bool", "BOOLEAN", 0, false},
- {"char", "SMALLINT", 0},
- {"signed char", "SMALLINT", 0},
- {"unsigned char", "SMALLINT", 0},
+ {"char", "SMALLINT", 0, false},
+ {"signed char", "SMALLINT", 0, false},
+ {"unsigned char", "SMALLINT", 0, false},
- {"short int", "SMALLINT", 0},
- {"short unsigned int", "SMALLINT", 0},
+ {"short int", "SMALLINT", 0, false},
+ {"short unsigned int", "SMALLINT", 0, false},
- {"int", "INTEGER", 0},
- {"unsigned int", "INTEGER", 0},
+ {"int", "INTEGER", 0, false},
+ {"unsigned int", "INTEGER", 0, false},
- {"long int", "BIGINT", 0},
- {"long unsigned int", "BIGINT", 0},
+ {"long int", "BIGINT", 0, false},
+ {"long unsigned int", "BIGINT", 0, false},
- {"long long int", "BIGINT", 0},
- {"long long unsigned int", "BIGINT", 0},
+ {"long long int", "BIGINT", 0, false},
+ {"long long unsigned int", "BIGINT", 0, false},
- {"float", "REAL", 0},
- {"double", "DOUBLE PRECISION", 0},
+ {"float", "REAL", 0, false},
+ {"double", "DOUBLE PRECISION", 0, false},
- {"::std::string", "TEXT", 0},
+ {"::std::string", "TEXT", 0, false},
- {"::size_t", "BIGINT", 0},
- {"::std::size_t", "BIGINT", 0}
+ {"::size_t", "BIGINT", 0, false},
+ {"::std::size_t", "BIGINT", 0, false}
};
}
@@ -94,7 +95,8 @@ namespace relational
type_map_type::value_type v (
e.cxx_type,
- db_type_type (e.db_type, e.db_id_type ? e.db_id_type : e.db_type));
+ db_type_type (
+ e.db_type, e.db_id_type ? e.db_id_type : e.db_type, e.null));
data_->type_map_.insert (v);
}
diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx
index 3ad463b..21954e0 100644
--- a/odb/relational/source.hxx
+++ b/odb/relational/source.hxx
@@ -1298,7 +1298,11 @@ namespace relational
else
{
type = mi.fq_type ();
- os << "bool is_null;";
+
+ // Indicate to the value_traits whether this column can be NULL.
+ //
+ os << "bool is_null (" <<
+ (null (mi.m, key_prefix_) ? "true" : "false") << ");";
}
if (comp)
diff --git a/odb/relational/sqlite/context.cxx b/odb/relational/sqlite/context.cxx
index faaa3b5..52c7751 100644
--- a/odb/relational/sqlite/context.cxx
+++ b/odb/relational/sqlite/context.cxx
@@ -22,35 +22,38 @@ namespace relational
{
struct type_map_entry
{
- const char* const cxx_type;
- const char* const db_type;
- const char* const db_id_type;
+ char const* const cxx_type;
+ char const* const db_type;
+ char const* const db_id_type;
+ bool const null;
};
type_map_entry type_map[] =
{
- {"bool", "INTEGER", 0},
+ {"bool", "INTEGER", 0, false},
- {"char", "INTEGER", 0},
- {"signed char", "INTEGER", 0},
- {"unsigned char", "INTEGER", 0},
+ {"char", "INTEGER", 0, false},
+ {"signed char", "INTEGER", 0, false},
+ {"unsigned char", "INTEGER", 0, false},
- {"short int", "INTEGER", 0},
- {"short unsigned int", "INTEGER", 0},
+ {"short int", "INTEGER", 0, false},
+ {"short unsigned int", "INTEGER", 0, false},
- {"int", "INTEGER", 0},
- {"unsigned int", "INTEGER", 0},
+ {"int", "INTEGER", 0, false},
+ {"unsigned int", "INTEGER", 0, false},
- {"long int", "INTEGER", 0},
- {"long unsigned int", "INTEGER", 0},
+ {"long int", "INTEGER", 0, false},
+ {"long unsigned int", "INTEGER", 0, false},
- {"long long int", "INTEGER", 0},
- {"long long unsigned int", "INTEGER", 0},
+ {"long long int", "INTEGER", 0, false},
+ {"long long unsigned int", "INTEGER", 0, false},
- {"float", "REAL", 0},
- {"double", "REAL", 0},
+ // SQLite stores NaN as NULL.
+ //
+ {"float", "REAL", 0, true},
+ {"double", "REAL", 0, true},
- {"::std::string", "TEXT", 0}
+ {"::std::string", "TEXT", 0, false}
};
}
@@ -92,7 +95,8 @@ namespace relational
type_map_type::value_type v (
e.cxx_type,
- db_type_type (e.db_type, e.db_id_type ? e.db_id_type : e.db_type));
+ db_type_type (
+ e.db_type, e.db_id_type ? e.db_id_type : e.db_type, e.null));
data_->type_map_.insert (v);
}