[odb-users] possible solution to 'friend' declaration,
pragma setters and getters
Brown, Matt C
Brown223 at llnl.gov
Thu Oct 20 14:04:27 EDT 2011
As I understand it, you can full odb-ilize any object fully from outside of it using pragmas with one giant horrible exception, the requirement that it be made a friend of odb::access, and one slightly smaller requirement that it have a default constructor (which, due to friendship, can remain private).
One solution (it's very much a Boris does more work type solution), would be to all specification of setter and getter functions (and construction) in the pragma language.
So, for instance take the following example coded up in the standard odb manner:
//Foo.h
#include <odb/core.hxx> //****
#pragma db object //****
class Foo {
explicit Foo(int id);
void set_val(int v) {val_ = v;}
int val() const {return val_;}
void set_id(int v) {id_ = v;}
int id() const {return id_;}
private:
friend class odb::access;//****
Foo(){}//****
#pragma db id auto//****
int id_;
int val_;
};
And again with as odb-less as we can get at the moment:
//Foo.h
#include <odb/core.hxx>//****
class Foo {
explicit Foo(int id);
void set_val(int v) {val_ = v;}
int val() const {return val_;}
void set_id(int v) {id_ = v;}
int id() const {return id_;}
private:
friend class odb::access;//****
Foo(){}//****
int id_;
int val_;
};
//Foo.oxx
#pragma db object(Foo)
#pragma db member(Foo::id_) id auto
#pragma db member(Foo::val_)
What I'm proposing would be something like the following:
//Foo.h
class Foo {
explicit Foo(int id);
void set_val(int v) {val_ = v;}
int val() const {return val_;}
void set_id(int v) {id_ = v;}
int id() const {return id_;}
private:
Foo(){}// don't allow default constructor
int id_;
int val_;
};
//Foo.oxx
#pragma db object(Foo) construct(Foo(id))... <not really sure how to handle this>)
#pragma db member(Foo::id_) set(set_id) get(id) id auto
#pragma db member(Foo::val_) set(set_val) get(val)
Looking at the way code is generated, it should be possible to do something like this. There are of course lots and lots and lots of details in adding this feature. I obviously left the 'construct' case ambiguous. And there are plenty of more complicated cases (for instance, what if there is a set_all(int id, int val) function, and you want to somehow use that). But, I think providing basic support would be a great leap forward in flexibility. From the ODB documentation: "It does not dictate how you should write your application. Rather, it is designed to fit into your style and architecture by only handling object persistence and not interfering with any other functionality". Currently it restricts what object you're allow make persistent, a major source of sadness.
In case you're curious, I'm trying to mash-up google protocol buffers and odb. Protobuf also uses code generation. While it is probably possible to modify its code generator to include the necessary odb hooks (i.e. friend declaration, pragmas, etc). I'd rather not go mucking about in their code. However, they DO have a plug-in interface that makes it easy to create an separate #pragma file, and all the hard-core low level template meta stuff to hook it into odb (i.e. template specializations for odb::sqlite::default_value_traits<GeneratedType,id_blob> {...}). But it required me to learn a lot about how the template underpinnings of odb work, and so far I'm just treating them as opaque blobs. I don't want to think about what would be required to actually break out the individual members from the protobufs. But, with the addition of the setter/getting pragma thing, it would be pretty trivial to do the full-blown mash-up.
In general, I think adding this feature would make it MUCH simpler to add 'native' support for new 3rd-party types. For instance, if I wanted to add support for something like QRect (a simple rectangle class from qt), right now I'd have to go write a specialization for each database type, and teach odb how to find it (i.e. options files). With this feature, you can just include the QRect-odb.hxx file, which would just be about 5 pragmas, and would work regardless of db.
I get that this is a pretty involved feature, but right now it's out of reach for many programmers to add support for 3rd-party types.
-Matt
b.t.w. I've only been playing with odb for about 2 weeks, and I didn't do a rigorous search of the mailing lists to see if this has been discussed. So I greatly apologize if there is already a solution to this problem.
More information about the odb-users
mailing list