summaryrefslogtreecommitdiff
path: root/odb/relational/sqlite
diff options
context:
space:
mode:
Diffstat (limited to 'odb/relational/sqlite')
-rw-r--r--odb/relational/sqlite/common.cxx217
-rw-r--r--odb/relational/sqlite/common.hxx147
-rw-r--r--odb/relational/sqlite/context.cxx490
-rw-r--r--odb/relational/sqlite/context.hxx146
-rw-r--r--odb/relational/sqlite/header.cxx63
-rw-r--r--odb/relational/sqlite/inline.cxx42
-rw-r--r--odb/relational/sqlite/model.cxx91
-rw-r--r--odb/relational/sqlite/schema.cxx455
-rw-r--r--odb/relational/sqlite/source.cxx470
9 files changed, 0 insertions, 2121 deletions
diff --git a/odb/relational/sqlite/common.cxx b/odb/relational/sqlite/common.cxx
deleted file mode 100644
index 03a3599..0000000
--- a/odb/relational/sqlite/common.cxx
+++ /dev/null
@@ -1,217 +0,0 @@
-// file : odb/relational/sqlite/common.cxx
-// license : GNU GPL v3; see accompanying LICENSE file
-
-#include <cassert>
-
-#include <odb/relational/sqlite/common.hxx>
-
-using namespace std;
-
-namespace relational
-{
- namespace sqlite
- {
- //
- // member_base
- //
-
- sql_type const& member_base::
- member_sql_type (semantics::data_member& m)
- {
- return parse_sql_type (column_type (m, key_prefix_), m);
- }
-
- void member_base::
- traverse_simple (member_info& mi)
- {
- switch (mi.st->type)
- {
- case sql_type::INTEGER:
- {
- traverse_integer (mi);
- break;
- }
- case sql_type::REAL:
- {
- traverse_real (mi);
- break;
- }
- case sql_type::TEXT:
- {
- if (mi.st->stream)
- traverse_text_stream (mi);
- else
- traverse_text (mi);
- break;
- }
- case sql_type::BLOB:
- {
- if (mi.st->stream)
- traverse_blob_stream (mi);
- else
- traverse_blob (mi);
- break;
- }
- case sql_type::invalid:
- {
- assert (false);
- break;
- }
- }
- }
-
- //
- // member_image_type
- //
-
- member_image_type::
- member_image_type (base const& x)
- : member_base::base (x), // virtual base
- base (x) {}
-
- member_image_type::
- member_image_type ()
- : relational::member_base (0, 0, string (), string ()) {}
-
- member_image_type::
- member_image_type (semantics::type* type,
- const custom_cxx_type* ct,
- string const& fq_type,
- string const& key_prefix)
- : relational::member_base (type, ct, fq_type, key_prefix) {}
-
- string member_image_type::
- image_type (semantics::data_member& m)
- {
- type_.clear ();
- member_base::traverse (m, true);
- return type_;
- }
-
- void member_image_type::
- traverse_composite (member_info& mi)
- {
- type_ = "composite_value_traits< " + mi.fq_type () +
- ", id_sqlite >::image_type";
- }
-
- void member_image_type::
- traverse_integer (member_info&)
- {
- type_ = "long long";
- }
-
- void member_image_type::
- traverse_real (member_info&)
- {
- type_ = "double";
- }
-
- void member_image_type::
- traverse_string (member_info&)
- {
- type_ = "details::buffer";
- }
-
- void member_image_type::
- traverse_stream (member_info&)
- {
- type_ = "sqlite::stream_buffers";
- }
-
- entry<member_image_type> member_image_type_;
-
- //
- // member_database_type
- //
-
- member_database_type_id::
- member_database_type_id (base const& x)
- : member_base::base (x), // virtual base
- base (x) {}
-
- member_database_type_id::
- member_database_type_id ()
- : member_base::base (0, 0, string (), string ()), // virtual base
- base (0, 0, string (), string ()) {}
-
- member_database_type_id::
- member_database_type_id (semantics::type* type,
- const custom_cxx_type* ct,
- string const& fq_type,
- string const& key_prefix)
- : member_base::base (type, ct, fq_type, key_prefix), // virtual base
- base (type, ct, fq_type, key_prefix) {}
-
- string member_database_type_id::
- database_type_id (type& m)
- {
- type_id_.clear ();
- member_base::traverse (m, true);
- return type_id_;
- }
-
- void member_database_type_id::
- traverse_composite (member_info&)
- {
- assert (false);
- }
-
- void member_database_type_id::
- traverse_integer (member_info&)
- {
- type_id_ = "sqlite::id_integer";
- }
-
- void member_database_type_id::
- traverse_real (member_info&)
- {
- type_id_ = "sqlite::id_real";
- }
-
- void member_database_type_id::
- traverse_text (member_info&)
- {
- type_id_ = "sqlite::id_text";
- }
-
- void member_database_type_id::
- traverse_blob (member_info&)
- {
- type_id_ = "sqlite::id_blob";
- }
-
- void member_database_type_id::
- traverse_text_stream (member_info&)
- {
- type_id_ = "sqlite::id_text_stream";
- }
-
- void member_database_type_id::
- traverse_blob_stream (member_info&)
- {
- type_id_ = "sqlite::id_blob_stream";
- }
-
- entry<member_database_type_id> member_database_type_id_;
-
- //
- // query_columns
- //
-
- struct query_columns: relational::query_columns, context
- {
- query_columns (base const& x): base_impl (x) {}
-
- virtual string
- database_type_id (semantics::data_member& m)
- {
- return member_database_type_id_.database_type_id (m);
- }
-
- private:
- member_database_type_id member_database_type_id_;
- };
- entry<query_columns> query_columns_;
- }
-}
diff --git a/odb/relational/sqlite/common.hxx b/odb/relational/sqlite/common.hxx
deleted file mode 100644
index 4d6089e..0000000
--- a/odb/relational/sqlite/common.hxx
+++ /dev/null
@@ -1,147 +0,0 @@
-// file : odb/relational/sqlite/common.hxx
-// license : GNU GPL v3; see accompanying LICENSE file
-
-#ifndef ODB_RELATIONAL_SQLITE_COMMON_HXX
-#define ODB_RELATIONAL_SQLITE_COMMON_HXX
-
-#include <odb/relational/common.hxx>
-#include <odb/relational/sqlite/context.hxx>
-
-namespace relational
-{
- namespace sqlite
- {
- struct member_base: virtual relational::member_base_impl<sql_type>, context
- {
- member_base (base const& x): base (x), base_impl (x) {}
-
- // This c-tor is for the direct use inside the sqlite namespace.
- // If you do use this c-tor, you should also explicitly call
- // relational::member_base (aka base).
- //
- member_base () {}
-
- virtual sql_type const&
- member_sql_type (semantics::data_member&);
-
- virtual void
- traverse_simple (member_info&);
-
- virtual void
- traverse_integer (member_info&)
- {
- }
-
- virtual void
- traverse_real (member_info&)
- {
- }
-
- virtual void
- traverse_text (member_info& m)
- {
- traverse_string (m);
- }
-
- virtual void
- traverse_blob (member_info& m)
- {
- traverse_string (m);
- }
-
- // String covers both text and blob.
- //
- virtual void
- traverse_string (member_info&)
- {
- }
-
- virtual void
- traverse_text_stream (member_info& m)
- {
- traverse_stream (m);
- }
-
- virtual void
- traverse_blob_stream (member_info& m)
- {
- traverse_stream (m);
- }
-
- virtual void
- traverse_stream (member_info&)
- {
- }
- };
-
- struct member_image_type: relational::member_image_type,
- member_base
- {
- member_image_type (base const&);
- member_image_type ();
- member_image_type (semantics::type* type,
- const custom_cxx_type*,
- string const& fq_type = string (),
- string const& key_prefix = string ());
- virtual string
- image_type (semantics::data_member&);
-
- virtual void
- traverse_composite (member_info&);
-
- virtual void
- traverse_integer (member_info&);
-
- virtual void
- traverse_real (member_info&);
-
- virtual void
- traverse_string (member_info&);
-
- virtual void
- traverse_stream (member_info&);
-
- private:
- string type_;
- };
-
- struct member_database_type_id: relational::member_database_type_id,
- member_base
- {
- member_database_type_id (base const&);
- member_database_type_id ();
- member_database_type_id (semantics::type* type,
- const custom_cxx_type*,
- string const& fq_type = string (),
- string const& key_prefix = string ());
-
- virtual string
- database_type_id (type&);
-
- virtual void
- traverse_composite (member_info&);
-
- virtual void
- traverse_integer (member_info&);
-
- virtual void
- traverse_real (member_info&);
-
- virtual void
- traverse_text (member_info&);
-
- virtual void
- traverse_blob (member_info&);
-
- virtual void
- traverse_text_stream (member_info&);
-
- virtual void
- traverse_blob_stream (member_info&);
-
- private:
- string type_id_;
- };
- }
-}
-#endif // ODB_RELATIONAL_SQLITE_COMMON_HXX
diff --git a/odb/relational/sqlite/context.cxx b/odb/relational/sqlite/context.cxx
deleted file mode 100644
index 9a4369f..0000000
--- a/odb/relational/sqlite/context.cxx
+++ /dev/null
@@ -1,490 +0,0 @@
-// file : odb/relational/sqlite/context.cxx
-// license : GNU GPL v3; see accompanying LICENSE file
-
-#include <vector>
-#include <cassert>
-#include <sstream>
-
-#include <odb/sql-token.hxx>
-#include <odb/sql-lexer.hxx>
-
-#include <odb/relational/sqlite/context.hxx>
-#include <odb/relational/sqlite/common.hxx>
-
-using namespace std;
-
-namespace relational
-{
- namespace sqlite
- {
- namespace
- {
- struct type_map_entry
- {
- 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, false},
-
- {"char", "TEXT", 0, false},
- {"wchar_t", "TEXT", 0, false},
- {"signed char", "INTEGER", 0, false},
- {"unsigned char", "INTEGER", 0, false},
-
- {"short int", "INTEGER", 0, false},
- {"short unsigned int", "INTEGER", 0, false},
-
- {"int", "INTEGER", 0, false},
- {"unsigned int", "INTEGER", 0, false},
-
- {"long int", "INTEGER", 0, false},
- {"long unsigned int", "INTEGER", 0, false},
-
- {"long long int", "INTEGER", 0, false},
- {"long long unsigned int", "INTEGER", 0, false},
-
- // SQLite stores NaN as NULL.
- //
- {"float", "REAL", 0, true},
- {"double", "REAL", 0, true},
-
- {"::std::string", "TEXT", 0, false},
- {"::std::wstring", "TEXT", 0, false}
- };
- }
-
- context* context::current_;
-
- context::
- ~context ()
- {
- if (current_ == this)
- current_ = 0;
- }
-
- context::
- context (ostream& os,
- semantics::unit& u,
- options_type const& ops,
- features_type& f,
- sema_rel::model* m)
- : root_context (os, u, ops, f, data_ptr (new (shared) data (os))),
- base_context (static_cast<data*> (root_context::data_.get ()), m),
- data_ (static_cast<data*> (base_context::data_))
- {
- assert (current_ == 0);
- current_ = this;
-
- generate_grow = true;
- need_alias_as = true;
- insert_send_auto_id = true;
- delay_freeing_statement_result = false;
- need_image_clone = false;
- generate_bulk = false;
- global_index = true;
- global_fkey = false;
- data_->bind_vector_ = "sqlite::bind*";
- data_->truncated_vector_ = "bool*";
-
- // Populate the C++ type to DB type map.
- //
- for (size_t i (0); i < sizeof (type_map) / sizeof (type_map_entry); ++i)
- {
- type_map_entry const& e (type_map[i]);
-
- 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, e.null));
-
- data_->type_map_.insert (v);
- }
- }
-
- context::
- context ()
- : data_ (current ().data_)
- {
- }
-
- string const& context::
- convert_expr (string const& sqlt, semantics::data_member& m, bool to)
- {
- sql_type const& t (parse_sql_type (sqlt, m));
- return to ? t.to : t.from;
- }
-
- namespace
- {
- struct has_grow: traversal::class_
- {
- has_grow (bool& r, user_section* s)
- : r_ (r), section_ (s)
- {
- *this >> inherits_ >> *this;
- }
-
- virtual void
- traverse (type& c)
- {
- // Ignore transient bases.
- //
- if (!(context::object (c) || context::composite (c)))
- return;
-
- if (section_ == 0 && c.count ("sqlite-grow"))
- r_ = c.get<bool> ("sqlite-grow");
- else
- {
- // r_ should be false.
- //
- inherits (c);
-
- if (!r_)
- names (c);
-
- if (section_ == 0)
- c.set ("sqlite-grow", r_);
- }
- }
-
- private:
- bool& r_;
- user_section* section_;
- traversal::inherits inherits_;
- };
-
- struct has_grow_member: member_base
- {
- has_grow_member (bool& r, user_section* section = 0)
- : relational::member_base (0, 0, string (), string (), section),
- r_ (r) {}
-
- has_grow_member (bool& r,
- user_section* section,
- semantics::type* t,
- const custom_cxx_type* ct,
- string const& key_prefix = string ())
- : relational::member_base (t, ct, string (), key_prefix, section),
- r_ (r) {}
-
- virtual bool
- pre (member_info& mi)
- {
- // If we have a key prefix (container), then it can't be in a
- // section (while mi.m can). The same for top-level -- if we got
- // called, then we shouldn't ignore it.
- //
- return !key_prefix_.empty () || top_level_ ||
- (section_ == 0 && !separate_load (mi.m)) ||
- (section_ != 0 && *section_ == section (mi.m));
- }
-
- virtual void
- traverse_composite (member_info& mi)
- {
- // By calling grow() instead of recursing, we reset any overrides.
- // We also don't pass section since they don't apply inside
- // composites.
- //
- r_ = r_ || context::grow (dynamic_cast<semantics::class_&> (mi.t));
- }
-
- virtual void
- traverse_string (member_info&)
- {
- r_ = true;
- }
-
- private:
- bool& r_;
- };
- }
-
- bool context::
- grow_impl (semantics::class_& c, user_section* section)
- {
- if (section == 0 && c.count ("sqlite-grow"))
- return c.get<bool> ("sqlite-grow");
-
- bool r (false);
- has_grow ct (r, section);
- has_grow_member mt (r, section);
- traversal::names names;
- ct >> names >> mt;
- ct.traverse (c);
- return r;
- }
-
- bool context::
- grow_impl (semantics::data_member& m)
- {
- bool r (false);
- has_grow_member mt (r);
- mt.traverse (m, true);
- return r;
- }
-
- bool context::
- grow_impl (semantics::data_member& m,
- semantics::type& t,
- const custom_cxx_type* ct,
- string const& kp)
- {
- bool r (false);
- has_grow_member mt (r, 0, &t, ct, kp);
- mt.traverse (m, true);
- return r;
- }
-
- string context::
- database_type_impl (semantics::type& t,
- semantics::names* hint,
- bool id,
- bool* null)
- {
- string r (base_context::database_type_impl (t, hint, id, null));
-
- if (!r.empty ())
- return r;
-
- using semantics::array;
-
- // char[N] mapping.
- //
- if (array* a = dynamic_cast<array*> (&t))
- {
- semantics::type& bt (a->base_type ());
- if (bt.is_a<semantics::fund_char> () ||
- bt.is_a<semantics::fund_wchar> ())
- {
- if (a->size () != 0)
- r = "TEXT";
- }
- }
-
- return r;
- }
-
- //
- // SQL type parsing.
- //
-
- namespace
- {
- struct sql_parser
- {
- typedef context::invalid_sql_type invalid_sql_type;
-
- sql_parser (custom_db_types const* ct): ct_ (ct) {}
-
- sql_type
- parse (string sql)
- {
- sql_type r;
-
- // First run the type through the custom mapping, if requested.
- //
- if (ct_ != 0)
- {
- for (custom_db_types::const_iterator i (ct_->begin ());
- i != ct_->end (); ++i)
- {
- custom_db_type const& t (*i);
-
- if (t.type.match (sql))
- {
- r.to = t.type.replace (sql, t.to);
- r.from = t.type.replace (sql, t.from);
- sql = t.type.replace (sql, t.as);
- break;
- }
- }
- }
-
- // Parse the type into a sequence of identifiers.
- //
- try
- {
- l_.lex (sql);
-
- for (sql_token t (l_.next ()); t.type () != sql_token::t_eos;)
- {
- sql_token::token_type tt (t.type ());
-
- if (tt == sql_token::t_identifier)
- {
- ids_.push_back (context::upcase (t.identifier ()));
- t = l_.next ();
-
- if (t.punctuation () == sql_token::p_lparen)
- {
- if (!parse_range ())
- return error (m_);
-
- t = l_.next ();
- }
- }
- else
- return error ("expected SQLite type name instead of '" +
- t.string () + "'");
- }
- }
- catch (sql_lexer::invalid_input const& e)
- {
- return error ("invalid SQLite type declaration: " + e.message);
- }
-
- if (ids_.empty ())
- return error ("expected SQLite type name");
-
- // First check our own types.
- //
- if (ids_.size () == 2 && ids_[0] == "TEXT" && ids_[1] == "STREAM")
- {
- r.type = sql_type::TEXT;
- r.stream = true;
- }
- if (ids_.size () == 2 && ids_[0] == "BLOB" && ids_[1] == "STREAM")
- {
- r.type = sql_type::BLOB;
- r.stream = true;
- }
- //
- // Apply the first four rules of the SQLite type to affinity
- // conversion algorithm.
- //
- else if (find ("INT"))
- r.type = sql_type::INTEGER;
- else if (find ("TEXT") || find ("CHAR") || find ("CLOB"))
- r.type = sql_type::TEXT;
- else if (find ("BLOB"))
- r.type = sql_type::BLOB;
- else if (find ("REAL") || find ("FLOA") || find ("DOUB"))
- r.type = sql_type::REAL;
- else
- {
- // Instead of the fifth rule which maps everything else
- // to NUMERICAL (which we don't have), map some commonly
- // used type names to one of the above types.
- //
- string const& id (ids_[0]);
-
- if (id == "NUMERIC")
- r.type = sql_type::REAL;
- else if (id == "DECIMAL")
- r.type = sql_type::TEXT;
- else if (id == "BOOLEAN" || id == "BOOL")
- r.type = sql_type::INTEGER;
- else if (id == "DATE" || id == "TIME" || id == "DATETIME")
- r.type = sql_type::TEXT;
- else
- return error ("unknown SQLite type '" + id + "'");
- }
-
- return r;
- }
-
- bool
- parse_range ()
- {
- // Skip tokens until we get the closing paren.
- //
- for (sql_token t (l_.next ());; t = l_.next ())
- {
- if (t.punctuation () == sql_token::p_rparen)
- break;
-
- if (t.type () == sql_token::t_eos)
- {
- m_ = "missing ')' in SQLite type declaration";
- return false;
- }
- }
-
- return true;
- }
-
- private:
- sql_type
- error (string const& m)
- {
- if (ct_ == 0)
- return sql_type ();
- else
- throw invalid_sql_type (m);
- }
-
- bool
- find (string const& str) const
- {
- for (identifiers::const_iterator i (ids_.begin ());
- i != ids_.end (); ++i)
- {
- if (i->find (str) != string::npos)
- return true;
- }
-
- return false;
- }
-
- private:
- custom_db_types const* ct_;
- sql_lexer l_;
- string m_; // Error message.
-
- typedef vector<string> identifiers;
- identifiers ids_;
- };
- }
-
- sql_type const& context::
- parse_sql_type (string const& t, semantics::data_member& m, bool custom)
- {
- // If this proves to be too expensive, we can maintain a cache of
- // parsed types across contexts.
- //
- data::sql_type_cache::iterator i (data_->sql_type_cache_.find (t));
-
- if (i != data_->sql_type_cache_.end ()
- && (custom ? i->second.custom_cached : i->second.straight_cached))
- {
- return (custom ? i->second.custom : i->second.straight);
- }
- else
- {
- try
- {
- sql_type st (
- parse_sql_type (
- t,
- custom ? &unit.get<custom_db_types> ("custom-db-types") : 0));
-
- if (custom)
- return data_->sql_type_cache_[t].cache_custom (st);
- else
- return data_->sql_type_cache_[t].cache_straight (st);
- }
- catch (invalid_sql_type const& e)
- {
- cerr << m.file () << ":" << m.line () << ":" << m.column ()
- << ": error: " << e.message () << endl;
-
- throw operation_failed ();
- }
- }
- }
-
- sql_type context::
- parse_sql_type (string const& sqlt, custom_db_types const* ct)
- {
- sql_parser p (ct);
- return p.parse (sqlt);
- }
- }
-}
diff --git a/odb/relational/sqlite/context.hxx b/odb/relational/sqlite/context.hxx
deleted file mode 100644
index 777998b..0000000
--- a/odb/relational/sqlite/context.hxx
+++ /dev/null
@@ -1,146 +0,0 @@
-// file : odb/relational/sqlite/context.hxx
-// license : GNU GPL v3; see accompanying LICENSE file
-
-#ifndef ODB_RELATIONAL_SQLITE_CONTEXT_HXX
-#define ODB_RELATIONAL_SQLITE_CONTEXT_HXX
-
-#include <map>
-
-#include <odb/relational/context.hxx>
-
-namespace relational
-{
- namespace sqlite
- {
- struct sql_type
- {
- // Keep the order in each block of types.
- //
- enum core_type
- {
- INTEGER,
- REAL,
- TEXT,
- BLOB,
- invalid
- };
-
- sql_type (): type (invalid), stream (false) {}
-
- core_type type;
- bool stream; // TEXT or BLOB via sqlite3_blob_open().
-
- // Conversion expressions for custom database types.
- //
- std::string to;
- std::string from;
- };
-
- class context: public virtual relational::context
- {
- public:
- sql_type const&
- parse_sql_type (string const&,
- semantics::data_member&,
- bool custom = true);
- public:
- struct invalid_sql_type
- {
- invalid_sql_type (string const& message): message_ (message) {}
-
- string const&
- message () const {return message_;}
-
- private:
- string message_;
- };
-
- // If custom_db_types is NULL, then this function returns
- // invalid type instead of throwing in case an unknown type
- // is encountered.
- //
- static sql_type
- parse_sql_type (string const&, custom_db_types const* = 0);
-
- protected:
- virtual string const&
- convert_expr (string const&, semantics::data_member&, bool);
-
- virtual bool
- grow_impl (semantics::class_&, user_section*);
-
- virtual bool
- grow_impl (semantics::data_member&);
-
- virtual bool
- grow_impl (semantics::data_member&,
- semantics::type&,
- const custom_cxx_type*,
- string const&);
-
- protected:
- virtual string
- database_type_impl (semantics::type&, semantics::names*, bool, bool*);
-
- public:
- virtual
- ~context ();
- context ();
- context (std::ostream&,
- semantics::unit&,
- options_type const&,
- features_type& f,
- sema_rel::model*);
-
- static context&
- current ()
- {
- return *current_;
- }
-
- private:
- static context* current_;
-
- private:
- struct data: base_context::data
- {
- data (std::ostream& os): base_context::data (os) {}
-
- struct sql_type_cache_entry
- {
- sql_type_cache_entry ()
- : custom_cached (false), straight_cached (false) {}
-
- sql_type const&
- cache_custom (sql_type const& t)
- {
- custom = t;
- custom_cached = true;
- return custom;
- }
-
- sql_type const&
- cache_straight (sql_type const& t)
- {
- straight = t;
- straight_cached = true;
- return straight;
- }
-
- sql_type custom; // With custom mapping.
- sql_type straight; // Without custom mapping.
-
- bool custom_cached;
- bool straight_cached;
- };
-
- typedef std::map<string, sql_type_cache_entry> sql_type_cache;
- sql_type_cache sql_type_cache_;
- };
-
- data* data_;
- };
- }
-}
-
-#endif // ODB_RELATIONAL_SQLITE_CONTEXT_HXX
diff --git a/odb/relational/sqlite/header.cxx b/odb/relational/sqlite/header.cxx
deleted file mode 100644
index 1aafe7a..0000000
--- a/odb/relational/sqlite/header.cxx
+++ /dev/null
@@ -1,63 +0,0 @@
-// file : odb/relational/sqlite/header.cxx
-// license : GNU GPL v3; see accompanying LICENSE file
-
-#include <odb/relational/header.hxx>
-
-#include <odb/relational/sqlite/common.hxx>
-#include <odb/relational/sqlite/context.hxx>
-
-namespace relational
-{
- namespace sqlite
- {
- namespace header
- {
- namespace relational = relational::header;
-
- struct image_member: relational::image_member_impl<sql_type>,
- member_base
- {
- image_member (base const& x)
- : member_base::base (x), // virtual base
- member_base::base_impl (x), // virtual base
- base_impl (x),
- member_base (x) {}
-
- virtual void
- traverse_integer (member_info& mi)
- {
- os << image_type << " " << mi.var << "value;"
- << "bool " << mi.var << "null;"
- << endl;
- }
-
- virtual void
- traverse_real (member_info& mi)
- {
- os << image_type << " " << mi.var << "value;"
- << "bool " << mi.var << "null;"
- << endl;
- }
-
- virtual void
- traverse_string (member_info& mi)
- {
- os << image_type << " " << mi.var << "value;"
- << "std::size_t " << mi.var << "size;"
- << "bool " << mi.var << "null;"
- << endl;
- }
-
- virtual void
- traverse_stream (member_info& mi)
- {
- os << image_type << " " << mi.var << "value;"
- << "std::size_t " << mi.var << "size;"
- << "bool " << mi.var << "null;"
- << endl;
- }
- };
- entry<image_member> image_member_;
- }
- }
-}
diff --git a/odb/relational/sqlite/inline.cxx b/odb/relational/sqlite/inline.cxx
deleted file mode 100644
index dd3274f..0000000
--- a/odb/relational/sqlite/inline.cxx
+++ /dev/null
@@ -1,42 +0,0 @@
-// file : odb/relational/sqlite/inline.cxx
-// license : GNU GPL v3; see accompanying LICENSE file
-
-#include <odb/relational/inline.hxx>
-
-#include <odb/relational/sqlite/common.hxx>
-#include <odb/relational/sqlite/context.hxx>
-
-using namespace std;
-
-namespace relational
-{
- namespace sqlite
- {
- namespace inline_
- {
- namespace relational = relational::inline_;
-
- struct null_member: relational::null_member_impl<sql_type>,
- member_base
- {
- null_member (base const& x)
- : member_base::base (x), // virtual base
- member_base::base_impl (x), // virtual base
- base_impl (x),
- member_base (x)
- {
- }
-
- virtual void
- traverse_simple (member_info& mi)
- {
- if (get_)
- os << "r = r && i." << mi.var << "null;";
- else
- os << "i." << mi.var << "null = true;";
- }
- };
- entry<null_member> null_member_;
- }
- }
-}
diff --git a/odb/relational/sqlite/model.cxx b/odb/relational/sqlite/model.cxx
deleted file mode 100644
index da16ded..0000000
--- a/odb/relational/sqlite/model.cxx
+++ /dev/null
@@ -1,91 +0,0 @@
-// file : odb/relational/sqlite/model.cxx
-// license : GNU GPL v3; see accompanying LICENSE file
-
-#include <sstream>
-
-#include <odb/relational/model.hxx>
-
-#include <odb/relational/sqlite/common.hxx>
-#include <odb/relational/sqlite/context.hxx>
-
-using namespace std;
-
-namespace relational
-{
- namespace sqlite
- {
- namespace model
- {
- namespace relational = relational::model;
-
- struct object_columns: relational::object_columns, context
- {
- object_columns (base const& x): base (x) {}
-
- virtual string
- type (semantics::data_member& m)
- {
- // Translate BLOB|TEXT STREAM to just BLOB|TEXT.
- //
- string r (relational::object_columns::type (m));
-
- sql_type const& t (parse_sql_type (r, m, false));
- if (t.stream)
- {
- switch (t.type)
- {
- case sql_type::BLOB: r = "BLOB"; break;
- case sql_type::TEXT: r = "TEXT"; break;
- default: break;
- }
- }
-
- return r;
- }
-
- virtual bool
- null (semantics::data_member& m)
- {
- return options.sqlite_override_null () || base::null (m);
- }
-
- virtual string
- default_enum (semantics::data_member& m, tree en, string const&)
- {
- // Make sure the column is mapped to INTEGER.
- //
- sql_type const& t (parse_sql_type (column_type (), m, false));
- if (t.type != sql_type::INTEGER)
- {
- cerr << m.file () << ":" << m.line () << ":" << m.column ()
- << ": error: column with default value specified as C++ "
- << "enumerator must map to SQLite INTEGER" << endl;
-
- throw operation_failed ();
- }
-
- using semantics::enumerator;
-
- enumerator& e (dynamic_cast<enumerator&> (*unit.find (en)));
-
- ostringstream ostr;
-
- if (e.enum_ ().unsigned_ ())
- ostr << e.value ();
- else
- ostr << static_cast<long long> (e.value ());
-
- return ostr.str ();
- }
-
- virtual void
- primary_key (sema_rel::primary_key& pk)
- {
- if (pk.auto_ () && options.sqlite_lax_auto_id ())
- pk.extra ()["lax"] = "true";
- }
- };
- entry<object_columns> object_columns_;
- }
- }
-}
diff --git a/odb/relational/sqlite/schema.cxx b/odb/relational/sqlite/schema.cxx
deleted file mode 100644
index f5549b4..0000000
--- a/odb/relational/sqlite/schema.cxx
+++ /dev/null
@@ -1,455 +0,0 @@
-// file : odb/relational/sqlite/schema.cxx
-// license : GNU GPL v3; see accompanying LICENSE file
-
-#include <odb/relational/schema.hxx>
-
-#include <odb/relational/sqlite/common.hxx>
-#include <odb/relational/sqlite/context.hxx>
-
-namespace relational
-{
- namespace sqlite
- {
- namespace schema
- {
- namespace relational = relational::schema;
-
- //
- // Drop.
- //
-
- struct drop_column: trav_rel::drop_column, relational::common
- {
- drop_column (relational::common const& c)
- : relational::common (c), first_ (true) {}
-
- virtual void
- traverse (sema_rel::drop_column& dc)
- {
- // SQLite does not support dropping columns. If this column is
- // not NULLable, then there is nothing we can do. Otherwise, do
- // a logical DROP by setting all the values to NULL.
- //
- sema_rel::column& c (find<sema_rel::column> (dc));
-
- if (!c.null ())
- {
- cerr << "error: SQLite does not support dropping of columns" <<
- endl;
- cerr << "info: first dropped column is '" << dc.name () <<
- "' in table '" << dc.table ().name () << "'" << endl;
- cerr << "info: could have performed logical drop if the column " <<
- "allowed NULL values" << endl;
- throw operation_failed ();
- }
-
- if (first_)
- first_ = false;
- else
- os << "," << endl
- << " ";
-
- os << quote_id (dc.name ()) << " = NULL";
- }
-
- private:
- bool first_;
- };
- // Not registered as an override.
-
- struct drop_index: relational::drop_index, context
- {
- drop_index (base const& x): base (x) {}
-
- virtual string
- name (sema_rel::index& in)
- {
- // In SQLite, index names can be qualified with the database.
- //
- sema_rel::table& t (static_cast<sema_rel::table&> (in.scope ()));
- sema_rel::qname n (t.name ().qualifier ());
- n.append (in.name ());
- return quote_id (n);
- }
- };
- entry<drop_index> drop_index_;
-
- struct drop_table: relational::drop_table, context
- {
- drop_table (base const& x): base (x) {}
-
- virtual void
- traverse (sema_rel::table& t, bool migration)
- {
- // In SQLite there is no way to drop foreign keys except as part
- // of the table.
- //
- if (pass_ != 2)
- return;
-
- // Polymorphic base cleanup code. Because we cannot drop foreign
- // keys, we will trigger cascade deletion. The only way to work
- // around this problem is to delete from the root table and rely
- // on the cascade to clean up the rest.
- //
- if (migration && t.extra ()["kind"] == "polymorphic derived object")
- {
- using sema_rel::model;
- using sema_rel::table;
- using sema_rel::primary_key;
- using sema_rel::foreign_key;
-
- model& m (dynamic_cast<model&> (t.scope ()));
-
- table* p (&t);
- do
- {
- // The polymorphic link is the first primary key.
- //
- for (table::names_iterator i (p->names_begin ());
- i != p->names_end (); ++i)
- {
- if (foreign_key* fk = dynamic_cast<foreign_key*> (
- &i->nameable ()))
- {
- p = m.find<table> (fk->referenced_table ());
- assert (p != 0); // Base table should be there.
- break;
- }
- }
- }
- while (p->extra ()["kind"] != "polymorphic root object");
-
- primary_key& rkey (*p->find<primary_key> (""));
- primary_key& dkey (*t.find<primary_key> (""));
- assert (rkey.contains_size () == dkey.contains_size ());
- delete_ (p->name (), t.name (), rkey, dkey);
- }
-
- drop (t, migration);
- }
- };
- entry<drop_table> drop_table_;
-
- //
- // Create.
- //
-
- struct create_column: relational::create_column, context
- {
- create_column (base const& x): base (x) {}
-
- virtual void
- traverse (sema_rel::add_column& ac)
- {
- using sema_rel::alter_table;
- using sema_rel::add_column;
- using sema_rel::add_foreign_key;
-
- alter_table& at (static_cast<alter_table&> (ac.scope ()));
-
- pre_statement ();
-
- os << "ALTER TABLE " << quote_id (at.name ()) << endl
- << " ADD COLUMN ";
-
- // In SQLite it is impossible to alter a column later, so unless
- // it has a default value, we add it as NULL. Without this, it
- // will be impossible to add a column to a table that contains
- // some rows.
- //
- create (ac);
-
- // SQLite doesn't support adding foreign keys other than inline
- // via a column definition. See if we can handle any.
- //
- add_foreign_key* afk (0);
-
- for (add_column::contained_iterator i (ac.contained_begin ());
- i != ac.contained_end ();
- ++i)
- {
- if ((afk = dynamic_cast<add_foreign_key*> (&i->key ())))
- {
- // Check that it is a single-column foreign key. Also make
- // sure the column and foreign key are from the same changeset.
- //
- if (afk->contains_size () != 1 || &ac.scope () != &afk->scope ())
- afk = 0;
- else
- break;
- }
- }
-
- if (afk != 0)
- {
- os << " CONSTRAINT " << quote_id (afk->name ()) << " REFERENCES " <<
- quote_id (afk->referenced_table ().uname ()) << " (" <<
- quote_id (afk->referenced_columns ()[0]) << ")";
-
- bool del (afk->on_delete () != sema_rel::foreign_key::no_action);
- bool def (!afk->not_deferrable ());
-
- if (del || def)
- {
- instance<relational::create_foreign_key> cfk (*this);
-
- if (del)
- cfk->on_delete (afk->on_delete ());
-
- if (def)
- cfk->deferrable (afk->deferrable ());
- }
-
- afk->set ("sqlite-fk-defined", true); // Mark it as defined.
- }
-
- os << endl;
- post_statement ();
- }
-
- virtual void
- auto_ (sema_rel::primary_key& pk)
- {
- if (pk.extra ().count ("lax"))
- os << " /*AUTOINCREMENT*/";
- else
- os << " AUTOINCREMENT";
- }
- };
- entry<create_column> create_column_;
-
- struct create_foreign_key: relational::create_foreign_key, context
- {
- create_foreign_key (base const& x): base (x) {}
-
- virtual void
- traverse (sema_rel::foreign_key& fk)
- {
- // In SQLite, all constraints are defined as part of a table.
- //
- os << "," << endl
- << " CONSTRAINT ";
-
- create (fk);
- }
-
- virtual string
- table_name (sema_rel::foreign_key& fk)
- {
- // In SQLite, the referenced table cannot be qualified with the
- // database name (it has to be in the same database anyway).
- //
- return quote_id (fk.referenced_table ().uname ());
- }
- };
- entry<create_foreign_key> create_foreign_key_;
-
- struct create_index: relational::create_index, context
- {
- create_index (base const& x): base (x) {}
-
- virtual string
- name (sema_rel::index& in)
- {
- // In SQLite, index names can be qualified with the database.
- //
- sema_rel::table& t (static_cast<sema_rel::table&> (in.scope ()));
- sema_rel::qname n (t.name ().qualifier ());
- n.append (in.name ());
- return quote_id (n);
- }
-
- virtual string
- table_name (sema_rel::index& in)
- {
- // In SQLite, the index table cannot be qualified with the
- // database name (it has to be in the same database).
- //
- return quote_id (
- static_cast<sema_rel::table&> (in.scope ()).name ().uname ());
- }
- };
- entry<create_index> create_index_;
-
- struct create_table: relational::create_table, context
- {
- create_table (base const& x): base (x) {}
-
- void
- traverse (sema_rel::table& t)
- {
- // For SQLite we do everything in a single pass since there
- // is no way to add constraints later.
- //
- if (pass_ == 1)
- create (t);
- }
- };
- entry<create_table> create_table_;
-
- //
- // Alter.
- //
-
- struct alter_table_pre: relational::alter_table_pre, context
- {
- alter_table_pre (base const& x): base (x) {}
-
- virtual void
- alter (sema_rel::alter_table& at)
- {
- // SQLite can only add a single column per ALTER TABLE statement.
- //
- instance<create_column> cc (*this);
- trav_rel::unames n (*cc);
- names (at, n);
-
- // SQLite does not support altering columns.
- //
- if (sema_rel::alter_column* ac = check<sema_rel::alter_column> (at))
- {
- cerr << "error: SQLite does not support altering of columns"
- << endl;
- cerr << "info: first altered column is '" << ac->name () <<
- "' in table '" << at.name () << "'" << endl;
- throw operation_failed ();
- }
-
- // SQLite does not support dropping constraints. We are going to
- // ignore this if the column is NULL'able since in most cases
- // the constraint is going to be dropped as a result of the
- // column drop (e.g., an object pointer member got deleted).
- // If we were not to allow this, then it would be impossible
- // to do logical drop for pointer columns.
- //
- for (sema_rel::alter_table::names_iterator i (at.names_begin ());
- i != at.names_end (); ++i)
- {
- using sema_rel::foreign_key;
- using sema_rel::drop_foreign_key;
-
- drop_foreign_key* dfk (
- dynamic_cast<drop_foreign_key*> (&i->nameable ()));
-
- if (dfk == 0)
- continue;
-
- foreign_key& fk (find<foreign_key> (*dfk));
-
- for (foreign_key::contains_iterator j (fk.contains_begin ());
- j != fk.contains_end (); ++j)
- {
- if (j->column ().null ())
- continue;
-
- cerr << "error: SQLite does not support dropping of foreign " <<
- "keys" << endl;
- cerr << "info: first dropped foreign key is '" << dfk->name () <<
- "' in table '" << at.name () << "'" << endl;
- cerr << "info: could have ignored it if the contained " <<
- "column(s) allowed NULL values" << endl;
- throw operation_failed ();
- }
- }
- }
- };
- entry<alter_table_pre> alter_table_pre_;
-
- struct alter_table_post: relational::alter_table_post, context
- {
- alter_table_post (base const& x): base (x) {}
-
- virtual void
- alter (sema_rel::alter_table& at)
- {
- // SQLite does not support altering columns (we have to do this
- // in both alter_table_pre/post because of the
- // check_alter_column_null() test in the common code).
- //
- if (sema_rel::alter_column* ac = check<sema_rel::alter_column> (at))
- {
- cerr << "error: SQLite does not support altering of columns"
- << endl;
- cerr << "info: first altered column is '" << ac->name () <<
- "' in table '" << at.name () << "'" << endl;
- throw operation_failed ();
- }
-
- // Try to do logical column drop.
- //
- if (check<sema_rel::drop_column> (at))
- {
- pre_statement ();
-
- os << "UPDATE " << quote_id (at.name ()) << endl
- << " SET ";
-
- drop_column dc (*this);
- trav_rel::unames n (dc);
- names (at, n);
- os << endl;
-
- post_statement ();
- }
-
- // SQLite doesn't support adding foreign keys other than inline
- // via a column definition. See if there are any that we couldn't
- // handle that way.
- //
- for (sema_rel::alter_table::names_iterator i (at.names_begin ());
- i != at.names_end (); ++i)
- {
- sema_rel::add_foreign_key* afk (
- dynamic_cast<sema_rel::add_foreign_key*> (&i->nameable ()));
-
- if (afk == 0 || afk->count ("sqlite-fk-defined"))
- continue;
-
- cerr << "error: SQLite does not support adding foreign keys"
- << endl;
- cerr << "info: first added foreign key is '" << afk->name () <<
- "' in table '" << at.name () << "'" << endl;
- throw operation_failed ();
- }
- }
- };
- entry<alter_table_post> alter_table_post_;
-
- //
- // Schema version table.
- //
-
- struct version_table: relational::version_table, context
- {
- version_table (base const& x): base (x) {}
-
- virtual void
- create_table ()
- {
- pre_statement ();
-
- os << "CREATE TABLE IF NOT EXISTS " << qt_ << " (" << endl
- << " " << qn_ << " TEXT NOT NULL PRIMARY KEY," << endl
- << " " << qv_ << " INTEGER NOT NULL," << endl
- << " " << qm_ << " INTEGER NOT NULL)" << endl;
-
- post_statement ();
- }
-
- virtual void
- create (sema_rel::version v)
- {
- pre_statement ();
-
- os << "INSERT OR IGNORE INTO " << qt_ << " (" << endl
- << " " << qn_ << ", " << qv_ << ", " << qm_ << ")" << endl
- << " VALUES (" << qs_ << ", " << v << ", 0)" << endl;
-
- post_statement ();
- }
- };
- entry<version_table> version_table_;
- }
- }
-}
diff --git a/odb/relational/sqlite/source.cxx b/odb/relational/sqlite/source.cxx
deleted file mode 100644
index 2624af2..0000000
--- a/odb/relational/sqlite/source.cxx
+++ /dev/null
@@ -1,470 +0,0 @@
-// file : odb/relational/sqlite/source.cxx
-// license : GNU GPL v3; see accompanying LICENSE file
-
-#include <odb/relational/source.hxx>
-
-#include <odb/relational/sqlite/common.hxx>
-#include <odb/relational/sqlite/context.hxx>
-
-using namespace std;
-
-namespace relational
-{
- namespace sqlite
- {
- namespace source
- {
- namespace relational = relational::source;
-
- struct query_parameters: relational::query_parameters, context
- {
- query_parameters (base const& x): base (x) {}
-
- virtual string
- next (semantics::data_member& m,
- const string& column,
- const string& sqlt)
- {
- // Handle stream columns. Specifically, we somehow need to
- // pass the column name to the code that runs in the
- // statement. So what we are going to do is encode it
- // in the parameter name.
- //
- if (sk_ == statement_insert || sk_ == statement_update)
- {
- const sql_type& t (parse_sql_type (sqlt, m, false));
- if (t.stream)
- {
- // The column name is quoted.
- //
- string r (column);
- r[0] = '$'; // Replace leading '"'.
- r.resize (r.size () - 1); // Remove trailing '"'.
-
- // Verify it only contains allowed characters.
- //
- for (size_t i (1); i != r.size (); ++i)
- {
- char c (r[i]);
- if (c != '_' &&
- (c < '0' || c > '9') &&
- (c < 'a' || c > 'z') &&
- (c < 'A' || c > 'Z'))
- {
- cerr << m.file () << ":" << m.line () << ":" << m.column ()
- << ": error: unsupported character '" << c << "' in "
- << sqlt << " column name " << column << endl;
-
- cerr << m.file () << ":" << m.line () << ":" << m.column ()
- << ": info: STREAM column can contain alpha-numeric "
- << "characters plus '_'" << endl;
-
- throw operation_failed ();
- }
- }
-
- // For TEXT columns, since we use the *_bind_zeroblob()
- // function (there is no *_bind_zerotext()), the value
- // that will be stored is BLOB, not TEXT, unless we
- // explicitly CAST it. The user better make sure the
- // encoding of raw TEXT data they are going to write
- // matches the database encoding.
- //
- if (t.type == sql_type::TEXT)
- r = "CAST(" + r + " AS TEXT)";
-
- return r;
- }
- }
-
- return "?";
- }
- };
- entry<query_parameters> query_parameters_;
-
- //
- // bind
- //
-
- struct bind_member: relational::bind_member_impl<sql_type>,
- member_base
- {
- bind_member (base const& x)
- : member_base::base (x), // virtual base
- member_base::base_impl (x), // virtual base
- base_impl (x),
- member_base (x)
- {
- }
-
- virtual void
- traverse_integer (member_info& mi)
- {
- os << b << ".type = sqlite::bind::integer;"
- << b << ".buffer = &" << arg << "." << mi.var << "value;"
- << b << ".is_null = &" << arg << "." << mi.var << "null;";
- }
-
- virtual void
- traverse_real (member_info& mi)
- {
- os << b << ".type = sqlite::bind::real;"
- << b << ".buffer = &" << arg << "." << mi.var << "value;"
- << b << ".is_null = &" << arg << "." << mi.var << "null;";
- }
-
- virtual void
- traverse_text (member_info& mi)
- {
- os << b << ".type = sqlite::image_traits<" << endl
- << " " << mi.fq_type () << "," << endl
- << " sqlite::id_text>::bind_value;"
- << b << ".buffer = " << arg << "." << mi.var << "value.data ();"
- << b << ".size = &" << arg << "." << mi.var << "size;"
- << b << ".capacity = " << arg << "." << mi.var <<
- "value.capacity ();"
- << b << ".is_null = &" << arg << "." << mi.var << "null;";
- }
-
- virtual void
- traverse_blob (member_info& mi)
- {
- os << b << ".type = sqlite::bind::blob;"
- << b << ".buffer = " << arg << "." << mi.var << "value.data ();"
- << b << ".size = &" << arg << "." << mi.var << "size;"
- << b << ".capacity = " << arg << "." << mi.var <<
- "value.capacity ();"
- << b << ".is_null = &" << arg << "." << mi.var << "null;";
- }
-
- virtual void
- traverse_stream (member_info& mi)
- {
- os << b << ".type = sqlite::bind::stream;"
- << b << ".buffer = &" << arg << "." << mi.var << "value;"
- << b << ".size = &" << arg << "." << mi.var << "size;"
- << b << ".is_null = &" << arg << "." << mi.var << "null;";
- }
- };
- entry<bind_member> bind_member_;
-
- //
- // grow
- //
-
- struct grow_member: relational::grow_member_impl<sql_type>,
- member_base
- {
- grow_member (base const& x)
- : member_base::base (x), // virtual base
- member_base::base_impl (x), // virtual base
- base_impl (x),
- member_base (x) {}
-
- virtual void
- traverse_integer (member_info&)
- {
- os << e << " = false;"
- << endl;
- }
-
- virtual void
- traverse_real (member_info&)
- {
- os << e << " = false;"
- << endl;
- }
-
- virtual void
- traverse_string (member_info& mi)
- {
- os << "if (" << e << ")" << endl
- << "{"
- << "i." << mi.var << "value.capacity (i." << mi.var << "size);"
- << "grew = true;"
- << "}";
- }
-
- virtual void
- traverse_stream (member_info&)
- {
- os << e << " = false;"
- << endl;
- }
- };
- entry<grow_member> grow_member_;
-
- //
- // init image
- //
-
- struct init_image_member: relational::init_image_member_impl<sql_type>,
- member_base
- {
- init_image_member (base const& x)
- : member_base::base (x), // virtual base
- member_base::base_impl (x), // virtual base
- base_impl (x),
- member_base (x)
- {
- }
-
- virtual void
- set_null (member_info& mi)
- {
- os << "i." << mi.var << "null = true;";
- }
-
- virtual void
- traverse_integer (member_info& mi)
- {
- os << traits << "::set_image (" << endl
- << "i." << mi.var << "value," << endl
- << "is_null," << endl
- << member << ");"
- << "i." << mi.var << "null = is_null;";
- }
-
- virtual void
- traverse_real (member_info& mi)
- {
- os << traits << "::set_image (" << endl
- << "i." << mi.var << "value," << endl
- << "is_null," << endl
- << member << ");"
- << "i." << mi.var << "null = is_null;";
- }
-
- virtual void
- traverse_string (member_info& mi)
- {
- os << "std::size_t cap (i." << mi.var << "value.capacity ());"
- << traits << "::set_image (" << endl
- << "i." << mi.var << "value," << endl
- << "i." << mi.var << "size," << endl
- << "is_null," << endl
- << member << ");"
- << "i." << mi.var << "null = is_null;"
- << "grew = grew || (cap != i." << mi.var << "value.capacity ());";
- }
-
- virtual void
- traverse_stream (member_info& mi)
- {
- os << traits << "::set_image (" << endl
- << "i." << mi.var << "value," << endl
- << "i." << mi.var << "size," << endl
- << "is_null," << endl
- << member << ");"
- << "i." << mi.var << "null = is_null;";
- }
- };
- entry<init_image_member> init_image_member_;
-
- //
- // init value
- //
-
- struct init_value_member: relational::init_value_member_impl<sql_type>,
- member_base
- {
- init_value_member (base const& x)
- : member_base::base (x), // virtual base
- member_base::base_impl (x), // virtual base
- base_impl (x),
- member_base (x)
- {
- }
-
- virtual void
- get_null (string const& var) const
- {
- os << "i." << var << "null";
- }
-
- virtual void
- traverse_integer (member_info& mi)
- {
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "value," << endl
- << "i." << mi.var << "null);"
- << endl;
- }
-
- virtual void
- traverse_real (member_info& mi)
- {
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "value," << endl
- << "i." << mi.var << "null);"
- << endl;
- }
-
- virtual void
- traverse_string (member_info& mi)
- {
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "value," << endl
- << "i." << mi.var << "size," << endl
- << "i." << mi.var << "null);"
- << endl;
- }
-
- virtual void
- traverse_stream (member_info& mi)
- {
- os << traits << "::set_value (" << endl
- << member << "," << endl
- << "i." << mi.var << "value," << endl
- << "i." << mi.var << "size," << endl
- << "i." << mi.var << "null);"
- << endl;
- }
- };
- entry<init_value_member> init_value_member_;
-
- struct statement_columns_common: context
- {
- void
- process (relational::statement_columns& cs, statement_kind sk)
- {
- using relational::statement_columns;
-
- // For SELECT statements, add _ROWID_ "follow-up" column to
- // each stream column. The reason we need both, and not just
- // ROWID is the NULL value. Let's hope that SELECT'ing a BLOB
- // but not actually reading it with sqlite3_result_blob() is
- // as fast as not SELECT'ing it.
- //
- if (sk != statement_select)
- return;
-
- for (statement_columns::iterator i (cs.begin ());
- i != cs.end (); ++i)
- {
- if (parse_sql_type (i->type, *i->member).stream)
- {
- // Column is already table-qualified and quoted. Do some
- // surgery to replace it with _ROWID_. That is, we want to
- // transform "table"."column" to "table"."_ROWID_".
- //
- string c (i->column);
- string::size_type n (c.size ()), p (c.rfind ('"', n - 2));
- assert (p != string::npos);
- string as (c, p + 1, n - p - 2);
- c.resize (p);
- c += "\"_ROWID_\"";
-
- // We are going to pack this "tightly", without any newlines,
- // so that the statement processing code treats them as a
- // single column.
- //
- i->column += ',';
- i->column += c;
- }
- }
- }
- };
-
- struct container_traits: relational::container_traits,
- statement_columns_common
- {
- container_traits (base const& x): base (x) {}
-
- virtual void
- cache_result (string const&)
- {
- // Caching is not necessary since SQLite can execute several
- // interleaving statements.
- //
- }
-
- virtual void
- process_statement_columns (relational::statement_columns& cols,
- statement_kind sk,
- bool)
- {
- statement_columns_common::process (cols, sk);
- }
- };
- entry<container_traits> container_traits_;
-
- struct section_traits: relational::section_traits,
- statement_columns_common
- {
- section_traits (base const& x): base (x) {}
-
- virtual void
- process_statement_columns (relational::statement_columns& cols,
- statement_kind sk)
- {
- statement_columns_common::process (cols, sk);
- }
- };
- entry<section_traits> section_traits_;
-
- struct class_: relational::class_, statement_columns_common
- {
- class_ (base const& x): base (x) {}
-
- virtual void
- init_auto_id (semantics::data_member& m, string const& im)
- {
- // Don't set the id value to NULL if this is a nullable wrapper.
- // This will allow the user to control whether the value is auto or
- // manually assigned by using something like this:
- //
- // #pragma db auto
- // odb::nullable<int64_t> id;
- //
- semantics::type& t (utype (m));
- if (wrapper (t) && t.template get<bool> ("wrapper-null-handler"))
- return;
-
- os << im << "null = true;"
- << endl;
- }
-
- virtual string
- select_trailer (type&)
- {
- // SQLite has not support for FOR UPDATE and since this is an
- // optimization, we simply ignore it.
- //
- return "";
- }
-
- virtual string
- join_syntax (view_object const& vo)
- {
- const char* n (0);
-
- if (vo.join == view_object::full)
- n = "FULL OUTER JOIN";
- else if (vo.join == view_object::right)
- n = "RIGHT OUTER JOIN";
-
- if (n != 0)
- {
- error (vo.loc) << n << " is not supported by SQLite" << endl;
- throw operation_failed ();
- }
-
- return base::join_syntax (vo);
- }
-
- virtual void
- process_statement_columns (relational::statement_columns& cols,
- statement_kind sk,
- bool)
- {
- statement_columns_common::process (cols, sk);
- }
- };
- entry<class_> class_entry_;
- }
- }
-}