summaryrefslogtreecommitdiff
path: root/odb/relational/sqlite
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2011-10-24 16:32:51 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2011-10-24 16:32:51 +0200
commit08a47c70ad517b80b72914d47d547463f576bcd3 (patch)
tree8a6ab07cf05e8668ea3c91735dfe97e2a98f3f05 /odb/relational/sqlite
parenta976183dc95a8b7a9bd7a308c3ea94f08982c426 (diff)
Generate database schema from database model instead of C++ model
We now first create the so-called database model from C++ model and then use that to generate the database schema. The new approach also adds more general support for primary/foreign keys, including multi- column keys. Finally, for MySQL we now generate out-of-line foreign key definitions. Because MySQL does not support deferred constraints checking, deferred foreign keys are written commented out, for documentation.
Diffstat (limited to 'odb/relational/sqlite')
-rw-r--r--odb/relational/sqlite/context.cxx66
-rw-r--r--odb/relational/sqlite/context.hxx20
-rw-r--r--odb/relational/sqlite/model.cxx58
-rw-r--r--odb/relational/sqlite/schema.cxx60
4 files changed, 121 insertions, 83 deletions
diff --git a/odb/relational/sqlite/context.cxx b/odb/relational/sqlite/context.cxx
index 466c5b9..a769fac 100644
--- a/odb/relational/sqlite/context.cxx
+++ b/odb/relational/sqlite/context.cxx
@@ -65,16 +65,19 @@ namespace relational
}
context::
- context (ostream& os, semantics::unit& u, options_type const& ops)
+ context (ostream& os,
+ semantics::unit& u,
+ options_type const& ops,
+ sema_rel::model* m)
: root_context (os, u, ops, data_ptr (new (shared) data (os))),
- base_context (static_cast<data*> (root_context::data_.get ())),
+ base_context (static_cast<data*> (root_context::data_.get ()), m),
data_ (static_cast<data*> (base_context::data_))
{
assert (current_ == 0);
current_ = this;
- data_->generate_grow_ = true;
- data_->need_alias_as_ = true;
+ generate_grow = true;
+ need_alias_as = true;
data_->bind_vector_ = "sqlite::bind*";
data_->truncated_vector_ = "bool*";
@@ -222,8 +225,8 @@ namespace relational
{
struct sql_parser
{
- sql_parser (semantics::data_member& m, std::string const& sql)
- : m_ (m), l_ (sql)
+ sql_parser (std::string const& sql)
+ : l_ (sql)
{
}
@@ -269,27 +272,20 @@ namespace relational
}
else
{
- cerr << m_.file () << ":" << m_.line () << ":" << m_.column ()
- << ": error: expected SQLite type name instead of '"
- << t << "'" << endl;
- throw operation_failed ();
+ throw context::invalid_sql_type (
+ "expected SQLite type name instead of '" + t.string ()
+ + "'");
}
}
}
catch (sql_lexer::invalid_input const& e)
{
- cerr << m_.file () << ":" << m_.line () << ":" << m_.column ()
- << ": error: invalid SQLite type declaration: " << e.message
- << endl;
- throw operation_failed ();
+ throw context::invalid_sql_type (
+ "invalid SQLite type declaration: " + e.message);
}
if (ids_.empty ())
- {
- cerr << m_.file () << ":" << m_.line () << ":" << m_.column ()
- << ": error: expected SQLite type name" << endl;
- throw operation_failed ();
- }
+ throw context::invalid_sql_type ("expected SQLite type name");
sql_type r;
@@ -322,9 +318,8 @@ namespace relational
r.type = sql_type::TEXT;
else
{
- cerr << m_.file () << ":" << m_.line () << ":" << m_.column ()
- << " error: unknown SQLite type '" << id << "'" << endl;
- throw operation_failed ();
+ throw context::invalid_sql_type (
+ "unknown SQLite type '" + id + "'");
}
}
@@ -343,10 +338,8 @@ namespace relational
if (t.type () == sql_token::t_eos)
{
- cerr << m_.file () << ":" << m_.line () << ":" << m_.column ()
- << ": error: missing ')' in SQLite type declaration"
- << endl;
- throw operation_failed ();
+ throw context::invalid_sql_type (
+ "missing ')' in SQLite type declaration");
}
}
}
@@ -368,7 +361,6 @@ namespace relational
typedef vector<string> identifiers;
private:
- semantics::data_member& m_;
sql_lexer l_;
identifiers ids_;
};
@@ -383,11 +375,27 @@ namespace relational
if (!m.count (key))
{
- sql_parser p (m, column_type (m, kp));
- m.set (key, p.parse ());
+ try
+ {
+ m.set (key, parse_sql_type (column_type (m, kp)));
+ }
+ catch (invalid_sql_type const& e)
+ {
+ cerr << m.file () << ":" << m.line () << ":" << m.column ()
+ << ": error: " << e.message () << endl;
+
+ throw operation_failed ();
+ }
}
return m.get<sql_type> (key);
}
+
+ sql_type context::
+ parse_sql_type (string const& t)
+ {
+ sql_parser p (t);
+ return p.parse ();
+ }
}
}
diff --git a/odb/relational/sqlite/context.hxx b/odb/relational/sqlite/context.hxx
index b5c3d85..de4e4c7 100644
--- a/odb/relational/sqlite/context.hxx
+++ b/odb/relational/sqlite/context.hxx
@@ -37,6 +37,21 @@ namespace relational
column_sql_type (semantics::data_member&,
string const& key_prefix = string ());
+ public:
+ struct invalid_sql_type
+ {
+ invalid_sql_type (string const& message): message_ (message) {}
+
+ string const&
+ message () const {return message_;}
+
+ private:
+ string message_;
+ };
+
+ static sql_type
+ parse_sql_type (string const&);
+
protected:
virtual bool
grow_impl (semantics::class_&);
@@ -55,7 +70,10 @@ namespace relational
virtual
~context ();
context ();
- context (std::ostream&, semantics::unit&, options_type const&);
+ context (std::ostream&,
+ semantics::unit&,
+ options_type const&,
+ sema_rel::model*);
static context&
current ()
diff --git a/odb/relational/sqlite/model.cxx b/odb/relational/sqlite/model.cxx
new file mode 100644
index 0000000..1324255
--- /dev/null
+++ b/odb/relational/sqlite/model.cxx
@@ -0,0 +1,58 @@
+// file : odb/relational/sqlite/model.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC
+// 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
+ default_enum (semantics::data_member& m, tree en, string const&)
+ {
+ // Make sure the column is mapped to INTEGER.
+ //
+ if (column_sql_type (m).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 ();
+ }
+ };
+ entry<object_columns> object_columns_;
+ }
+ }
+}
diff --git a/odb/relational/sqlite/schema.cxx b/odb/relational/sqlite/schema.cxx
index 589ce7b..6562905 100644
--- a/odb/relational/sqlite/schema.cxx
+++ b/odb/relational/sqlite/schema.cxx
@@ -20,66 +20,20 @@ namespace relational
// Create.
//
- struct object_columns: relational::object_columns, context
+ struct create_column: relational::create_column, context
{
- object_columns (base const& x): base (x) {}
+ create_column (base const& x): base (x) {}
virtual void
- default_enum (semantics::data_member& m, tree en, string const&)
+ auto_ (sema_rel::column&)
{
- // Make sure the column is mapped to INTEGER.
- //
- if (column_sql_type (m).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)));
-
- if (e.enum_ ().unsigned_ ())
- os << " DEFAULT " << e.value ();
+ if (options.sqlite_lax_auto_id ())
+ os << " /*AUTOINCREMENT*/";
else
- os << " DEFAULT " << static_cast<long long> (e.value ());
+ os << " AUTOINCREMENT";
}
-
- virtual void
- constraints (semantics::data_member& m)
- {
- base::constraints (m);
-
- if (m.count ("auto"))
- {
- if (options.sqlite_lax_auto_id ())
- os << " /*AUTOINCREMENT*/";
- else
- os << " AUTOINCREMENT";
- }
- }
-
- virtual void
- reference (semantics::data_member& m)
- {
- // In SQLite, by default, constraints are immediate.
- //
- if (semantics::class_* c =
- object_pointer (member_utype (m, prefix_)))
- {
- os << " REFERENCES " << table_qname (*c) << " (" <<
- column_qname (*id_member (*c)) << ") " <<
- "DEFERRABLE INITIALLY DEFERRED";
- }
- else
- base::reference (m);
- }
-
};
- entry<object_columns> object_columns_;
+ entry<create_column> create_column_;
}
}
}