[odb-users] Re: ODB compiler crash

Boris Kolpackov boris at codesynthesis.com
Thu Sep 18 05:00:45 EDT 2014


Hi Marcel,

[I've CC'ed ODB users since others might have similar questions.]

Marcel Nehring <mne at qosmotec.com> writes:

> 1) For a custom type (boost::posix_time::ptime or boost::posix_time::
> time_period in my example), when I specify the database column type with the
> type pragma is there a way to do it on a portable way? For example if I want
> to have a text column and I am using Oracle I would write something like
> VARCHAR2(X) but when switching to MySQL this would fail.

The data types in various databases are inherently non-portable. So what
you can do is specify a suitable type for each database that you plan to
support. To achieve this ODB allows you to prefix a pragma with the
database name, for example:

#pragma db oracle:type("VARCHAR2(10)") mysql:type("TEXT")

You can still use the unprefixed pragma (which must come before any
prefixed ones) as the default, catch-all type for all the other
databases:

#pragma db type("TEXT") oracle:type("VARCHAR2(10)")

One trick that you can do with this catch-all semantics is to specify
an invalid type for all the databases that you currently do not support:

#pragma db type("BADTYPE") oracle:type("VARCHAR2(10)")

This way, if in the future you port to a new database, you will get
compile-time errors pointing to the places where you need to decided
which types to use.

A couple of other notes:

1. You can specify the database type both on the member and C++ type
   basis (or both), for example:

#pragma db value (std::string) oracle:type("VARCHAR2(100)")

class person
{
  #pragma db oracle:type("VARCHAR2(10)")
  std::string first_;

  std::string last_; // VARCHAR2(100)
}

2. Not all (re)mappings from C++ types to database types will work out
   of the box. For example, if you want to store boost::posix_time::ptime
   in Oracle as VARCHAR2, then simply specifying one of the above pragmas
   won't be enough since ODB doesn't know what format it should be in nor
   does it include code for every such C++/database type combination (which
   alternative mappings are provided is mentioned in the documentation;
   for example, for Oracle, ptime can be mapped to DATE in addition to
   the default TIMESTAMP).

   But you can always implement such a mapping code yourself as described
   in this article:

   http://www.codesynthesis.com/~boris/blog/2012/10/16/custom-cxx-to-database-type-mapping-in-odb/


> 2) The --sql-name-case switch of the ODB compiler does not apply to the
> schema version table. Is this by design?

Yes, this is by design since the name of this table is used in the ODB
runtime (libodb). But you can give this table a custom name. From the
ODB compiler command line manual (man pages):

--schema-version-table <name>

  Specify the alternative schema version table name instead of the default
  schema_version. If you specify this option then you are also expected to
  manually specify the schema version table name at runtime using the
  odb::database::schema_version_table() function. The table name can be
  qualified.


> 3) When using the --at-once switch of the ODB compiler I have to manually
> provide all persistent class headers by hand? Would it be possible to make
> ODB ignore any header file that contains only classes that are not
> persisted? One could then simply use *.h or similar and ODB would
> automatically filter out the subset to use. At the moment I am using a
> custom script to pass the correct filenames to ODB.

Yes, this will work with a few caveats:

1. If you are using the at-once mode for schema generation, then the only
   drawback is longer ODB compilation time since it has to compile these
   "no-persistent" files.

2. If you are using the at-once mode for C++ code generation (i.e., one
   huge -odb.cxx file; generally not recommended), then in addition to
   the above drawback the generated code will also #include the "no-
   persistent" files which will at least increase the C++ compilation
   time and may have other consequences depending on what's inside those
   files.

For general understanding, what ODB does under the hood in the at-once
mode is simply synthesize a header file that #include's all the input
files and then compiles that.

Boris



More information about the odb-users mailing list