[odb-users] accessing meta information

Boris Kolpackov boris at codesynthesis.com
Mon Sep 29 04:57:33 EDT 2014


Hi Christian,

Christian Sell <christian at gsvitec.com> writes:

> One requirement would be the availability of meta information about the
> mapped classes, from which we could generate a UI. The required information
> would be stuff along the lines of "what mapped attributes are there, of what
> types are they", and "what relationships exist".
> 
> My question would be whether ODB has anything to offer along that path.  As
> I see it, there are 2 conceivable approaches for obtaining the information,
> i.e.  during parsing or at runtime. Runtime would rely completely on
> existant ODB APIs, and parse time could be achieved by integrating with the
> ODB parser.

I think it will have to be something that you generate (e.g., C++ code).
Currently, ODB doesn't provide any meta-information about the persistent
classes. But even if it did, I don't think just knowing what data members
there are and their types will be sufficient. Next you will probably
want to be able to access/modify these data members from your UI. And
that would be even further out of the ODB's scope. So that's why I
think code generation is the way to go for this.

You have mentioned customizing the ODB parser (more precisely, you
would customize the ODB's C++ code generator). This is definitely
doable and will give you the most control. There will be very few
things you won't know about the mapped classes or won't be able to
do. But, this may require some effort, depending on how far away
from the way ODB does things now you want to take it.

There is also another interesting option that will be a lot easier
to implement than ODB customization. ODB supports database schema
evolution (Chapter 13 in the ODB manual) and for that it keeps a
changelog. The changelog is an XML file that consists of the base
model description and a changeset for each version. And that base
model description is essentially the mapping of your C++ classes
to the database. As an example, say we have these two classes:

#pragma db object
struct user
{
  #pragma db id
  std::string email_;
  std::string name_;

  #pragma db inverse(reporter_)
  std::vector<std::weak_ptr<bug>> reported_bugs_;
};

#pragma db object
struct bug
{
  #pragma db id auto
  unsigned long long id_;

  status status_;
  std::string summary_;
  std::string description_;

  std::shared_ptr<user> reporter_;
};

The base model for these classes will look like this (using 
PostgreSQL in this example):

  <model version="1">
    <table name="user" kind="object">
      <column name="email" type="TEXT" null="false"/>
      <column name="name" type="TEXT" null="false"/>
      <primary-key>
        <column name="email"/>
      </primary-key>
    </table>
    <table name="bug" kind="object">
      <column name="id" type="BIGINT" null="false"/>
      <column name="status" type="INTEGER" null="false"/>
      <column name="summary" type="TEXT" null="false"/>
      <column name="description" type="TEXT" null="false"/>
      <column name="reporter" type="TEXT" null="true"/>
      <primary-key auto="true">
        <column name="id"/>
      </primary-key>
      <foreign-key name="reporter_fk" deferrable="DEFERRED">
        <column name="reporter"/>
        <references table="user">
          <column name="email"/>
        </references>
      </foreign-key>
    </table>
  </model>

Now this is clearly a description of the database schema, not C++
classes. But, given that you follow a consistent convention in your
code (e.g., that all data members end with '_', use std::string
to represent text, etc), then it is fairly easy to reconstruct
the C++ classes that this has been generated from. And once you
have this, you can generate UI layouts, C++ code, etc. If I were
you, I would seriously consider if this simpler approach will
work.

Boris



More information about the odb-users mailing list