aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2011-09-05 10:36:33 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2011-09-05 10:36:33 +0200
commit428558c89850fe8c79b9c89a943bd996912d12f5 (patch)
treeb6d8af6fd6a82b3e3822f7da4637c7c16ee7100d
parenta7ec19749a76cc262240124f5c71c1ee4051cba7 (diff)
Support for views; native part
-rw-r--r--odb/common.cxx81
-rw-r--r--odb/common.hxx12
-rw-r--r--odb/context.cxx17
-rw-r--r--odb/context.hxx29
-rw-r--r--odb/include.cxx4
-rw-r--r--odb/pragma.cxx90
-rw-r--r--odb/relational/header.hxx145
-rw-r--r--odb/relational/inline.hxx55
-rw-r--r--odb/relational/mysql/context.cxx7
-rw-r--r--odb/relational/pgsql/source.cxx4
-rw-r--r--odb/relational/source.hxx257
-rw-r--r--odb/relational/type-processor.cxx8
-rw-r--r--odb/validator.cxx134
13 files changed, 674 insertions, 169 deletions
diff --git a/odb/common.cxx b/odb/common.cxx
index 81f8155..036b491 100644
--- a/odb/common.cxx
+++ b/odb/common.cxx
@@ -44,6 +44,14 @@ traverse_object (semantics::class_& c)
}
void object_members_base::
+traverse_view (semantics::class_& c)
+{
+ // A view has no bases.
+ //
+ names (c);
+}
+
+void object_members_base::
traverse (semantics::data_member& m, semantics::class_& c)
{
traverse_composite_wrapper (&m, c, 0);
@@ -52,24 +60,28 @@ traverse (semantics::data_member& m, semantics::class_& c)
void object_members_base::
traverse (semantics::class_& c)
{
- bool obj (object (c));
+ class_kind_type k (class_kind (c));
- // Ignore transient bases.
- //
- if (!(obj || context::composite (c)))
+ if (k == class_other)
+ {
+ // Ignore transient bases.
+ //
+ assert (context::top_object != 0);
return;
-
- semantics::class_* prev;
- if (obj)
+ }
+ else if (k == class_composite)
{
- prev = context::cur_object;
- context::cur_object = &c;
-
- if (context::top_object == 0)
- context::top_object = &c;
+ traverse_composite_wrapper (0, c, 0);
+ return;
}
- if (obj && build_table_prefix_)
+ semantics::class_* prev (context::cur_object);
+ context::cur_object = &c;
+
+ if (context::top_object == 0)
+ context::top_object = &c;
+
+ if (build_table_prefix_)
{
// Don't reset the table prefix if we are traversing a base.
//
@@ -83,7 +95,10 @@ traverse (semantics::class_& c)
tb = true;
}
- traverse_object (c);
+ if (k == class_object)
+ traverse_object (c);
+ else
+ traverse_view (c);
if (tb)
{
@@ -93,19 +108,16 @@ traverse (semantics::class_& c)
}
else
{
- if (obj)
+ if (k == class_object)
traverse_object (c);
else
- traverse_composite_wrapper (0, c, 0);
+ traverse_view (c);
}
- if (obj)
- {
- if (prev == 0)
- context::top_object = 0;
+ if (prev == 0)
+ context::top_object = 0;
- context::cur_object = prev;
- }
+ context::cur_object = prev;
}
void object_members_base::member::
@@ -206,6 +218,14 @@ traverse_object (semantics::class_& c)
}
void object_columns_base::
+traverse_view (semantics::class_& c)
+{
+ // A view has no bases.
+ //
+ names (c);
+}
+
+void object_columns_base::
traverse (semantics::data_member& m,
semantics::class_& c,
string const& key_prefix,
@@ -236,12 +256,15 @@ traverse (semantics::data_member& m,
void object_columns_base::
traverse (semantics::class_& c)
{
- bool obj (object (c));
+ class_kind_type k (class_kind (c));
// Ignore transient bases.
//
- if (!(obj || context::composite (c)))
+ if (k == class_other)
+ {
+ assert (context::top_object != 0);
return;
+ }
bool f (top_level_);
@@ -249,7 +272,7 @@ traverse (semantics::class_& c)
top_level_ = false;
semantics::class_* prev;
- if (obj)
+ if (k == class_object || k == class_view)
{
prev = context::cur_object;
context::cur_object = &c;
@@ -258,12 +281,14 @@ traverse (semantics::class_& c)
context::top_object = &c;
}
- if (obj)
+ if (k == class_object)
traverse_object (c);
- else
+ else if (k == class_view)
+ traverse_view (c);
+ else if (k == class_composite)
traverse_composite (0, c);
- if (obj)
+ if (k == class_object || k == class_view)
{
if (prev == 0)
context::top_object = 0;
diff --git a/odb/common.hxx b/odb/common.hxx
index 9e48771..60f5e3b 100644
--- a/odb/common.hxx
+++ b/odb/common.hxx
@@ -50,6 +50,12 @@ struct object_members_base: traversal::class_, virtual context
virtual void
traverse_object (semantics::class_&);
+ // If you override this function, you can call the base to traverse
+ // members.
+ //
+ virtual void
+ traverse_view (semantics::class_&);
+
public:
object_members_base ()
: member_ (*this)
@@ -144,6 +150,12 @@ struct object_columns_base: traversal::class_, virtual context
virtual void
traverse_object (semantics::class_&);
+ // If you override this function, you can call the base to traverse
+ // members.
+ //
+ virtual void
+ traverse_view (semantics::class_&);
+
// Called after the last column, provided at least one column hasn't
// been ignored.
//
diff --git a/odb/context.cxx b/odb/context.cxx
index 33d9e08..56b9ab0 100644
--- a/odb/context.cxx
+++ b/odb/context.cxx
@@ -279,6 +279,19 @@ null (semantics::data_member& m, string const& kp)
}
}
+context::class_kind_type context::
+class_kind (semantics::class_& c)
+{
+ if (object (c))
+ return class_object;
+ else if (view (c))
+ return class_view;
+ else if (composite (c))
+ return class_composite;
+ else
+ return class_other;
+}
+
string context::
upcase (string const& s)
{
@@ -1006,10 +1019,10 @@ is_a (semantics::data_member& m,
}
bool context::
-has_a (semantics::type& t, unsigned short flags)
+has_a (semantics::class_& c, unsigned short flags)
{
has_a_impl impl (flags);
- impl.dispatch (t);
+ impl.dispatch (c);
return impl.result ();
}
diff --git a/odb/context.hxx b/odb/context.hxx
index 75becef..e00ec4e 100644
--- a/odb/context.hxx
+++ b/odb/context.hxx
@@ -57,6 +57,16 @@ enum container_kind
ck_multimap
};
+// The same as class_kind in libodb/odb/traits.hxx.
+//
+enum class_kind
+{
+ class_object,
+ class_view,
+ class_composite,
+ class_other
+};
+
class context
{
public:
@@ -84,6 +94,12 @@ public:
}
static bool
+ view (semantics::type& t)
+ {
+ return t.count ("view");
+ }
+
+ static bool
transient (semantics::data_member& m)
{
return m.count ("transient");
@@ -177,6 +193,11 @@ public:
bool
null (semantics::data_member&, string const& key_prefix);
+ typedef ::class_kind class_kind_type;
+
+ static class_kind_type
+ class_kind (semantics::class_&);
+
// Database names and types.
//
public:
@@ -377,7 +398,7 @@ public:
string const& key_prefix);
bool
- has_a (semantics::type&, unsigned short flags);
+ has_a (semantics::class_&, unsigned short flags);
public:
// Process include path by adding the prefix, putting it through
@@ -480,12 +501,12 @@ public:
bool embedded_schema;
- // Outermost object currently being traversed.
+ // Outermost object or view currently being traversed.
//
semantics::class_*& top_object;
- // Object currently being traversed. It can be the same as top_object
- // or it can a base of top_object.
+ // Object or view currently being traversed. It can be the same as
+ // top_object or it can a base of top_object.
//
semantics::class_*& cur_object;
diff --git a/odb/include.cxx b/odb/include.cxx
index 08e785f..16842c8 100644
--- a/odb/include.cxx
+++ b/odb/include.cxx
@@ -79,7 +79,9 @@ namespace
if (c.file () == unit.file ())
return;
- // We only generate things for objects and composite value types.
+ // We only generate things for objects and composite value types. In
+ // particular, we don't care about views since they cannot be used in
+ // definitions of other views, objects, or composite values.
//
if (!(object (c) || composite (c)))
return;
diff --git a/odb/pragma.cxx b/odb/pragma.cxx
index 23d3fd3..ec3fb8d 100644
--- a/odb/pragma.cxx
+++ b/odb/pragma.cxx
@@ -126,9 +126,11 @@ check_decl_type (tree d, string const& name, string const& p, location_t l)
}
}
else if (p == "object" ||
+ p == "view" ||
p == "pointer" ||
p == "abstract" ||
- p == "callback")
+ p == "callback" ||
+ p == "query")
{
if (tc != RECORD_TYPE)
{
@@ -140,7 +142,7 @@ check_decl_type (tree d, string const& name, string const& p, location_t l)
else if (p == "table")
{
// Table can be used for both members (container) and types (container
- // or object).
+ // object, or view).
//
if (tc != FIELD_DECL && !TYPE_P (d))
{
@@ -442,6 +444,40 @@ handle_pragma (cpp_reader* reader,
tt = pragma_lex (&t);
}
+ else if (p == "query")
+ {
+ // query ("statement")
+ //
+
+ // Make sure we've got the correct declaration type.
+ //
+ if (decl != 0 && !check_decl_type (decl, decl_name, p, loc))
+ return;
+
+ if (pragma_lex (&t) != CPP_OPEN_PAREN)
+ {
+ error () << "'(' expected after db pragma '" << p << "'" << endl;
+ return;
+ }
+
+ tt = pragma_lex (&t);
+
+ if (tt != CPP_STRING)
+ {
+ error () << "query statement expected in db pragma '" << p << "'" << endl;
+ return;
+ }
+
+ val = TREE_STRING_POINTER (t);
+
+ if (pragma_lex (&t) != CPP_CLOSE_PAREN)
+ {
+ error () << "')' expected at the end of db pragma '" << p << "'" << endl;
+ return;
+ }
+
+ tt = pragma_lex (&t);
+ }
else if (p == "id")
{
// id
@@ -839,47 +875,12 @@ handle_pragma_qualifier (cpp_reader* reader, string const& p)
// Pragma qualifiers.
//
- if (p == "object")
+ if (p == "object" ||
+ p == "view" ||
+ p == "value")
{
// object [(<identifier>)]
- //
-
- tt = pragma_lex (&t);
-
- if (tt == CPP_OPEN_PAREN)
- {
- tt = pragma_lex (&t);
-
- if (tt == CPP_NAME || tt == CPP_SCOPE)
- {
- decl = parse_scoped_name (t, tt, decl_name, true, p);
-
- if (decl == 0)
- return;
-
- // Make sure we've got the correct declaration type.
- //
- if (!check_decl_type (decl, decl_name, p, loc))
- return;
-
- if (tt != CPP_CLOSE_PAREN)
- {
- error () << "')' expected at the end of db pragma '" << p << "'"
- << endl;
- return;
- }
-
- tt = pragma_lex (&t);
- }
- else
- {
- error () << "type name expected in db pragma '" << p << "'" << endl;
- return;
- }
- }
- }
- else if (p == "value")
- {
+ // view [(<identifier>)]
// value [(<identifier>)]
//
@@ -1029,6 +1030,12 @@ handle_pragma_db_object (cpp_reader* r)
}
extern "C" void
+handle_pragma_db_view (cpp_reader* r)
+{
+ handle_pragma_qualifier (r, "view");
+}
+
+extern "C" void
handle_pragma_db_value (cpp_reader* r)
{
handle_pragma_qualifier (r, "value");
@@ -1229,6 +1236,7 @@ register_odb_pragmas (void*, void*)
/*
c_register_pragma_with_expansion ("db", "object", handle_pragma_db_object);
+ c_register_pragma_with_expansion ("db", "view", handle_pragma_db_view);
c_register_pragma_with_expansion ("db", "value", handle_pragma_db_value);
c_register_pragma_with_expansion ("db", "member", handle_pragma_db_member);
c_register_pragma_with_expansion ("db", "id", handle_pragma_db_id);
diff --git a/odb/relational/header.hxx b/odb/relational/header.hxx
index 69f7977..f7e1058 100644
--- a/odb/relational/header.hxx
+++ b/odb/relational/header.hxx
@@ -46,7 +46,7 @@ namespace relational
{
bool obj (object (c));
- // Ignore transient bases.
+ // Ignore transient bases. Not used for views.
//
if (!(obj || composite (c)))
return;
@@ -92,6 +92,7 @@ namespace relational
{
os << "struct image_type";
+ if (!view (c))
{
instance<image_base> b;
traversal::inherits i (*b);
@@ -126,7 +127,7 @@ namespace relational
virtual void
traverse (type& c)
{
- // Ignore transient bases.
+ // Ignore transient bases. Not used for views.
//
if (!object (c))
return;
@@ -224,7 +225,7 @@ namespace relational
if (object (c_))
{
- base = cur_object != &c_ ||
+ base = cur_object != &c_ ||
!object (dynamic_cast<type&> (m.scope ()));
abst = abstract (c_);
}
@@ -754,6 +755,8 @@ namespace relational
if (object (c))
traverse_object (c);
+ else if (view (c))
+ traverse_view (c);
else if (composite (c))
traverse_composite (c);
}
@@ -782,6 +785,12 @@ namespace relational
<< "//" << endl;
os << "template <>" << endl
+ << "struct class_traits< " << type << " >"
+ << "{"
+ << "static const class_kind kind = class_object;"
+ << "};";
+
+ os << "template <>" << endl
<< "class access::object_traits< " << type << " >"
<< "{"
<< "public:" << endl;
@@ -1073,6 +1082,124 @@ namespace relational
}
virtual void
+ view_public_extra_pre (type&)
+ {
+ }
+
+ virtual void
+ view_public_extra_post (type&)
+ {
+ }
+
+ virtual void
+ traverse_view (type& c)
+ {
+ string const& type (c.fq_name ());
+
+ os << "// " << c.name () << endl
+ << "//" << endl;
+
+ os << "template <>" << endl
+ << "struct class_traits< " << type << " >"
+ << "{"
+ << "static const class_kind kind = class_view;"
+ << "};";
+
+ os << "template <>" << endl
+ << "class access::view_traits< " << type << " >"
+ << "{"
+ << "public:" << endl;
+
+ view_public_extra_pre (c);
+
+ // view_type & pointer_type
+ //
+ os << "typedef " << type << " view_type;"
+ << "typedef " << c.get<string> ("object-pointer") << " pointer_type;"
+ << endl;
+
+ // image_type
+ //
+ image_type_->traverse (c);
+
+ //
+ // Query.
+ //
+
+ // query_base_type
+ //
+ os << "typedef " << db << "::query query_base_type;"
+ << endl;
+
+ // query_type
+ //
+ os << "typedef query_base_type query_type;"
+ << endl;
+
+ /*
+ os << "struct query_type: query_base_type, query_columns"
+ << "{"
+ << "query_type ();"
+ << "query_type (const std::string&);"
+ << "query_type (const query_base_type&);"
+ << "};";
+ */
+
+ //
+ // Functions.
+ //
+
+ // grow ()
+ //
+ os << "static bool" << endl
+ << "grow (image_type&, " << truncated_vector << ");"
+ << endl;
+
+ // bind (image_type)
+ //
+ os << "static void" << endl
+ << "bind (" << bind_vector << ", image_type&);"
+ << endl;
+
+ // init (view, image)
+ //
+ os << "static void" << endl
+ << "init (view_type&, const image_type&);"
+ << endl;
+
+ // column_count
+ //
+ os << "static const std::size_t column_count = " <<
+ out_column_count (c) << "UL;"
+ << endl;
+
+ // Statements.
+ //
+ os << "static const char* const query_statement;"
+ << endl;
+
+ //
+ // Functions.
+ //
+
+ // callback ()
+ //
+ os << "static void" << endl
+ << "callback (database&, view_type&, callback_event);"
+ << endl;
+
+ // query ()
+ //
+ os << "static result<view_type>" << endl
+ << "query (database&, const query_type&);"
+ << endl;
+
+ view_public_extra_post (c);
+
+ os << "};";
+ }
+
+ virtual void
traverse_composite (type& c)
{
string const& type (c.fq_name ());
@@ -1081,11 +1208,17 @@ namespace relational
<< "//" << endl;
os << "template <>" << endl
+ << "struct class_traits< " << type << " >"
+ << "{"
+ << "static const class_kind kind = class_composite;"
+ << "};";
+
+ os << "template <>" << endl
<< "class access::composite_value_traits< " << type << " >"
<< "{"
<< "public:" << endl;
- // object_type
+ // value_type
//
os << "typedef " << type << " value_type;"
<< endl;
@@ -1113,13 +1246,13 @@ namespace relational
<< "bind (" << bind_vector << ", image_type&);"
<< endl;
- // init (image, object)
+ // init (image, value)
//
os << "static bool" << endl
<< "init (image_type&, const value_type&);"
<< endl;
- // init (object, image)
+ // init (value, image)
//
os << "static void" << endl
<< "init (value_type&, const image_type&, database&);"
diff --git a/odb/relational/inline.hxx b/odb/relational/inline.hxx
index 311640e..1134df6 100644
--- a/odb/relational/inline.hxx
+++ b/odb/relational/inline.hxx
@@ -41,29 +41,31 @@ namespace relational
virtual void
traverse (type& c)
{
+ bool obj (object (c));
+
// Ignore transient bases.
//
- if (!object (c))
+ if (!(obj || view (c)))
return;
if (c.count ("callback"))
{
string name (c.get<string> ("callback"));
- // In case of the const object, we only generate the call if
+ // In case of the const instance, we only generate the call if
// there is a const callback.
//
if (const_)
{
if (c.count ("callback-const"))
- os << "static_cast< const " << c.fq_name () << "& > (obj)." <<
+ os << "static_cast< const " << c.fq_name () << "& > (x)." <<
name << " (e, db);";
}
else
- os << "static_cast< " << c.fq_name () << "& > (obj)." <<
+ os << "static_cast< " << c.fq_name () << "& > (x)." <<
name << " (e, db);";
}
- else
+ else if (obj)
inherits (c);
}
@@ -86,6 +88,8 @@ namespace relational
if (object (c))
traverse_object (c);
+ if (view (c))
+ traverse_view (c);
else if (composite (c))
traverse_composite (c);
}
@@ -178,11 +182,11 @@ namespace relational
//
os << "inline" << endl
<< "void " << traits << "::" << endl
- << "callback (database& db, object_type& obj, callback_event e)"
+ << "callback (database& db, object_type& x, callback_event e)"
<< endl
<< "{"
<< "ODB_POTENTIALLY_UNUSED (db);"
- << "ODB_POTENTIALLY_UNUSED (obj);"
+ << "ODB_POTENTIALLY_UNUSED (x);"
<< "ODB_POTENTIALLY_UNUSED (e);"
<< endl;
callback_calls_->traverse (c, false);
@@ -190,11 +194,10 @@ namespace relational
os << "inline" << endl
<< "void " << traits << "::" << endl
- << "callback (database& db, const object_type& obj, " <<
- "callback_event e)"
+ << "callback (database& db, const object_type& x, callback_event e)"
<< "{"
<< "ODB_POTENTIALLY_UNUSED (db);"
- << "ODB_POTENTIALLY_UNUSED (obj);"
+ << "ODB_POTENTIALLY_UNUSED (x);"
<< "ODB_POTENTIALLY_UNUSED (e);"
<< endl;
callback_calls_->traverse (c, true);
@@ -239,6 +242,38 @@ namespace relational
}
virtual void
+ view_extra (type&)
+ {
+ }
+
+ virtual void
+ traverse_view (type& c)
+ {
+ string const& type (c.fq_name ());
+ string traits ("access::view_traits< " + type + " >");
+
+ os << "// " << c.name () << endl
+ << "//" << endl
+ << endl;
+
+ view_extra (c);
+
+ // callback ()
+ //
+ os << "inline" << endl
+ << "void " << traits << "::" << endl
+ << "callback (database& db, view_type& x, callback_event e)"
+ << endl
+ << "{"
+ << "ODB_POTENTIALLY_UNUSED (db);"
+ << "ODB_POTENTIALLY_UNUSED (x);"
+ << "ODB_POTENTIALLY_UNUSED (e);"
+ << endl;
+ callback_calls_->traverse (c, false);
+ os << "}";
+ }
+
+ virtual void
traverse_composite (type&)
{
/*
diff --git a/odb/relational/mysql/context.cxx b/odb/relational/mysql/context.cxx
index ccd1861..59b93ba 100644
--- a/odb/relational/mysql/context.cxx
+++ b/odb/relational/mysql/context.cxx
@@ -122,9 +122,11 @@ namespace relational
virtual void
traverse (type& c)
{
+ bool view (context::view (c));
+
// Ignore transient bases.
//
- if (!(context::object (c) || context::composite (c)))
+ if (!(context::object (c) || view || context::composite (c)))
return;
if (c.count ("mysql-grow"))
@@ -133,7 +135,8 @@ namespace relational
{
// r_ should be false.
//
- inherits (c);
+ if (!view)
+ inherits (c);
if (!r_)
names (c);
diff --git a/odb/relational/pgsql/source.cxx b/odb/relational/pgsql/source.cxx
index b869520..da9d0d7 100644
--- a/odb/relational/pgsql/source.cxx
+++ b/odb/relational/pgsql/source.cxx
@@ -969,7 +969,7 @@ namespace relational
}
virtual void
- query_statement_ctor_args (type&)
+ object_query_statement_ctor_args (type&)
{
os << "sts.connection ()," << endl
<< "query_statement_name," << endl
@@ -981,7 +981,7 @@ namespace relational
}
virtual void
- erase_query_statement_ctor_args (type&)
+ object_erase_query_statement_ctor_args (type&)
{
os << "conn," << endl
<< "erase_query_statement_name," << endl
diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx
index d9cf66f..a3ef5de 100644
--- a/odb/relational/source.hxx
+++ b/odb/relational/source.hxx
@@ -404,7 +404,7 @@ namespace relational
{
bool obj (object (c));
- // Ignore transient bases.
+ // Ignore transient bases. Not used for views.
//
if (!(obj || composite (c)))
return;
@@ -461,7 +461,7 @@ namespace relational
{
bool obj (object (c));
- // Ignore transient bases.
+ // Ignore transient bases. Not used for views.
//
if (!(obj || composite (c)))
return;
@@ -519,7 +519,7 @@ namespace relational
{
bool obj (object (c));
- // Ignore transient bases.
+ // Ignore transient bases. Not used for views.
//
if (!(obj || composite (c)))
return;
@@ -570,7 +570,7 @@ namespace relational
{
bool obj (object (c));
- // Ignore transient bases.
+ // Ignore transient bases. Not used for views.
//
if (!(obj || composite (c)))
return;
@@ -689,8 +689,13 @@ namespace relational
grow = grow || context::grow (m, vt, "value");
- bool eager_ptr (is_a (m, test_eager_pointer, vt, "value") ||
- has_a (vt, test_eager_pointer));
+ bool eager_ptr (is_a (m, test_eager_pointer, vt, "value"));
+
+ if (!eager_ptr)
+ {
+ if (semantics::class_* cvt = composite_wrapper (vt))
+ eager_ptr = has_a (*cvt, test_eager_pointer);
+ }
string name (prefix_ + public_name (m) + "_traits");
string scope (scope_ + "::" + name);
@@ -1902,17 +1907,32 @@ namespace relational
if (object (c))
traverse_object (c);
+ else if (view (c))
+ traverse_view (c);
else if (composite (c))
traverse_composite (c);
}
+ //
+ // common
+ //
+
+ virtual void
+ post_query_ (type&)
+ {
+ }
+
+ //
+ // object
+ //
+
virtual void
object_extra (type&)
{
}
virtual void
- query_statement_ctor_args (type&)
+ object_query_statement_ctor_args (type&)
{
os << "sts.connection ()," << endl
<< "query_clause + q.clause (table_name)," << endl
@@ -1921,7 +1941,7 @@ namespace relational
}
virtual void
- erase_query_statement_ctor_args (type&)
+ object_erase_query_statement_ctor_args (type&)
{
os << "conn," << endl
<< "erase_query_clause + q.clause (table_name)," << endl
@@ -1929,11 +1949,6 @@ namespace relational
}
virtual void
- post_query_ (type&)
- {
- }
-
- virtual void
traverse_object (type& c)
{
bool abst (abstract (c));
@@ -2249,10 +2264,10 @@ namespace relational
<< "{"
<< "using namespace " << db << ";"
<< endl
- << db << "::connection& conn (" << db <<
- "::transaction::current ().connection ());"
+ << db << "::connection& conn (" << endl
+ << db << "::transaction::current ().connection ());"
<< "object_statements< object_type >& sts (" << endl
- << "conn.statement_cache ().find<object_type> ());"
+ << "conn.statement_cache ().find_object<object_type> ());"
<< "image_type& im (sts.image ());"
<< "binding& imb (sts.in_image_binding ());"
<< endl
@@ -2311,10 +2326,10 @@ namespace relational
<< "{"
<< "using namespace " << db << ";"
<< endl
- << db << "::connection& conn (" << db <<
- "::transaction::current ().connection ());"
+ << db << "::connection& conn (" << endl
+ << db << "::transaction::current ().connection ());"
<< "object_statements< object_type >& sts (" << endl
- << "conn.statement_cache ().find<object_type> ());"
+ << "conn.statement_cache ().find_object<object_type> ());"
<< endl;
// Initialize id image.
@@ -2363,10 +2378,10 @@ namespace relational
<< "{"
<< "using namespace " << db << ";"
<< endl
- << db << "::connection& conn (" << db <<
- "::transaction::current ().connection ());"
+ << db << "::connection& conn (" << endl
+ << db << "::transaction::current ().connection ());"
<< "object_statements< object_type >& sts (" << endl
- << "conn.statement_cache ().find<object_type> ());"
+ << "conn.statement_cache ().find_object<object_type> ());"
<< endl;
// Initialize id image.
@@ -2410,10 +2425,10 @@ namespace relational
<< "{"
<< "using namespace " << db << ";"
<< endl
- << db << "::connection& conn (" << db <<
- "::transaction::current ().connection ());"
+ << db << "::connection& conn (" << endl
+ << db << "::transaction::current ().connection ());"
<< "object_statements< object_type >& sts (" << endl
- << "conn.statement_cache ().find<object_type> ());"
+ << "conn.statement_cache ().find_object<object_type> ());"
<< "object_statements< object_type >::auto_lock l (sts);"
<< endl
<< "if (l.locked ())"
@@ -2452,10 +2467,10 @@ namespace relational
<< "{"
<< "using namespace " << db << ";"
<< endl
- << db << "::connection& conn (" << db <<
- "::transaction::current ().connection ());"
+ << db << "::connection& conn (" << endl
+ << db << "::transaction::current ().connection ());"
<< "object_statements< object_type >& sts (" << endl
- << "conn.statement_cache ().find<object_type> ());"
+ << "conn.statement_cache ().find_object<object_type> ());"
<< "object_statements< object_type >::auto_lock l (sts);"
<< endl
<< "if (l.locked ())"
@@ -2568,19 +2583,24 @@ namespace relational
<< "const query_type& q)"
<< "{"
<< "using namespace " << db << ";"
+ << "using odb::details::shared;"
+ << "using odb::details::shared_ptr;"
<< endl
- << db << "::connection& conn (" << db <<
- "::transaction::current ().connection ());"
+ << db << "::connection& conn (" << endl
+ << db << "::transaction::current ().connection ());"
<< endl
<< "object_statements< object_type >& sts (" << endl
- << "conn.statement_cache ().find<object_type> ());"
- << "odb::details::shared_ptr<select_statement> st;"
+ << "conn.statement_cache ().find_object<object_type> ());"
+ << "shared_ptr<select_statement> st;"
<< endl
<< "query_ (db, q, sts, st);"
<< endl
- << "odb::details::shared_ptr<odb::result_impl<object_type> > r (" << endl
- << "new (odb::details::shared) " << db <<
- "::result_impl<object_type> (q, st, sts));"
+ << "shared_ptr<odb::result_impl<object_type, " <<
+ "class_object> > r (" << endl
+ << "new (shared) " << db <<
+ "::result_impl<object_type, class_object> (" << endl
+ << "q, st, sts));"
+ << endl
<< "return result<object_type> (r);"
<< "}";
@@ -2592,19 +2612,24 @@ namespace relational
<< "const query_type& q)"
<< "{"
<< "using namespace " << db << ";"
+ << "using odb::details::shared;"
+ << "using odb::details::shared_ptr;"
<< endl
- << db << "::connection& conn (" << db <<
- "::transaction::current ().connection ());"
+ << db << "::connection& conn (" << endl
+ << db << "::transaction::current ().connection ());"
<< endl
<< "object_statements< object_type >& sts (" << endl
- << "conn.statement_cache ().find<object_type> ());"
- << "odb::details::shared_ptr<select_statement> st;"
+ << "conn.statement_cache ().find_object<object_type> ());"
+ << "shared_ptr<select_statement> st;"
<< endl
<< "query_ (db, q, sts, st);"
<< endl
- << "odb::details::shared_ptr<odb::result_impl<const object_type> > r (" << endl
- << "new (odb::details::shared) " << db <<
- "::result_impl<const object_type> (q, st, sts));"
+ << "shared_ptr<odb::result_impl<" <<
+ "const object_type, class_object> > r (" << endl
+ << "new (shared) " << db <<
+ "::result_impl<const object_type, class_object> (" << endl
+ << "q, st, sts));"
+ << endl
<< "return result<const object_type> (r);"
<< "}";
@@ -2628,7 +2653,7 @@ namespace relational
<< "st.reset (new (odb::details::shared) select_statement ("
<< endl;
- query_statement_ctor_args (c);
+ object_query_statement_ctor_args (c);
os << "));" << endl
<< "st->execute ();";
@@ -2644,12 +2669,12 @@ namespace relational
<< "{"
<< "using namespace " << db << ";"
<< endl
- << db << "::connection& conn (" << db <<
- "::transaction::current ().connection ());"
+ << db << "::connection& conn (" << endl
+ << db << "::transaction::current ().connection ());"
<< endl
<< "delete_statement st (" << endl;
- erase_query_statement_ctor_args (c);
+ object_erase_query_statement_ctor_args (c);
os << ");"
<< endl
@@ -2811,6 +2836,142 @@ namespace relational
<< endl;
}
+ //
+ // view
+ //
+
+ virtual void
+ view_extra (type&)
+ {
+ }
+
+ virtual void
+ view_query_statement_ctor_args (type&)
+ {
+ os << "sts.connection ()," << endl
+ << "query_statement + q.clause (\"\")," << endl
+ << "q.parameters_binding ()," << endl
+ << "imb";
+ }
+
+ virtual void
+ traverse_view (type& c)
+ {
+ string const& type (c.fq_name ());
+ string traits ("access::view_traits< " + type + " >");
+
+ os << "// " << c.name () << endl
+ << "//" << endl
+ << endl;
+
+ view_extra (c);
+
+ //
+ // Functions.
+ //
+
+ // grow ()
+ //
+ os << "bool " << traits << "::" << endl
+ << "grow (image_type& i, " << truncated_vector << " t)"
+ << "{"
+ << "ODB_POTENTIALLY_UNUSED (i);"
+ << "ODB_POTENTIALLY_UNUSED (t);"
+ << endl
+ << "bool grew (false);"
+ << endl;
+
+ index_ = 0;
+ names (c, grow_member_names_);
+
+ os << "return grew;"
+ << "}";
+
+ // bind (image_type)
+ //
+ os << "void " << traits << "::" << endl
+ << "bind (" << bind_vector << " b, image_type& i)"
+ << "{"
+ << "bool out (true);" //@@ Try to get rid of this.
+ << "ODB_POTENTIALLY_UNUSED (out);"
+ << endl
+ << "std::size_t n (0);"
+ << endl;
+
+ names (c, bind_member_names_);
+
+ os << "}";
+
+ // init (view, image)
+ //
+ os << "void " << traits << "::" << endl
+ << "init (view_type& o, const image_type& i)"
+ << "{"
+ << "ODB_POTENTIALLY_UNUSED (o);"
+ << "ODB_POTENTIALLY_UNUSED (i);"
+ << endl;
+
+ names (c, init_value_member_names_);
+
+ os << "}";
+
+ // query_statement
+ //
+ os << "const char* const " << traits << "::query_statement =" << endl
+ << strlit (c.get<string> ("query")) << endl
+ << strlit (" ") << ";" << endl
+ << endl;
+
+ // query ()
+ //
+ os << "result< " << traits << "::view_type >" << endl
+ << traits << "::" << endl
+ << "query (database&, const query_type& q)"
+ << "{"
+ << "using namespace " << db << ";"
+ << "using odb::details::shared;"
+ << "using odb::details::shared_ptr;"
+ << endl
+ << db << "::connection& conn (" << endl
+ << db << "::transaction::current ().connection ());"
+ << endl
+ << "view_statements< view_type >& sts (" << endl
+ << "conn.statement_cache ().find_view<view_type> ());"
+ << endl
+ << "image_type& im (sts.image ());"
+ << "binding& imb (sts.image_binding ());"
+ << endl
+ << "if (im.version != sts.image_version () || imb.version == 0)"
+ << "{"
+ << "bind (imb.bind, im);"
+ << "sts.image_version (im.version);"
+ << "imb.version++;"
+ << "}"
+ << "shared_ptr<select_statement> st (" << endl
+ << "new (shared) select_statement (" << endl;
+
+ view_query_statement_ctor_args (c);
+
+ os << "));" << endl
+ << "st->execute ();";
+
+ post_query_ (c);
+
+ os << endl
+ << "shared_ptr<odb::result_impl<view_type, " <<
+ "class_view> > r (" << endl
+ << "new (shared) " << db <<
+ "::result_impl<view_type, class_view> (" << endl
+ << "q, st, sts));"
+ << endl
+ << "return result<view_type> (r);"
+ << "}";
+ }
+
+ //
+ // composite
+ //
+
virtual void
traverse_composite (type& c)
{
@@ -2863,7 +3024,7 @@ namespace relational
os << "}";
- // init (image, object)
+ // init (image, value)
//
os << "bool " << traits << "::" << endl
<< "init (image_type& i, const value_type& o)"
@@ -2880,7 +3041,7 @@ namespace relational
os << "return grew;"
<< "}";
- // init (object, image)
+ // init (value, image)
//
os << "void " << traits << "::" << endl
<< "init (value_type& o, const image_type& i, database& db)"
diff --git a/odb/relational/type-processor.cxx b/odb/relational/type-processor.cxx
index 12d2b52..362fab3 100644
--- a/odb/relational/type-processor.cxx
+++ b/odb/relational/type-processor.cxx
@@ -1087,16 +1087,16 @@ namespace relational
virtual void
traverse (type& c)
{
- bool obj (object (c));
+ bool ov (object (c) || view (c));
- if (!(obj || composite (c)))
+ if (!(ov || composite (c)))
return;
names (c);
- // Assign object pointer.
+ // Assign pointer.
//
- if (obj)
+ if (ov)
assign_pointer (c);
}
diff --git a/odb/validator.cxx b/odb/validator.cxx
index 435d480..0494741 100644
--- a/odb/validator.cxx
+++ b/odb/validator.cxx
@@ -80,10 +80,12 @@ namespace
//
struct id_member: traversal::class_
{
- id_member (bool object, bool& valid, semantics::data_member*& m)
- : object_ (object), member_ (valid, m)
+ id_member (class_kind kind, bool& valid, semantics::data_member*& m)
+ : kind_ (kind), member_ (valid, m)
{
- *this >> inherits_ >> *this;
+ if (kind != class_view)
+ *this >> inherits_ >> *this;
+
*this >> names_ >> member_;
}
@@ -92,18 +94,36 @@ namespace
{
// Skip transient bases.
//
- if (object_)
+ switch (kind_)
{
- if (!context::object (c))
- return;
- }
- else
- {
- if (!context::composite (c))
- return;
+ case class_object:
+ {
+ if (!context::object (c))
+ return;
+ break;
+ }
+ case class_view:
+ {
+ break;
+ }
+ case class_composite:
+ {
+ if (!context::composite (c))
+ return;
+ break;
+ }
+ case class_other:
+ {
+ assert (false);
+ break;
+ }
}
- inherits (c);
+ // Views don't have bases.
+ //
+ if (kind_ != class_view)
+ inherits (c);
+
names (c);
}
@@ -139,7 +159,7 @@ namespace
semantics::data_member*& m_;
};
- bool object_;
+ class_kind kind_;
member member_;
traversal::names names_;
traversal::inherits inherits_;
@@ -178,6 +198,8 @@ namespace
{
if (context::object (c))
traverse_object (c);
+ else if (context::view (c))
+ traverse_view (c);
else
{
if (context::composite (c))
@@ -241,18 +263,20 @@ namespace
if (context::object (b))
base = true;
- if (context::composite (b))
+ else if (context::view (b) || context::composite (b))
{
// @@ Should we use hint here?
//
string name (b.fq_name ());
cerr << c.file () << ":" << c.line () << ":" << c.column () << ":"
- << " error: base class '" << name << "' is a value type"
+ << " error: base class '" << name << "' is a view or value type"
<< endl;
cerr << c.file () << ":" << c.line () << ":" << c.column () << ":"
- << " info: object types cannot derive from value types" << endl;
+ << " info: object types cannot derive from view or value "
+ << "types"
+ << endl;
cerr << b.file () << ":" << b.line () << ":" << b.column () << ":"
<< " info: class '" << name << "' is defined here" << endl;
@@ -265,7 +289,7 @@ namespace
//
semantics::data_member* id (0);
{
- id_member t (true, valid_, id);
+ id_member t (class_object, valid_, id);
t.traverse (c);
}
@@ -328,6 +352,73 @@ namespace
}
virtual void
+ traverse_view (type& c)
+ {
+ // Check bases.
+ //
+ for (type::inherits_iterator i (c.inherits_begin ());
+ i != c.inherits_end ();
+ ++i)
+ {
+ type& b (i->base ());
+
+ if (context::object (b) ||
+ context::view (b) ||
+ context::composite (b))
+ {
+ // @@ Should we use hint here?
+ //
+ string name (b.fq_name ());
+
+ cerr << c.file () << ":" << c.line () << ":" << c.column () << ":"
+ << " error: base class '" << name << "' is an object, "
+ << "view, or value type"
+ << endl;
+
+ cerr << c.file () << ":" << c.line () << ":" << c.column () << ":"
+ << " info: view types cannot derive from view, object or "
+ << "value types"
+ << endl;
+
+ cerr << b.file () << ":" << b.line () << ":" << b.column () << ":"
+ << " info: class '" << name << "' is defined here" << endl;
+
+ valid_ = false;
+ }
+ }
+
+ // Check id.
+ //
+ semantics::data_member* id (0);
+ {
+ id_member t (class_view, valid_, id);
+ t.traverse (c);
+ }
+
+ if (id != 0)
+ {
+ cerr << id->file () << ":" << id->line () << ":" << id->column ()
+ << ": error: view type data member cannot be designated as "
+ << "object id" << endl;
+
+ valid_ = false;
+ }
+
+ // Check members.
+ //
+ member_.count_ = 0;
+ names (c);
+
+ if (member_.count_ == 0)
+ {
+ cerr << c.file () << ":" << c.line () << ":" << c.column () << ":"
+ << " error: no persistent data members in the class" << endl;
+
+ valid_ = false;
+ }
+ }
+
+ virtual void
traverse_composite (type& c)
{
bool base (false);
@@ -340,19 +431,20 @@ namespace
if (context::composite (b))
base = true;
- else if (context::object (b))
+ else if (context::object (b) || context::view (b))
{
// @@ Should we use hint here?
//
string name (b.fq_name ());
cerr << c.file () << ":" << c.line () << ":" << c.column () << ":"
- << " error: base class '" << name << "' is an object type"
+ << " error: base class '" << name << "' is a view or object "
+ << "type"
<< endl;
cerr << c.file () << ":" << c.line () << ":" << c.column () << ":"
<< " info: composite value types cannot derive from object "
- << "types" << endl;
+ << "or view types" << endl;
cerr << b.file () << ":" << b.line () << ":" << b.column () << ":"
<< " info: class '" << name << "' is defined here" << endl;
@@ -365,7 +457,7 @@ namespace
//
semantics::data_member* id (0);
{
- id_member t (false, valid_, id);
+ id_member t (class_composite, valid_, id);
t.traverse (c);
}