From an9bit at gmail.com Fri Jun 1 06:39:01 2012 From: an9bit at gmail.com (Andrey Devyatka) Date: Fri Jun 1 06:38:45 2012 Subject: [odb-users] Support c++11 Message-ID: <4FC89BC5.8080204@gmail.com> Hi, odb-users, Hi, Boris I'm using c++11 with odb 2.0.0. Now for the processing of query results, I use the following code: std::list> list; auto res = db->query(query); for(auto at = std::begin(res); at != std::end(res); ++at) list.push_back(std::shared_ptr(at.load())); I would like to use a range-based for-loops for the sample results: for( auto at : res) { list.push_back(std::shared_ptr(at.load())); // so list.push_back(std::shared_ptr(at)); // or so } Is it possible? Andrey From an9bit at gmail.com Fri Jun 1 07:28:14 2012 From: an9bit at gmail.com (Andrey Devyatka) Date: Fri Jun 1 07:27:50 2012 Subject: [odb-users] Re: Support c++11 In-Reply-To: <4FC89BC5.8080204@gmail.com> References: <4FC89BC5.8080204@gmail.com> Message-ID: <4FC8A74E.8080705@gmail.com> Hi, odb-users, Hi, Boris, Sorry, I did not read the documentation. Everything is written: for(DBO at : res) { list.push_back(std::shared_ptr(new DBO(at))); } Sorry. Andrey 01.06.2012 16:39, Andrey Devyatka ???????: > Hi, odb-users, > Hi, Boris > > I'm using c++11 with odb 2.0.0. > > Now for the processing of query results, I use the following code: > > std::list> list; > auto res = db->query(query); > for(auto at = std::begin(res); at != std::end(res); ++at) > list.push_back(std::shared_ptr(at.load())); > > I would like to use a range-based for-loops for the sample results: > > for( auto at : res) { > list.push_back(std::shared_ptr(at.load())); // so > list.push_back(std::shared_ptr(at)); // or so > } > > Is it possible? > > Andrey From boris at codesynthesis.com Fri Jun 1 11:51:27 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Fri Jun 1 11:51:34 2012 Subject: [odb-users] Support c++11 In-Reply-To: <4FC89BC5.8080204@gmail.com> References: <4FC89BC5.8080204@gmail.com> Message-ID: Hi Andrey, I am glad you found an answer to your question. However, here are some efficiency/correctness suggestions: Andrey Devyatka writes: > auto res = db->query(query); > for( auto at : res) { Here you are making a copy of an object as you are iterating because 'at' is a value. If the object is not polymorphic, then this will be just less efficient. Howevere, if the object is polymorphic, then the copy could be "sliced". A better way is to make 'at' a reference: auto res = db->query (query); for (auto& at : res) { Also, we can move the call to query() inside the for-loop: for (auto& at : db->query (query)) { > for(DBO at : res) { > list.push_back(std::shared_ptr(new DBO(at))); > } Here you are making two copies, the first as dicussed above, and the second explicitly. If you want a pointer to the object, then it is more efficient to use the load() function, wich will allocate, initialize, and return the object without making any copies. In this case, however, we cannot use the range-based for-loop since we need access to the iterator: for (auto i = res.begin (); i != res.end (); ++i) list.push_back (std::shared_ptr (i.load ())); If DBO's canonical object pointer is std::shared_ptr, then this code can be simplified further since load() will return the pointer as shared_ptr: for (auto i = res.begin (); i != res.end (); ++i) list.push_back (i.load ()); Boris From boris at codesynthesis.com Sat Jun 2 14:22:05 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Sat Jun 2 14:22:11 2012 Subject: [odb-users] Re: how to properly use odb::nullable In-Reply-To: References: Message-ID: Hi Huy, In the future please send technical questions like these to the odb-users mailing list (which I've CC'ed) instead of to me directly, as discussed in the posting guidelines: http://www.codesynthesis.com/support/posting-guidelines.xhtml Huy Nguyen writes: > I'm trying use odb::nullable to create a NULL value (this value > is also the referential foreign key, this is key *controller_id*) > > My *constructor *is defined: > > sources (int id, int controller_id) > : id_(id) , controller_id_(controller_id){} > > In my private member I have: > > #pragma db id auto > int id_ ; > odb::nullable controller_id_; > > I'm creating a transient object with: > sources sourcesA (125,NULL); > > But the persist failed because of the foreign key check even though the > foreign key is set to allow NULL value. The int type doesn't have a notion of the special NULL value. The way you create your object is essentially equivalent to this: sources sourcesA (125, 0); Which will initialize the controller_id_ member to 0 int value, not the NULL special value (that's also the reason why we have to wrap int with odb::nullable). One way to fix your constructor is to pass a pointer to int, which will give us a special value (NULL pointer): sources (int id, const int* controller_id) : id_ (id) { if (controller_id != 0) controller_id_ = *controller_id; } The problem with this constructor is that it is inconvenient to use if you want to pass a non-NULL value. Now we have to write: int cid (123) sources sourcesA (125, &cid); Instead of just: sources sourcesA (125, 123); So instead of passing a pointer you may want to add another overload of the constructor that will be used to create objects with controller_id set to NULL: sources (int id, int controller_id) : id_ (id), controller_id_ (controller_id) {} sources (int id) : id_ (id) {} Now we can write: sources sourcesA (125, 123); // controller_id is 123 sources sourcesB (126); // controller_id is NULL Yet another option is to use odb::nullable instead of int as the controller_id parameter. For more information on the odb::nullable interface, refer to Section 7.3, "Pointers and NULL Value Semantics" in the ODB manual: http://www.codesynthesis.com/products/odb/doc/manual.xhtml#7.3 Boris From crburton at tnsi.com Tue Jun 5 13:21:24 2012 From: crburton at tnsi.com (Burton, Craig) Date: Tue Jun 5 13:21:58 2012 Subject: [odb-users] query results not being cached? Message-ID: Hi ODB Users, I am not able to call "size()" on query results even if I try to use the "cache()" method on the results template. Here's the code snippet: auto_ptr ora_db (create_database (argc, argv)); transaction t (ora_db->begin()); MyPersistentClass *n = new MyPersistentClass (i); try { cout << "About to call query..." << endl; query pred (query:: name == n->name()); result r (ora_db->query (pred) ); r.cache(); cout << "...back." << endl; if ( r.empty() == true ) { cout << "no instances found..." << endl; } cout << "Query returned " << r.size() << " elements." << endl; } catch (const odb::exception& e) { cerr << e.what () << endl; } This is the output: About to call query... ...back. no instances found... Query returned query result is not cached So, r.empty() works, but r.size() does not. Is it possible to examine the size/count of the query result without iterating over it? Thanks in advance, Craig ________________________________ This e-mail message is for the sole use of the intended recipient(s)and may contain confidential and privileged information of Transaction Network Services. Any unauthorised review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply e-mail and destroy all copies of the original message. From boris at codesynthesis.com Wed Jun 6 03:15:28 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Wed Jun 6 03:15:35 2012 Subject: [odb-users] query results not being cached? In-Reply-To: References: Message-ID: Hi Craig, Burton, Craig writes: > I am not able to call "size()" on query results even if I try to use > the "cache()" method on the results template. For some databases (right now Oracle, SQLite, and MS SQL Server), caching (and therefore size()) is not supported. This is documented in the database-specific chapters. For Oracle that would be Section 16.5.2, "Query Result Caching": http://www.codesynthesis.com/products/odb/doc/manual.xhtml#16.5.2 If you are interested, in the case or Oracle, supporting size() would require switching the query result cursor to the scrollable mode. This results in a much worse performance compared to the forward-only mode. There is also a long and complicated list of limitations of scrollable cursors that stipulate the kind of situations that are not supported (specifically, support for BLOB/LONG types is very limited). So it is better to try not to rely on knowing in advance the number of entries in the result. Specifically, any optimizations that you may want to make (e.g., reserve the space in the vector, etc), will be inconsequential compared to the cost of supporting size(). If you really need to know the size prior to the iteration, then the best you can do is probably run a separate query that returns the count, for example: #pragma db view object(MyPersistentClass) struct MyPersistentClassCount { #pragma db column("count(*)") std::size_t count; }; size_t count = ora_db->query (pred)->begin ()->count; Boris From rene at catatonic.dk Wed Jun 6 08:30:57 2012 From: rene at catatonic.dk (Rene Jensen) Date: Wed Jun 6 08:31:04 2012 Subject: [odb-users] Proper way to reload QLazySharedPointer objects within a session Message-ID: Hi odb-list. I am trying to map a hierachy of objects into a Qt tree view model. In order to keep potential problems to a minimum, I decided that whenever anything is changed, all data should simple be reloaded. My database object is trivial: #pragma db object session #pragma db object table("my_table_name") #pragma db object pointer(QSharedPointer) class MyObject: public ProxyBase { public: friend class odb::access; #pragma db id auto qint32 id; #pragma db null #pragma db column("super_id") QLazySharedPointer supergroup; #pragma db value_not_null inverse(supergroup) QList > subgroups; }; ... which clearly forms a tree. I recursively load all objects at startup (again, to minimize chance of complications), and upon any change, I want to reload everything. First I try to flush: foreach (MyObject_LazySharedPointer P, myPool.values()): { P.unload(); } Trouble with duplicated instances forced me to use sessions. Now I cannot properly reload the tree, even though I call QLazySharedPointer::reload on all my instances: for (MyObject_Result::iterator I (result.begin()); I != result.end(); ++I) { MyObject_LazySharedPointer P = I.load(); db->reload (P.data()); myPool[ P->id) ] = P; loadRecursively(P); // ... doing the same thing inside loadRecursively: reload each subgroup... } --------------- A slightly confusing setup, I admit. Here's the question: Can database::reload be used to force a reload of an object that is already owned by a QLazySharedPointer? Assuming I can't get rid of all QLazySharedPointers. Is there any way to force a reload of those objects? Best regards, Rene Jensen From boris at codesynthesis.com Wed Jun 6 09:50:38 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Wed Jun 6 09:50:44 2012 Subject: [odb-users] Proper way to reload QLazySharedPointer objects within a session In-Reply-To: References: Message-ID: Hi Rene, Rene Jensen writes: > I want to reload everything. First I try to flush: > > foreach (MyObject_LazySharedPointer P, myPool.values()): > { > P.unload(); > } I assume myPool is some map of object ids to LazySharedPointer. Then, provided nobody else holds pointers to these objects, the above should simply release all the objects in your pool. So you are not really reloading in the sense of refreshing the state of existing objects from the database. Rather, you are simply freeing the old objects and loading new ones. BTW, I don't see a good reason for using LazySharedPointer in the pool. To me it looks like normal SharedPointer will work just as well (and hopefully will minimize the confusion). > Trouble with duplicated instances forced me to use sessions. Yes, you have cycles (parent pointing to child and child pointing to parent), so you need to use the session to be able to properly load the whole thing. > Now I cannot properly reload the tree, even though I call > QLazySharedPointer::reload on all my instances: What exactly doesn't work? > for (MyObject_Result::iterator I (result.begin()); I != > result.end(); ++I) > { > MyObject_LazySharedPointer P = I.load(); > db->reload (P.data()); I don't see a point in calling reload() on an object that has just been loaded, unless a "stale" instance was cached in the session. But as far as I can see, this shouldn't happen in your case. To make sure that's the case, you may want to limit the lifetime of the session so that it is in effect only when you load the pool. For example: { session s; for (MyObject_Result::iterator I (result.begin()); ...) { ... } } If the objects are not shared among the trees, then you should even be able to move the session inside the for-loop: for (MyObject_Result::iterator I (result.begin()); ...) { session s; ... } > A slightly confusing setup, I admit. No kidding ;-). > Can database::reload be used to force a reload of an object that > is already owned by a QLazySharedPointer? Yes, provided QLazySharedPointer is loaded (i.e., it points to the object instead of just containing the id), call to reload() will reload its state from the database. Boris From crburton at tnsi.com Wed Jun 6 13:58:03 2012 From: crburton at tnsi.com (Burton, Craig) Date: Wed Jun 6 13:58:48 2012 Subject: [odb-users] query results not being cached? In-Reply-To: References: Message-ID: Hi Boris, My apologies; I see now (with some embarrassment) that this specific Oracle limitation is well documented. Under many circumstances, our application expects to find exactly zero or one instance for many specific queries, but finding two or more would lead to an error scenario. Application logic is the following in many such cases: if zero instances, create a new one if one instance, update the one found in the db if two or more, do nothing and return an error Your alternative approach using the view works well for my needs, since I can determine the count and then perform the query if there is, indeed, only one instance. I don't see a clean way to do the same by only iterating over the result, unless the iteration determines the count and temporarily holds a reference to the single instance (if there is only one). I'll continue to try a few different approaches to see which one is most compatible with our current implementation. Thanks again for your help! Craig -----Original Message----- From: Boris Kolpackov [mailto:boris@codesynthesis.com] Sent: Wednesday, June 06, 2012 12:15 AM To: Burton, Craig Cc: odb-users@codesynthesis.com Subject: Re: [odb-users] query results not being cached? Hi Craig, Burton, Craig writes: > I am not able to call "size()" on query results even if I try to use > the "cache()" method on the results template. For some databases (right now Oracle, SQLite, and MS SQL Server), caching (and therefore size()) is not supported. This is documented in the database-specific chapters. For Oracle that would be Section 16.5.2, "Query Result Caching": http://www.codesynthesis.com/products/odb/doc/manual.xhtml#16.5.2 If you are interested, in the case or Oracle, supporting size() would require switching the query result cursor to the scrollable mode. This results in a much worse performance compared to the forward-only mode. There is also a long and complicated list of limitations of scrollable cursors that stipulate the kind of situations that are not supported (specifically, support for BLOB/LONG types is very limited). So it is better to try not to rely on knowing in advance the number of entries in the result. Specifically, any optimizations that you may want to make (e.g., reserve the space in the vector, etc), will be inconsequential compared to the cost of supporting size(). If you really need to know the size prior to the iteration, then the best you can do is probably run a separate query that returns the count, for example: #pragma db view object(MyPersistentClass) struct MyPersistentClassCount { #pragma db column("count(*)") std::size_t count; }; size_t count = ora_db->query (pred)->begin ()->count; Boris This e-mail message is for the sole use of the intended recipient(s)and may contain confidential and privileged information of Transaction Network Services. Any unauthorised review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply e-mail and destroy all copies of the original message. From philly.dilly at gmail.com Wed Jun 6 22:04:58 2012 From: philly.dilly at gmail.com (Philippe Cadieux-Pelletier) Date: Thu Jun 7 02:45:12 2012 Subject: [odb-users] SQLite and std::wstring Message-ID: It seems like a pretty severe shortcoming of the SQLite database binding not to support std::wstring. Are there any plans to add support? I can think of two ways to add support off the top of my head: 1. Have some kind of setting, either at compile time or runtime, that will bind SQLite's TEXT type to std::wstring and configure the SQLite database to use utf16 for TEXT. This would mean that you would have to pick either utf8 or utf16, but at least you'd have the option of supporting std::wstring. 2. C++ 11 adds std::codecvt_utf8_utf16 to convert between utf8 and utf16. It would then be possible to convert at runtime therefore being able to support both std::string and std::wstring Thanks! From philly.dilly at gmail.com Wed Jun 6 22:09:03 2012 From: philly.dilly at gmail.com (Philippe Cadieux-Pelletier) Date: Thu Jun 7 02:45:13 2012 Subject: [odb-users] Streaming BLOBs Message-ID: Are there any plans to add support to stream blobs, let's say by binding std::istream to blobs? From boris at codesynthesis.com Thu Jun 7 03:11:32 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Thu Jun 7 03:11:38 2012 Subject: [odb-users] query results not being cached? In-Reply-To: References: Message-ID: Hi Craig, Burton, Craig writes: > Under many circumstances, our application expects to find exactly zero > or one instance for many specific queries, but finding two or more would > lead to an error scenario. Application logic is the following in many > such cases: > > if zero instances, create a new one > if one instance, update the one found in the db > if two or more, do nothing and return an error If we can assume that the error scenario is quite rare and not performance- sensitive, this can be handled optimally for the other two cases by doing a "speculative" load (i.e., with the expectation that there is no error) and then checking for the error condition: result r = ...; if (r.empty ()) { // Zero instances. } else { result::iterator i (r.begin ()); shared_ptr obj (i.load ()); if (++i != r.end ()) { // More than one instance (error). return/throw; } // One instance. } Boris From boris at codesynthesis.com Thu Jun 7 08:46:40 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Thu Jun 7 08:46:47 2012 Subject: [odb-users] SQLite and std::wstring In-Reply-To: References: Message-ID: Hi Philippe, Philippe Cadieux-Pelletier writes: > It seems like a pretty severe shortcoming of the SQLite database binding > not to support std::wstring. I wouldn't call it "severe" since you can easily add a custom mapping for the std::wstring type (see the 'mapping' example). > Are there any plans to add support? Yes, we can implement built-in support if you need it. > I can think of two ways to add support off the top of my head: > > 1. Have some kind of setting, either at compile time or runtime, that > will bind SQLite's TEXT type to std::wstring and configure the SQLite > database to use utf16 for TEXT. This would mean that you would have to pick > either utf8 or utf16, but at least you'd have the option of supporting > std::wstring. > 2. C++ 11 adds std::codecvt_utf8_utf16 to convert between utf8 and > utf16. It would then be possible to convert at runtime therefore being able > to support both std::string and std::wstring In SQLite the database encoding (specified with 'PRAGMA encoding') and the encoding used in the application to bind parameters/results are somewhat independent. That is, if the database is UTF-8 and we pass UTF-16 text or if the database is UTF-16 and we pass UTF-8, then SQLite performs automatic conversions as required. So, in this light, it would be best to pass std::wstring as UTF-16 and let SQLite determine what to do. This will also give the user the flexibility to make the database either UTF-8 or UTF-16 without any changes to ODB or generated code. BTW, which database encoding are you planning to use in your case? Boris From boris at codesynthesis.com Thu Jun 7 09:00:58 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Thu Jun 7 09:01:08 2012 Subject: [odb-users] Streaming BLOBs In-Reply-To: References: Message-ID: Hi Philippe, Philippe Cadieux-Pelletier writes: > Are there any plans to add support to stream blobs, let's say by binding > std::istream to blobs? If this is for a member of a persistent class, then you would need a bi-directional stream (i.e., std::iostream), since it will have to support both reading (for persist, update, etc.) and writing (for load, query, etc). There are only two cases where you may want to use a unidirectional stream: in query parameters (std::istream) and in views (std::ostream). However, I am still having a hard time coming up with a realistic use case for this. Can you provide a bit more details on what you are trying to achieve? Also note that currently ODB doesn't use the SQLite BLOB streaming mechanism (i.e., sqlite3_blob_open() & friends[1]) for BLOB reading/ writing. We may support this in the future (as we do for some other databases, e.g., Oracle and MS SQL), though there are some tricky limitations of this mechanism in SQLite that we still need to think about. [1] http://www.sqlite.org/c3ref/blob_open.html Boris From philly.dilly at gmail.com Thu Jun 7 09:47:51 2012 From: philly.dilly at gmail.com (philly.dilly@gmail.com) Date: Thu Jun 7 09:50:29 2012 Subject: [odb-users] Streaming BLOBs In-Reply-To: Message-ID: Hi Boris, The use case I had in mind was for backing up user provided documents of unknown size which could get as big as several hundred megabytes. I know this is an edge case scenario since a database (specially a light weight one like sqlite) isn't really the place to save such big documents! On , Boris Kolpackov wrote: > Hi Philippe, > Philippe Cadieux-Pelletier philly.dilly@gmail.com> writes: > > Are there any plans to add support to stream blobs, let's say by binding > > std::istream to blobs? > If this is for a member of a persistent class, then you would need a > bi-directional stream (ie, std::iostream), since it will have to > support both reading (for persist, update, etc.) and writing (for > load, query, etc). > There are only two cases where you may want to use a unidirectional > stream: in query parameters (std::istream) and in views (std::ostream). > However, I am still having a hard time coming up with a realistic use > case for this. Can you provide a bit more details on what you are trying > to achieve? > Also note that currently ODB doesn't use the SQLite BLOB streaming > mechanism (ie, sqlite3_blob_open() & friends[1]) for BLOB reading/ > writing. We may support this in the future (as we do for some other > databases, eg, Oracle and MS SQL), though there are some tricky > limitations of this mechanism in SQLite that we still need to think > about. > [1] http://www.sqlite.org/c3ref/blob_open.html > Boris From philly.dilly at gmail.com Thu Jun 7 09:53:59 2012 From: philly.dilly at gmail.com (philly.dilly@gmail.com) Date: Thu Jun 7 09:59:23 2012 Subject: [odb-users] SQLite and std::wstring In-Reply-To: Message-ID: Hi (again) Boris, Although utf8 is generally a more compact encoding, in my case I will be using wstring since my application deals with a lot of non latin languages and processing utf16 is a lot easier. I tried mapping std::wstring to TEXT with pragmas but then I got some compilation errors about wrong number of arguments or something. I'll definitely look into the mapping example! Cheers, Phil On , Boris Kolpackov wrote: > Hi Philippe, > Philippe Cadieux-Pelletier philly.dilly@gmail.com> writes: > > It seems like a pretty severe shortcoming of the SQLite database binding > > not to support std::wstring. > I wouldn't call it "severe" since you can easily add a custom mapping > for the std::wstring type (see the 'mapping' example). > > Are there any plans to add support? > Yes, we can implement built-in support if you need it. > > I can think of two ways to add support off the top of my head: > > > > 1. Have some kind of setting, either at compile time or runtime, that > > will bind SQLite's TEXT type to std::wstring and configure the SQLite > > database to use utf16 for TEXT. This would mean that you would have to > pick > > either utf8 or utf16, but at least you'd have the option of supporting > > std::wstring. > > 2. C++ 11 adds std::codecvt_utf8_utf16 to convert between utf8 and > > utf16. It would then be possible to convert at runtime therefore being > able > > to support both std::string and std::wstring > In SQLite the database encoding (specified with 'PRAGMA encoding') and > the encoding used in the application to bind parameters/results are > somewhat independent. That is, if the database is UTF-8 and we pass > UTF-16 text or if the database is UTF-16 and we pass UTF-8, then > SQLite performs automatic conversions as required. So, in this light, > it would be best to pass std::wstring as UTF-16 and let SQLite > determine what to do. This will also give the user the flexibility > to make the database either UTF-8 or UTF-16 without any changes to > ODB or generated code. > BTW, which database encoding are you planning to use in your case? > Boris From hurdad at gmail.com Thu Jun 7 18:32:04 2012 From: hurdad at gmail.com (Alex Hurd) Date: Thu Jun 7 23:15:39 2012 Subject: [odb-users] libodb-mysql.so Undefined Reference to 'THR_KEY_msys' Message-ID: All, libodb-2.0.0 + libodb-mysql-2.0.0 + Fedora 16 + mysqlclient.so.18 Compiling and installing libodb and libodb-mysql works fine. However, when linking I get the following error: $ ld -lodb-mysql ld: warning: cannot find entry symbol _start; not setting start address /usr/local/lib/libodb-mysql.so: undefined reference to `THR_KEY_mysys' This variable is used in 'connection-factory.hxx' but I don't understand how it would compile and get the error during runtime. I have compiled the same libs on ubuntu + mysqlclient.so.16 without the above issue. Please advise -alex h From boris at codesynthesis.com Fri Jun 8 09:52:53 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Fri Jun 8 09:52:58 2012 Subject: [odb-users] SQLite and std::wstring In-Reply-To: References: Message-ID: Hi Phil, philly.dilly@gmail.com writes: > Although utf8 is generally a more compact encoding, in my case I will be > using wstring since my application deals with a lot of non latin > languages and processing utf16 is a lot easier. Yes, I understand that you want to use wstring/UTF-16 in the application. What I was curious about is which encoding you were planning to use in the database (you have a choice of UTF-8 or UTF-16, and it seems UTF-8 is generally recommended since it results in a more compact database and thus better performance). > I tried mapping std::wstring to TEXT with pragmas but then I got some > compilation errors about wrong number of arguments or something. Yes, since there is not built-in support for std::wstring (yet), you will need to implement a value_traits specialization for it which will need to convert to/from UTF-8, since that's the only "image" currently supported by ODB for SQLite TEXT. The 'mapping' example has more information on how to do this. Boris From boris at codesynthesis.com Fri Jun 8 10:08:10 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Fri Jun 8 10:08:16 2012 Subject: [odb-users] Streaming BLOBs In-Reply-To: References: Message-ID: Hi Phil, philly.dilly@gmail.com writes: > The use case I had in mind was for backing up user provided documents of > unknown size which could get as big as several hundred megabytes. So I guess you will have something like an std::fstream as a member in your persistent class? I guess that could work if you open it for reading before calling persist() or update() and open it for writing before calling load(). You can add support for the fstream to BLOB mapping in exactly the same way as for std::wstring, which we discussed in another thread (for those reading just this thread, see the 'mapping' example for details). Maybe we will add built-in support for this in the future, but at the moment this feels a bit too "new" to me (especially the fact that one needs to open the file before performing database operations). Perhaps you can give us some feedback on how this works out for you. > I know this is an edge case scenario since a database (specially a > light weight one like sqlite) isn't really the place to save such > big documents! The SQLite BLOB streaming mechanism (sqlite3_blob_open(), etc.) actually seems like it was made for this kind of use cases. You can still store that kind of BLOBs into SQLite even with the current mechanism used by ODB (i.e., copy the whole thing into a memory buffer and pass it to SQLite). But I think it is a good idea to support streaming as an alternative. Added to my TODO. Boris From boris at codesynthesis.com Fri Jun 8 11:22:19 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Fri Jun 8 11:22:28 2012 Subject: [odb-users] libodb-mysql.so Undefined Reference to 'THR_KEY_msys' In-Reply-To: References: Message-ID: Hi Alex, Alex Hurd writes: > libodb-2.0.0 + libodb-mysql-2.0.0 + Fedora 16 + mysqlclient.so.18 > > Compiling and installing libodb and libodb-mysql works fine. > > However, when linking I get the following error: > > $ ld -lodb-mysql > ld: warning: cannot find entry symbol _start; not setting start address > /usr/local/lib/libodb-mysql.so: undefined reference to `THR_KEY_mysys' I did some investigating and here is the story: THR_KEY_mysys is a global variable in libmysqlclient that contains the thread-specific storage key that is used my MySQL. We use this key to work around some issues in trying to handle MySQL per-thread initialization/termination automatically and transparently (for the gory details, see the long comment at the beginning of the connection-factory.cxx file). This works well ith the vanilla build of the libmysqlclient library. However, Fedora folks did some customizations to the build procedure. Specifically, they limited the number of symbols that are visible form the library. They only included the public interface plus some internal functions used by other software (e.g., PHP). > This variable is used in 'connection-factory.hxx' but I don't understand > how it would compile and get the error during runtime. Shared libraries can have undefined symbols. However, we pass the --no-undefined option to libtool to make sure this doesn't happen. So this is strange. In any case, I've come up with a workaround for the missing symbols. Can you give this package a try: http://www.codesynthesis.com/~boris/tmp/odb/libodb-mysql-2.0.1.tar.bz2 Let me know if it works for you and I will make an official bugfix. I am also going to file a bug report with Fedora to see if we can add this symbol to the export list. And thanks for reporting this! Boris From philly.dilly at gmail.com Sun Jun 10 21:54:21 2012 From: philly.dilly at gmail.com (philly.dilly@gmail.com) Date: Mon Jun 11 05:06:06 2012 Subject: [odb-users] SQLite and std::wstring In-Reply-To: Message-ID: <047d7b163439f59ab804c228a07e@google.com> Hi Boris, I was indeed planning on using utf8 in database since utf8 is rarely bigger than utf16 but often smaller. Considering database are often IO bound rather than cpu bound, it seems like the conversion is a small price to pay for potentially better throughput. I played around a little bit trying to implement specialization of class odb::sqlite::value_traits however it seems like the odb compiler doesn't like that I include . Furthermore, this step seems superfluous since sqlite natively supports utf16. When I have some more time, I might play around with adding the value text16 to enum odb::sqlite::bind::buffer_type which will use the native sqlite utf16 api since it seems to me like the logical way to add utf16 support. That being said, I clearly don't fully understand odb yet so I may be going in the completely wrong direction :D Cheers, Phil On , Boris Kolpackov wrote: > Hi Phil, > philly.dilly@gmail.com philly.dilly@gmail.com> writes: > > Although utf8 is generally a more compact encoding, in my case I will be > > using wstring since my application deals with a lot of non latin > > languages and processing utf16 is a lot easier. > Yes, I understand that you want to use wstring/UTF-16 in the application. > What I was curious about is which encoding you were planning to use in > the database (you have a choice of UTF-8 or UTF-16, and it seems UTF-8 is > generally recommended since it results in a more compact database and thus > better performance). > > I tried mapping std::wstring to TEXT with pragmas but then I got some > > compilation errors about wrong number of arguments or something. > Yes, since there is not built-in support for std::wstring (yet), you will > need to implement a value_traits specialization for it which will need to > convert to/from UTF-8, since that's the only "image" currently supported > by ODB for SQLite TEXT. The 'mapping' example has more information on how > to do this. > Boris From boris at codesynthesis.com Mon Jun 11 05:24:05 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Mon Jun 11 05:33:30 2012 Subject: [odb-users] SQLite and std::wstring In-Reply-To: <047d7b163439f59ab804c228a07e@google.com> References: <047d7b163439f59ab804c228a07e@google.com> Message-ID: Hi Phil, philly.dilly@gmail.com writes: > I played around a little bit trying to implement specialization of > class odb::sqlite::value_traits however it > seems like the odb compiler doesn't like that I include . AFAIK, std::codecvt is defined in , not . Also note that by default the ODB compiler compiles in the C++98 mode so the new UTF-8/UTF-16 stuff won't be available. To switch to the C++11 mode you will need to pass '--std c++11' option. > Furthermore, this step seems superfluous since sqlite natively > supports utf16. When I have some more time, I might play around with > adding the value text16 to enum odb::sqlite::bind::buffer_type which > will use the native sqlite utf16 api since it seems to me like the > logical way to add utf16 support. Right, that's exactly what we are planning to do. However, there are some architectural issues that we first need to resolve to be able to support such "dual images" (i.e., TEXT can be mapped to a UTF-8 or UTF-16 image). Also, once we have this worked out, it will also be fairly straightforward to add support for streaming BLOB interface for SQLite. Boris From boris at codesynthesis.com Tue Jun 12 01:47:20 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Tue Jun 12 01:47:25 2012 Subject: [odb-users] SQLite and std::wstring In-Reply-To: <047d7b15faf10c6a8b04c232e0a8@google.com> References: <047d7b15faf10c6a8b04c232e0a8@google.com> Message-ID: Hi Phil, In the future please keep your replies CC'ed to the odb-users mailing list as discussed in the posting guidelines: http://www.codesynthesis.com/support/posting-guidelines.xhtml philly.dilly@gmail.com writes: > Unfortunately, to the best of my knowledge codecvt_utf8_utf16 is in > :( Ok, I did some more digging, and it appears codecvt_utf8_utf16 is an VC10 non-standard extension that is indeed defined in . The C++11 name for this functionality is std::codecvt that is defined in (and is probably not supported by VC10). You could provide two separate implementations based on the ODB_COMPILER macro, which is defined when the header is compiled by the ODB compiler. However, I don't think you need to include the traits implementation (and thus ) in your header file that defines persistent classes. If you look at the 'mapping' example, you will notice that it only include the traits.hxx file in the generated code (using the --hxx-prologue option; see the accompanying README file for details). > I was already able to to define a new binding for text16 in > libodb-sqlite but then I ran into the architectural issue in the compiler > you mentioned. Guess I'll have to wait until the next version of odb :) Note that you still should be able to provide the std::wstring mapping by doing UTF-16 to UTF-8 conversion yourself. Seeing that you are using UTF-8-encoded database, this conversion will have to happen either way. Right now you will have to do it yourself. Once we support UTF-16 image for TEXT, SQLite will be doing the conversion. The only time the latter approach is a clear winner is when you have a UTF-16-encoded database. Boris From gforster at liquidcapital.com Tue Jun 12 03:18:11 2012 From: gforster at liquidcapital.com (Giles Forster) Date: Tue Jun 12 05:28:23 2012 Subject: [odb-users] using special db field types Message-ID: <53DED215D1A2F14BB93C00E9B0EA33C2041A24@lcldn-mail12.Liquid-Capital.liquidcap.com> While evaluating ODB for usage in an existing application, one of the types of data structure we repeatedly have in the db is relating to series of x,y data points. I'm looking for a way to exploit the fact that I don't have to fully normalise all my data in tables for a relational DB by using some of the more specialised types available in some DB's like Postgres. The fully normalised format is not particular useful in our use cases and at the same time introduces all the relationships that need to be maintained in tables that would end up existing to maintain a single column of data. Now I see with the ODB support for Postgres you have the following types: http://www.codesynthesis.com/products/odb/doc/manual.xhtml#15 However, Postgres and other db's support more specialist types which use as compact container fields on a given record, rather than joining to a table to store arrays of that type. i.e they extend arrays beyond just varchar's but bring about something similar with other intrinsic types like arrays of doubles or ints. In particular 'array's, the following is possible with PostGres and others. CREATE TABLE series ( name text, x_data double[], y_data double[] ); As you can see this is quite a compact structure compared to the default schema that would be created by ODB if I used a vector for x and y in the source C++ class where it would create 3 tables, of which two would be indexed back to the first with a join to the series table. I have yet to extend this sample further and include the surface object that owns the series objects delineated by time which bring in a 4th table. Is there a way to make use of a db's SQL 'ARRAY' field type? Separately, this can be simplified further by either using a multi-dimensional array as so: CREATE TABLE series ( name text, xy_data double[][] ); And better yet, just using the in-built tuple type called a 'point' CREATE TABLE series ( name text, xy_data point[] ); All of this is valid for Psotgres, and similar things can be done with other RDBMS. I saw there was a way to over-ride the default types assigned, but I assume these need to be for types ODB knows about? As per: http://www.codesynthesis.com/products/odb/doc/manual.xhtml#12.4.3 Is anything like I describe possible through the pragmas with ODB to exploit these features of the db's being targeted? Thanks, Giles Liquid Capital Securities Limited ("LCS") and Liquid Capital Trading LLP are registered and located in England & Wales and authorised and regulated by the Financial Services Authority in the United Kingdom. LCS is also registered with the U.S. National Futures Association ("NFA") as an Exempt Foreign Broker. Liquid Capital Management LLP and Liquid Capital Markets Limited are registered and located in England & Wales. For more information about these entities, please contact +44 207 429 0700. Please click this link for terms relating to all email correspondence. From boris at codesynthesis.com Tue Jun 12 12:00:56 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Tue Jun 12 12:01:00 2012 Subject: [odb-users] using special db field types In-Reply-To: <53DED215D1A2F14BB93C00E9B0EA33C2041A24@lcldn-mail12.Liquid-Capital.liquidcap.com> References: <53DED215D1A2F14BB93C00E9B0EA33C2041A24@lcldn-mail12.Liquid-Capital.liquidcap.com> Message-ID: Hi Giles, Giles Forster writes: > As you can see this is quite a compact structure compared to the default > schema that would be created by ODB if I used a vector for x and y > in the source C++ class where it would create 3 tables, of which two would > be indexed back to the first with a join to the series table. I agree that using PostgreSQL array support results in a more concise schema. Whether it results in better performance, I don't know; it probably depends on the number of elements in the arrays as well as the access patterns of the application. Also, with the separate table approach, the more natural way to arrange things would be to define a composite value instead of having two parallel arrays (this is similar to your use of the PostgreSQL point type): #pragma db value struct point { double x; double y; }; #pragma db object class series { ... std::vector data; }; This will also result in two tables instead of three. > Is there a way to make use of a db's SQL 'ARRAY' field type? Not at the moment. I did some reading on this feature and in the case of PostgreSQL, to support arrays we would need to parse their undocumented binary format (ODB uses binary format for passing parameters and receiving results, for efficiency). This format appears to be quite complex (see this discussion[1], for example) and I am not sure we want to go this route at this stage. We would have to implement array support for every built-in type and then there will still be a question about other/user-defined types, like point. However, there seems to be another way to add support for arrays. It is possible to interface with PostgreSQL arrays using their string representations (see, for example, array_to_string() and string_to_array() functions). This approach can also be used to handle other extended data types, such as point. In fact, some time ago we already had a request for this functionality, except in that case it was about the GEOMETRY extension. Here is my earlier reply that outlined this idea in a bit more detail: http://www.codesynthesis.com/pipermail/odb-users/2011-September/000312.html The way I currently see this working is as follows: There would be a pragma that would allow one to introduce additional database types as well as information on how they can be mapped to one of the known built-in types. Essentially, the ODB compiler will need to know three things about the new type: 1. Its "interface type" (i.e., the built-in type that will be used to send/receive the data). 2. The "to" conversion expression that will be used in the SELECT statements. 3. The "from" conversion expression that will be used in the UPDATE and INSERT statements. Also having the type name specified as a regex pattern and the above three pieces of information as regex substitutions sounds like it will give some nice flexibility to the mechanism. So, for the PostgreSQL one-dimension array of double, the pragma could look like this: #pragma db type("DOUBLE PRECISION\[[^[]\]") \ as("TEXT") \ to("string_to_array(?, ',', 'NULL')") \ from("array_to_string(?, ',', 'NULL')") After that, one would need to also provide a value_traits specialization, say, for std::vector that would be able to parse/serialize the string representation of the array of doubles. The good news is that, AFAICS, this should be fairly straightforward to implement in the ODB compiler. So if you would like to use this feature, let me know, and I will implement it and have something for you to try. [1] http://stackoverflow.com/questions/4016412/postgresqls-libpq-encoding-for-binary-transport-of-array-data Boris From doitsjz at 163.com Tue Jun 12 11:33:41 2012 From: doitsjz at 163.com (doitsjz) Date: Tue Jun 12 12:02:38 2012 Subject: [odb-users] odb-hello compile problem,help me Message-ID: <17132e9a.24a9a.137e15435d7.Coremail.doitsjz@163.com> hi, i 'm trying to use odb for learning. but when i compile the dir of odb-examples-2.0.0\hello, occur a error, as below, odb and the dll(odb-d.dll, odb-sqlite-d.dll,sqlite3.dll) in the same dir . and odb.exe in the path. 1>------ Build started: Project: hello-sqlite-vc10, Configuration: Debug Win32 ------ 1>Build started 2012-6-12 23:07:01. 1>InitializeBuildStatus: 1> Touching "Debug\hello-sqlite-vc10.unsuccessfulbuild". 1>CustomBuild: 1> odb person.hxx 1>odb.exe : error : ??????????(system can't find the path)? 1> 1> --------------------------- when i in cmd window, enter "odb.exe --database sqlite --generate-query --generate-schema person.hxx" ,occur the same error. why? From boris at codesynthesis.com Tue Jun 12 12:13:18 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Tue Jun 12 12:13:23 2012 Subject: [odb-users] odb-hello compile problem,help me In-Reply-To: <17132e9a.24a9a.137e15435d7.Coremail.doitsjz@163.com> References: <17132e9a.24a9a.137e15435d7.Coremail.doitsjz@163.com> Message-ID: Hi, doitsjz writes: > and odb.exe in the path. > > 1>odb.exe : error : system can't find the path > > when i in cmd window, enter "odb.exe --database sqlite --generate-query > --generate-schema person.hxx" ,occur the same error. My guess would be that you copied the odb.exe file to some other directory. This is not supported, as stated in the README file: "Note also that while you can move the ODB compiler directory around, you cannot move the individual sub-directories or files inside it. For example, copying the ODB compiler executable to C:\Windows will not work." Try the following steps: 1. Unpack the odb-2.0.0-i686-windows.zip, say, to C:\ 2. In the command prompt, run these commands: C: cd odb-2.0.0-i686-windows bin\odb.exe --database sqlite --generate-query --generate-schema path\to\person.hxx If that works, then add C:\odb-2.0.0-i686-windows\bin path to the PATH environment variable, as instructed in the README file. Boris From Davide.Anastasia at qualitycapital.com Wed Jun 13 11:48:53 2012 From: Davide.Anastasia at qualitycapital.com (Davide Anastasia) Date: Wed Jun 13 11:49:13 2012 Subject: [odb-users] one-to-many relationship with property(ies) Message-ID: Hi, I'm back! I'm trying to build an ODB layer over an already existing database. I have a one-to-many relationship between table A and table B, with a middle table containing (primary_key(A), primary_key(B), int). In practice, I have a relationship with a weight between A and B. I'm not sure how I can model this. I have tried something like (inside class A): #pragma db unordered value_not_null table("mapping_a_b") \ key_column("id_B") \ id_column("id_A") \ value_column("weight") \ key_type("VARCHAR(8)") value_type("INT(11)") std::map< ::odb::boost::lazy_shared_ptr , int > m_mapping; Unfortunately, I get a lot of errors from the compiler. If I had "id_type" as well, ODB compiler crashes. Any suggestion? Thanks, Davide Anastasia Analyst, Research & Development Quality Capital Management Ltd. QCM House * Horizon Business Village No. 1 Brooklands Road Weybridge * Surrey KT13 0TJ United Kingdom Tel: +44 (0) 1932 334 400 Fax: +44 (0) 1932 334 415 Email: Davide.Anastasia@QualityCapital.com www.qualitycapital.com ________________________________ This email and any attachments are confidential and intended solely for the use of the individual(s) to whom it is addressed. Any views or opinions presented are solely those of the author and do not necessarily represent those of Quality Capital Management Ltd. If you are not the intended recipient, be advised that you have received this email in error and that any use, dissemination, printing, forwarding or copying of this email is strictly prohibited. Please contact the sender if you have received this email in error. You should also be aware that emails are susceptible to interference and you should not assume that the contents of this email originated from the sender above or that they have been accurately reproduced in their original form. Quality Capital Management Ltd is authorised and regulated by the Financial Services Authority in the UK and is a member of the National Futures Association in the US. ________________________________ From philly.dilly at gmail.com Wed Jun 13 08:03:51 2012 From: philly.dilly at gmail.com (Philippe Cadieux-Pelletier) Date: Thu Jun 14 03:19:56 2012 Subject: [odb-users] Bug: Schema catalog registration not initialized in Visual Studio 2012 RC Message-ID: Hi Boris, Just a heads up that I found a bug where it appears the static schema_catalog_entry variables do not get initialized (and therefore registered) prior to calling schema_catalog::create_schema. The current workaround I have is to not compile the generated cxx but rather include it in the same cpp file that calls schema_catalog::create_schema so that they are in the same compilation unit. I'm not sure if the VC11 compiler now lazily initializes global variables on a per compilation unit basis or if it's the linker that stripped those globals since they aren't unreferenced. My guess is that declaring the variables in the generated hxx file would fix this. Cheers, Phil From boris at codesynthesis.com Thu Jun 14 03:37:32 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Thu Jun 14 03:37:32 2012 Subject: [odb-users] one-to-many relationship with property(ies) In-Reply-To: References: Message-ID: Hi Davide, Davide Anastasia writes: > I'm trying to build an ODB layer over an already existing database. I > have a one-to-many relationship between table A and table B, with a > middle table containing (primary_key(A), primary_key(B), int). In > practice, I have a relationship with a weight between A and B. I'm not > sure how I can model this. I think having a composite value that contains the pointer plus the extra data and then using a vector of those is the most natural way. Here is an example: #pragma db object class employee { public: #pragma db id auto unsigned long id_; }; #pragma db value struct employee_info { #pragma db not_null employee* ptr; int data; }; #pragma db object class employer { public: #pragma db id auto unsigned long id_; #pragma db unordered std::vector employees; }; With this model the auto-generated schema (for PostgreSQL) looks along these lines: CREATE TABLE employee ( id BIGSERIAL NOT NULL PRIMARY KEY); CREATE TABLE employer ( id BIGSERIAL NOT NULL PRIMARY KEY); CREATE TABLE employer_employees ( object_id BIGINT NOT NULL, value_ptr BIGINT NOT NULL, value_data INTEGER NOT NULL); As a general tip, when trying to use an existing schema, it can be helpful to auto-generate a "test schema" from the object model. Once they are similar enough, then you know you have achieved the correct mapping. Boris From Davide.Anastasia at qualitycapital.com Thu Jun 14 05:23:40 2012 From: Davide.Anastasia at qualitycapital.com (Davide Anastasia) Date: Thu Jun 14 05:23:49 2012 Subject: [odb-users] one-to-many relationship with property(ies) In-Reply-To: References: Message-ID: It works brilliantly, thanks a lot! -----Original Message----- From: Boris Kolpackov [mailto:boris@codesynthesis.com] Sent: 14 June 2012 08:38 To: Davide Anastasia Cc: odb-users@codesynthesis.com Subject: Re: [odb-users] one-to-many relationship with property(ies) Hi Davide, Davide Anastasia writes: > I'm trying to build an ODB layer over an already existing database. I > have a one-to-many relationship between table A and table B, with a > middle table containing (primary_key(A), primary_key(B), int). In > practice, I have a relationship with a weight between A and B. I'm not > sure how I can model this. I think having a composite value that contains the pointer plus the extra data and then using a vector of those is the most natural way. Here is an example: #pragma db object class employee { public: #pragma db id auto unsigned long id_; }; #pragma db value struct employee_info { #pragma db not_null employee* ptr; int data; }; #pragma db object class employer { public: #pragma db id auto unsigned long id_; #pragma db unordered std::vector employees; }; With this model the auto-generated schema (for PostgreSQL) looks along these lines: CREATE TABLE employee ( id BIGSERIAL NOT NULL PRIMARY KEY); CREATE TABLE employer ( id BIGSERIAL NOT NULL PRIMARY KEY); CREATE TABLE employer_employees ( object_id BIGINT NOT NULL, value_ptr BIGINT NOT NULL, value_data INTEGER NOT NULL); As a general tip, when trying to use an existing schema, it can be helpful to auto-generate a "test schema" from the object model. Once they are similar enough, then you know you have achieved the correct mapping. Boris From boris at codesynthesis.com Thu Jun 14 09:02:40 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Thu Jun 14 09:02:39 2012 Subject: [odb-users] Bug: Schema catalog registration not initialized in Visual Studio 2012 RC In-Reply-To: References: Message-ID: Hi Philippe, Philippe Cadieux-Pelletier writes: > Just a heads up that I found a bug where it appears the static > schema_catalog_entry variables do not get initialized (and therefore > registered) prior to calling schema_catalog::create_schema. The current > workaround I have is to not compile the generated cxx but rather include it > in the same cpp file that calls schema_catalog::create_schema so that they > are in the same compilation unit. This is very strange. Are you generating the schema creation code into a separate file (i.e., using the '--schema-format separate' option) or is it in the same source file as the rest of the generated code? The only situation that I know can lead to this behavior is if you generate the -schema.cxx file, package its object code into a static library (.lib or .a), and then link this library into your executable. In this case, because your application doesn't link to any of the symbols from the -schema.cxx file directly, linker will not add it to the executable. > I'm not sure if the VC11 compiler now lazily initializes global > variables on a per compilation unit basis or if it's the linker > that stripped those globals since they aren't unreferenced. The lazy initialization would not be allowed by the standard since it has side-effects. Also the fact that including the generated source file into another source file fixes the problem suggests that something else is going on. BTW, have you tried the same code with VC10? Boris From philly.dilly at gmail.com Thu Jun 14 10:29:09 2012 From: philly.dilly at gmail.com (Philippe Cadieux-Pelletier) Date: Thu Jun 14 13:19:58 2012 Subject: [odb-users] Bug: Schema catalog registration not initialized in Visual Studio 2012 RC In-Reply-To: References: Message-ID: Hi Boris, The code is generated in the same file. The generated code and the code that uses it is in the same project put it is a lib. Haven't tried it on vc10 since I don't have it installed on this machine. On Thu, Jun 14, 2012 at 10:02 PM, Boris Kolpackov wrote: > Hi Philippe, > > Philippe Cadieux-Pelletier writes: > > > Just a heads up that I found a bug where it appears the static > > schema_catalog_entry variables do not get initialized (and therefore > > registered) prior to calling schema_catalog::create_schema. The current > > workaround I have is to not compile the generated cxx but rather include > it > > in the same cpp file that calls schema_catalog::create_schema so that > they > > are in the same compilation unit. > > This is very strange. Are you generating the schema creation code into > a separate file (i.e., using the '--schema-format separate' option) or > is it in the same source file as the rest of the generated code? > > The only situation that I know can lead to this behavior is if you > generate the -schema.cxx file, package its object code into a static > library (.lib or .a), and then link this library into your executable. > In this case, because your application doesn't link to any of the > symbols from the -schema.cxx file directly, linker will not add it > to the executable. > > > I'm not sure if the VC11 compiler now lazily initializes global > > variables on a per compilation unit basis or if it's the linker > > that stripped those globals since they aren't unreferenced. > > The lazy initialization would not be allowed by the standard since > it has side-effects. Also the fact that including the generated source > file into another source file fixes the problem suggests that something > else is going on. BTW, have you tried the same code with VC10? > > Boris > From boris at codesynthesis.com Fri Jun 15 06:42:41 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Fri Jun 15 06:38:50 2012 Subject: [odb-users] Bug: Schema catalog registration not initialized in Visual Studio 2012 RC In-Reply-To: References: Message-ID: Hi Philippe, Philippe Cadieux-Pelletier writes: > The code is generated in the same file. The generated code and the code > that uses it is in the same project put it is a lib. Ok, I am pretty sure this is the "linking only what's referenced" .lib behavior. If none of the object files that end up in the executable reference any symbols from the object file with the registration code, then it won't be linked to the executable. So, for example, if all your executable does is create the database schema (and not call any database operations on persistent classes from this file), then the registration code won't end up in the executable. GNU linker has the --whole-archive option which allows you to force it to add all the files from the static library: ld ... --whole-archive libgencode.a --no-whole-archive ... But there doesn't seem to be a similar option in Microsoft linker. Instead, it is recommended that you use the /INCLUDE: option or #pragma comment(linker, "/INCLUDE:") to force the linker to include the object file that defines this symbol. Of course, if you try to use one of the C++ symbols from the generated code, then you will have to provide it in a mangled form, which can be a pain. Instead, you could add a phony extern "C" symbol to the generated source file with the --cxx-epilogue option. Then you would use it in the /INCLUDE option: odb ... --cxx-epilogue 'extern "C" int person_phony_symbol = 0;' person.hxx And then in your source file that uses the generated code, you can add: #pragma comment(linker, "/INCLUDE:person_phony_symbol") Boris From boris at codesynthesis.com Mon Jun 18 04:04:44 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Mon Jun 18 04:00:28 2012 Subject: [odb-users] ODB runtimes 2.0.1 bugfix released Message-ID: Hi, New bugfix releases for the common ODB runtime library (libodb) and database-specific ODB runtime libraries (libodb-) are now available. The new common runtime release works around a VC++ compilation bug resulting in ambiguous name lookup in polymorphic-map.hxx:44 for some databases. The new database-specific runtime releases fix a compilation bug in polymorphic class hierarchies that are split over multiple source files. For more information on this issue, refer to the following mailing list thread: http://www.codesynthesis.com/pipermail/odb-users/2012-May/000576.html In addition the MySQL runtime release fixes a build problem on Fedora 15 and later. For more information on this issue, refer to the following mailing list thread: http://www.codesynthesis.com/pipermail/odb-users/2012-June/000599.html Note also that all the fixes are for compile-time/build related issues which means that you don't need to upgrade if everything compiles fine for you. You can download the new packages from the ODB download page: http://www.codesynthesis.com/products/odb/download.xhtml SHA1 checksums for the files in this release are as follows: fac1da357db6aa3ef605358e15fe0a0735b80f72 libodb-2.0.1.tar.bz2 94ca678c17d84b1f31ce7ac3c8c0246d94b81a61 libodb-2.0.1.tar.gz e7a7f02a134ef92388532f8c7b1932e507035db7 libodb-2.0.1.zip 1e32488b50e5dc3aa9d807e0f608e67896aadaf9 libodb-mssql-2.0.1.tar.bz2 59ceb66378bc2f6c590832af8391ff0929d60963 libodb-mssql-2.0.1.tar.gz bf17333233349f15b3ce1be3dc347b1fe2cb8782 libodb-mssql-2.0.1.zip e128cd1ff5880e5746ea3ca2c61189e28cc32670 libodb-mysql-2.0.1.tar.bz2 4a9410f49d66a68a8ab02f8abc401979bad2ef41 libodb-mysql-2.0.1.tar.gz f7cb6aafb4c1efb0f57d6bbefbf653a8381f9661 libodb-mysql-2.0.1.zip 97c43c025a89b18a7014e704bd896c10db008ea4 libodb-oracle-2.0.1.tar.bz2 093f7a3e5b2644c1eaeddc01509f83f51f0b6923 libodb-oracle-2.0.1.tar.gz bb671b4ab51d3ffc148ebe7c1740f20a821b06e6 libodb-oracle-2.0.1.zip 0a69cc90394c814a8c1773cde952f079b5bf87af libodb-pgsql-2.0.1.tar.bz2 c17f8c68e94360b6b438ac7db7ec9945570224b6 libodb-pgsql-2.0.1.tar.gz 245baa458d38e3adf4c5ad7df0f26544c61eb231 libodb-pgsql-2.0.1.zip 4fec286798a8d627602a56fedd404ba1ae8dcb73 libodb-sqlite-2.0.1.tar.bz2 f64d03585139d823bb7bc183dfd8b5865b5b641e libodb-sqlite-2.0.1.tar.gz a2d8661127adfc8da54cbf96af90515b4c401c87 libodb-sqlite-2.0.1.zip Boris From boris at codesynthesis.com Mon Jun 18 04:24:26 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Mon Jun 18 04:20:07 2012 Subject: [odb-users] libodb-mysql.so Undefined Reference to 'THR_KEY_msys' In-Reply-To: References: Message-ID: Hi, To close this thread, I've tested the fix on Fedora 17 and it is now release as the 2.0.1 bugfix: http://www.codesynthesis.com/pipermail/odb-announcements/2012/000015.html Boris From hurdad at gmail.com Mon Jun 18 14:53:03 2012 From: hurdad at gmail.com (Alex Hurd) Date: Tue Jun 19 01:58:46 2012 Subject: [odb-users] Generating model.hxx from pre-existing schema Message-ID: All, Has anyone built a script to generate a model.hxx file from a pre existing database schema? Basically the reverse of the odb compiler (model.hxx to model.sql). Thanks, -alex From boris at codesynthesis.com Tue Jun 19 02:18:05 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Tue Jun 19 02:13:38 2012 Subject: [odb-users] Generating model.hxx from pre-existing schema In-Reply-To: References: Message-ID: Hi Alex, Alex Hurd writes: > Has anyone built a script to generate a model.hxx file from a pre existing > database schema? Basically the reverse of the odb compiler (model.hxx to > model.sql). We have this on our TODO list since quite a few people seem to be interested in this feature. Of course the ODB compiler won't be able to do a stellar job in all the cases since there could be multiple ways to map SQL tables to C++. For example, two tables with a relationship between them can be mapped to two persistent objects or it can be a persistent object and a container. So we might also have to provide a way to give ODB some hints about how to map things. Also, we haven't decided what will be the input format for this feature. The natural way would be to use an SQL file with the DDL statements but in this case we will have to parse all the different SQL dialects. The other option is to query the database itself using the API. While this sidesteps the whole SQL parsing issue, it has its own drawbacks, such as dependency on all the database runtimes, as well as the need to be able to access the database during compilation. Which approach do you think will work better in your case? Boris From yo at miguelrevilla.com Wed Jun 27 07:49:19 2012 From: yo at miguelrevilla.com (=?UTF-8?Q?Miguel_Revilla_Rodr=C3=ADguez?=) Date: Wed Jun 27 07:49:28 2012 Subject: [odb-users] Is this possible? Message-ID: Now, it's probably not possible or, at least, my C++ skills don't get that far. Imagine the situation: I have a polymorphic class called 'node': #pragma db object polymorphic class node { ... } ; Now, node is inherited by several other classes (user, group, etc). And one of those classes (group) is a node that defines a group of nodes. I want to set a many-to-many relationship where a group contains a number of nodes and a node belongs to a number of groups. This one is obvious in the group definition: #pragma db value_not_null std::vector > nodes_ ; But this one is tricky in the node definition: #pragma db value_not_null inverse(nodes_) std::vector > groups_ ; Because, if I include "group.h" (that inherits from node, remember that) it obviously crashes as node is not yet defined. I could, of course, just declare an empty class group and implement later, but the odb compiler wants their kids to be defined and #pragma db object class group {} ; instead of #include "group.h" is, obviously, not working. Any chances of solving this? Thanks guys From boris at codesynthesis.com Wed Jun 27 09:45:56 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Wed Jun 27 09:40:05 2012 Subject: [odb-users] Is this possible? In-Reply-To: References: Message-ID: Hi Miguel, Miguel Revilla Rodr?guez writes: > I have a polymorphic class called 'node': > > #pragma db object polymorphic > class node { ... } ; > > Now, node is inherited by several other classes (user, group, etc). > And one of those classes (group) is a node that defines a group of > nodes. I want to set a many-to-many relationship where a group > contains a number of nodes and a node belongs to a number of groups. This is pretty easy to arrange if both node and group are in the same header file (generally a good idea when you have such a tight integration between the two). The idea is to forward-declare one of the classes: class group; class node { #pragma db value_not_null inverse(nodes_) std::vector > groups_ ; }; class group: public node { #pragma db value_not_null std::vector > nodes_ ; }; If you want to place node and group in separate headers, things are a bit trickier, but the idea is pretty much the same. You most likely need to include the definition of group into node in any case (e.g., for destructors to work, etc). In this case simply #include group.h after the node definition: class group; class node { #pragma db value_not_null inverse(nodes_) std::vector > groups_ ; }; #include "group.h" If your application doesn't need group.h in node.h (but the ODB compiler does), then you can make the include conditional: #ifdef ODB_COMPILER # include "group.h" #endif Boris From yo at miguelrevilla.com Wed Jun 27 10:10:45 2012 From: yo at miguelrevilla.com (=?UTF-8?Q?Miguel_Revilla_Rodr=C3=ADguez?=) Date: Wed Jun 27 10:10:54 2012 Subject: [odb-users] Is this possible? In-Reply-To: References: Message-ID: Now that looks fixed and odb compiler doesn't complain, but I'm getting this on compiling the resulting code. I'm using G++ 4.7.1 with c++11 BTW. [ 4%] Building CXX object CMakeFiles/yajpws.dir/odbClasses/node-odb.cpp.o In file included from /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.h:25:0, from /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:12: /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:105:13: error: 'discriminator_type' in 'odb::access::object_traits::root_traits {aka class odb::access::object_traits}' does not name a type /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:110:13: error: 'id_type' in 'class odb::access::object_traits' does not name a type /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:111:13: error: 'id_image_type' in 'class odb::access::object_traits' does not name a type /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:120:7: error: 'image_type' in 'class odb::access::object_traits' does not name a type /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:240:12: error: 'id_type' does not name a type /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:254:25: error: 'id_image_type' has not been declared /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:263:11: error: 'id_image_type' has not been declared /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:263:33: error: 'id_type' does not name a type /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:263:40: error: ISO C++ forbids declaration of 'parameter' with no type [-fpermissive] /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:272:37: error: incomplete type 'odb::access::object_traits::root_traits {aka odb::access::object_traits}' used in nested name specifier /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:272:37: error: incomplete type 'odb::access::object_traits::root_traits {aka odb::access::object_traits}' used in nested name specifier /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:272:62: error: template argument 1 is invalid /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:316:28: error: 'id_type' does not name a type /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:316:35: error: ISO C++ forbids declaration of 'parameter' with no type [-fpermissive] /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:319:28: error: 'id_type' does not name a type /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:319:35: error: ISO C++ forbids declaration of 'parameter' with no type [-fpermissive] /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:328:29: error: 'id_type' does not name a type /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:328:36: error: ISO C++ forbids declaration of 'parameter' with no type [-fpermissive] /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:355:36: error: 'id_type' does not name a type /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:355:43: error: ISO C++ forbids declaration of 'parameter' with no type [-fpermissive] /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h: In instantiation of 'struct odb::query_columns >': /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:371:3: required from here /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:61:10: error: invalid use of incomplete type 'struct odb::query_columns >' In file included from /usr/include/odb/database.hxx:15:0, from /usr/include/odb/lazy-ptr-impl.txx:5, from /usr/include/odb/lazy-ptr-impl.hxx:176, from /usr/include/odb/lazy-ptr.hxx:15, from /home/mine/git/bettercodes/yajp-backend/odbClasses/node.h:7, from /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.h:21, from /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:12: /usr/include/odb/query.hxx:31:10: error: declaration of 'struct odb::query_columns >' In file included from /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:380:0, from /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.h:25, from /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:12: /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.i:18:3: error: 'id_type' in 'class odb::access::object_traits' does not name a type /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.i:27:25: error: 'id_image_type' has not been declared /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.i: In static member function 'static void odb::access::object_traits::bind(odb::pgsql::bind*, int&)': /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.i:29:5: error: incomplete type 'odb::access::object_traits' used in nested name specifier /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.i: At global scope: /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.i:34:9: error: variable or field 'init' declared void /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.i:34:9: error: 'id_image_type' was not declared in this scope /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.i:34:24: error: 'i' was not declared in this scope /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.i:34:27: error: expected primary-expression before 'const' /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.i: In static member function 'static bool odb::access::object_traits::check_version(const size_t*, const odb::access::object_traits::image_type&)': /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.i:45:19: error: 'const struct odb::access::object_traits::image_type' has no member named 'base' /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.i: In static member function 'static void odb::access::object_traits::update_version(std::size_t*, const odb::access::object_traits::image_type&, odb::pgsql::binding*)': /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.i:53:16: error: 'const struct odb::access::object_traits::image_type' has no member named 'base' /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp: In static member function 'static void odb::access::object_traits::groups_traits::init(odb::access::object_traits::groups_traits::value_type&, const odb::access::object_traits::groups_traits::data_image_type&, odb::database*)': /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:556:9: error: 'id_type' is not a member of 'obj_traits {aka odb::access::object_traits}' /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:556:29: error: expected ';' before 'id' /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:558:13: error: 'id_type' is not a member of 'obj_traits {aka odb::access::object_traits}' /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:558:13: error: 'id_type' is not a member of 'obj_traits {aka odb::access::object_traits}' /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:559:30: error: template argument 1 is invalid /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:559:43: error: invalid type in declaration before '(' token /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:562:23: error: expression list treated as compound expression in initializer [-fpermissive] /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:562:23: error: left operand of comma operator cannot resolve address of overloaded function /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:564:46: error: no matching function for call to 'odb::lazy_weak_ptr::lazy_weak_ptr(odb::database&, )' /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:564:46: note: candidates are: In file included from /home/mine/git/bettercodes/yajp-backend/odbClasses/node.h:7:0, from /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.h:21, from /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:12: /usr/include/odb/lazy-ptr.hxx:598:24: note: template odb::lazy_weak_ptr::lazy_weak_ptr(odb::lazy_weak_ptr::database_type&, const std::weak_ptr<_Tp1>&) /usr/include/odb/lazy-ptr.hxx:598:24: note: template argument deduction/substitution failed: /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:564:46: note: mismatched types 'const std::weak_ptr<_Tp>' and 'odb::access::object_traits::id_type(const odb::access::object_traits::image_type&) {aka long unsigned int(const odb::access::object_traits::image_type&)}' /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:564:46: note: mismatched types 'const std::weak_ptr<_Tp>' and 'odb::access::object_traits::id_type(const object_type&) {aka long unsigned int(const node&)}' /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:564:46: note: could not resolve address from overloaded function 'odb::access::object_traits::id' In file included from /home/mine/git/bettercodes/yajp-backend/odbClasses/node.h:7:0, from /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.h:21, from /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:12: /usr/include/odb/lazy-ptr.hxx:597:24: note: template odb::lazy_weak_ptr::lazy_weak_ptr(odb::lazy_weak_ptr::database_type&, const std::shared_ptr<_Tp1>&) /usr/include/odb/lazy-ptr.hxx:597:24: note: template argument deduction/substitution failed: /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:564:46: note: mismatched types 'const std::shared_ptr<_Tp>' and 'odb::access::object_traits::id_type(const odb::access::object_traits::image_type&) {aka long unsigned int(const odb::access::object_traits::image_type&)}' /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:564:46: note: mismatched types 'const std::shared_ptr<_Tp>' and 'odb::access::object_traits::id_type(const object_type&) {aka long unsigned int(const node&)}' /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:564:46: note: could not resolve address from overloaded function 'odb::access::object_traits::id' In file included from /home/mine/git/bettercodes/yajp-backend/odbClasses/node.h:7:0, from /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.h:21, from /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:12: /usr/include/odb/lazy-ptr.hxx:596:25: note: template odb::lazy_weak_ptr::lazy_weak_ptr(odb::lazy_weak_ptr::database_type&, const ID&) /usr/include/odb/lazy-ptr.hxx:596:25: note: template argument deduction/substitution failed: /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:564:46: note: couldn't deduce template parameter 'ID' In file included from /home/mine/git/bettercodes/yajp-backend/odbClasses/node.h:7:0, from /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.h:21, from /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:12: /usr/include/odb/lazy-ptr.hxx:568:24: note: template odb::lazy_weak_ptr::lazy_weak_ptr(const std::shared_ptr<_Tp1>&) /usr/include/odb/lazy-ptr.hxx:568:24: note: template argument deduction/substitution failed: /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:564:46: note: 'odb::database' is not derived from 'const std::shared_ptr<_Tp>' In file included from /home/mine/git/bettercodes/yajp-backend/odbClasses/node.h:7:0, from /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.h:21, from /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:12: /usr/include/odb/lazy-ptr.hxx:567:24: note: template odb::lazy_weak_ptr::lazy_weak_ptr(const std::weak_ptr<_Tp1>&) /usr/include/odb/lazy-ptr.hxx:567:24: note: template argument deduction/substitution failed: /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:564:46: note: 'odb::database' is not derived from 'const std::weak_ptr<_Tp>' In file included from /home/mine/git/bettercodes/yajp-backend/odbClasses/node.h:7:0, from /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.h:21, from /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:12: /usr/include/odb/lazy-ptr.hxx:546:24: note: template odb::lazy_weak_ptr::lazy_weak_ptr(const odb::lazy_weak_ptr&) /usr/include/odb/lazy-ptr.hxx:546:24: note: template argument deduction/substitution failed: /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:564:46: note: 'odb::database' is not derived from 'const odb::lazy_weak_ptr' In file included from /usr/include/odb/lazy-ptr.hxx:643:0, from /home/mine/git/bettercodes/yajp-backend/odbClasses/node.h:7, from /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.h:21, from /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:12: /usr/include/odb/lazy-ptr.ixx:1393:10: note: odb::lazy_weak_ptr::lazy_weak_ptr(const odb::lazy_weak_ptr&) [with T = group; odb::lazy_weak_ptr = odb::lazy_weak_ptr] /usr/include/odb/lazy-ptr.ixx:1393:10: note: candidate expects 1 argument, 2 provided In file included from /home/mine/git/bettercodes/yajp-backend/odbClasses/node.h:7:0, from /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.h:21, from /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:12: /usr/include/odb/lazy-ptr.hxx:544:24: note: template odb::lazy_weak_ptr::lazy_weak_ptr(const odb::lazy_shared_ptr&) /usr/include/odb/lazy-ptr.hxx:544:24: note: template argument deduction/substitution failed: /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:564:46: note: 'odb::database' is not derived from 'const odb::lazy_shared_ptr' In file included from /usr/include/odb/lazy-ptr.hxx:643:0, from /home/mine/git/bettercodes/yajp-backend/odbClasses/node.h:7, from /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.h:21, from /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:12: /usr/include/odb/lazy-ptr.ixx:1384:10: note: odb::lazy_weak_ptr::lazy_weak_ptr() [with T = group] /usr/include/odb/lazy-ptr.ixx:1384:10: note: candidate expects 0 arguments, 2 provided make[2]: *** [CMakeFiles/yajpws.dir/odbClasses/node-odb.cpp.o] Error 1 make[1]: *** [CMakeFiles/yajpws.dir/all] Error 2 make: *** [all] Error 2 node.h: #ifndef NODE_H #define NODE_H #include #include #include #include #include "activity.h" class group ; #pragma db object polymorphic class node { public: node( const std::string &hash, int creationTime) : hash_(hash), creationTime_(creationTime) {} virtual ~node() = 0 ; protected: friend class odb::access ; node() {} #pragma db id auto unsigned long id_ ; std::string hash_ ; int creationTime_ ; #pragma db value_not_null std::vector > activities_ ; #pragma db value_not_null inverse(nodes_) std::vector > groups_ ; } ; #ifdef ODB_COMPILER #include "group.h" #endif #endif // NODE_H group.h: #ifndef GROUP_H #define GROUP_H #include #include #include "node.h" #pragma db object class group : public node { public: group( const std::string &hash, int creationTime, const std::string &title) : node(hash,creationTime), title_(title) {} private: friend class odb::access ; group() {} std::string title_ ; #pragma db value_not_null std::vector > nodes_ ; } ; #endif // GROUP_H 2012/6/27 Boris Kolpackov : > Hi Miguel, > > Miguel Revilla Rodr?guez writes: > >> I have a polymorphic class called 'node': >> >> #pragma db object polymorphic >> class node { ... } ; >> >> Now, node is inherited by several other classes (user, group, etc). >> And one of those classes (group) is a node that defines a group of >> nodes. I want to set a many-to-many relationship where a group >> contains a number of nodes and a node belongs to a number of groups. > > This is pretty easy to arrange if both node and group are in the same > header file (generally a good idea when you have such a tight integration > between the two). The idea is to forward-declare one of the classes: > > class group; > > class node > { > ?#pragma db value_not_null inverse(nodes_) > ?std::vector > groups_ ; > }; > > class group: public node > { > ?#pragma db value_not_null > ?std::vector > nodes_ ; > }; > > If you want to place node and group in separate headers, things are > a bit trickier, but the idea is pretty much the same. You most likely > need to include the definition of group into node in any case (e.g., > for destructors to work, etc). In this case simply #include group.h > after the node definition: > > class group; > > class node > { > ?#pragma db value_not_null inverse(nodes_) > ?std::vector > groups_ ; > }; > > #include "group.h" > > If your application doesn't need group.h in node.h (but the ODB compiler > does), then you can make the include conditional: > > #ifdef ODB_COMPILER > # ?include "group.h" > #endif > > Boris From yo at miguelrevilla.com Wed Jun 27 11:09:57 2012 From: yo at miguelrevilla.com (=?UTF-8?Q?Miguel_Revilla_Rodr=C3=ADguez?=) Date: Wed Jun 27 11:10:07 2012 Subject: [odb-users] Is this possible? In-Reply-To: References: Message-ID: If both class declarations are in the same file (your first advice) everything works fine. Using that as a workaround while we get a fix. Thanks! 2012/6/27 Miguel Revilla Rodr?guez : > Now that looks fixed and odb compiler doesn't complain, but I'm > getting this on compiling the resulting code. I'm using G++ 4.7.1 with > c++11 BTW. > > [ ?4%] Building CXX object CMakeFiles/yajpws.dir/odbClasses/node-odb.cpp.o > In file included from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.h:25:0, > ? ? ? ? ? ? ? ? from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:12: > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:105:13: > error: 'discriminator_type' in > 'odb::access::object_traits::root_traits {aka class > odb::access::object_traits}' does not name a type > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:110:13: > error: 'id_type' in 'class odb::access::object_traits' does not > name a type > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:111:13: > error: 'id_image_type' in 'class odb::access::object_traits' > does not name a type > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:120:7: > error: 'image_type' in 'class odb::access::object_traits' does > not name a type > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:240:12: > error: 'id_type' does not name a type > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:254:25: > error: 'id_image_type' has not been declared > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:263:11: > error: 'id_image_type' has not been declared > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:263:33: > error: 'id_type' does not name a type > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:263:40: > error: ISO C++ forbids declaration of 'parameter' with no type > [-fpermissive] > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:272:37: > error: incomplete type 'odb::access::object_traits::root_traits > {aka odb::access::object_traits}' used in nested name specifier > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:272:37: > error: incomplete type 'odb::access::object_traits::root_traits > {aka odb::access::object_traits}' used in nested name specifier > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:272:62: > error: template argument 1 is invalid > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:316:28: > error: 'id_type' does not name a type > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:316:35: > error: ISO C++ forbids declaration of 'parameter' with no type > [-fpermissive] > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:319:28: > error: 'id_type' does not name a type > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:319:35: > error: ISO C++ forbids declaration of 'parameter' with no type > [-fpermissive] > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:328:29: > error: 'id_type' does not name a type > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:328:36: > error: ISO C++ forbids declaration of 'parameter' with no type > [-fpermissive] > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:355:36: > error: 'id_type' does not name a type > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:355:43: > error: ISO C++ forbids declaration of 'parameter' with no type > [-fpermissive] > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h: In > instantiation of 'struct odb::query_columns odb::access::object_traits >': > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:371:3: > ?required from here > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:61:10: > error: invalid use of incomplete type 'struct odb::query_columns odb::access::object_traits >' > In file included from /usr/include/odb/database.hxx:15:0, > ? ? ? ? ? ? ? ? from /usr/include/odb/lazy-ptr-impl.txx:5, > ? ? ? ? ? ? ? ? from /usr/include/odb/lazy-ptr-impl.hxx:176, > ? ? ? ? ? ? ? ? from /usr/include/odb/lazy-ptr.hxx:15, > ? ? ? ? ? ? ? ? from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node.h:7, > ? ? ? ? ? ? ? ? from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.h:21, > ? ? ? ? ? ? ? ? from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:12: > /usr/include/odb/query.hxx:31:10: error: declaration of 'struct > odb::query_columns >' > In file included from > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.h:380:0, > ? ? ? ? ? ? ? ? from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.h:25, > ? ? ? ? ? ? ? ? from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:12: > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.i:18:3: > error: 'id_type' in 'class odb::access::object_traits' does not > name a type > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.i:27:25: > error: 'id_image_type' has not been declared > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.i: In > static member function 'static void > odb::access::object_traits::bind(odb::pgsql::bind*, int&)': > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.i:29:5: > error: incomplete type 'odb::access::object_traits' used in > nested name specifier > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.i: At global scope: > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.i:34:9: > error: variable or field 'init' declared void > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.i:34:9: > error: 'id_image_type' was not declared in this scope > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.i:34:24: > error: 'i' was not declared in this scope > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.i:34:27: > error: expected primary-expression before 'const' > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.i: In > static member function 'static bool > odb::access::object_traits::check_version(const size_t*, const > odb::access::object_traits::image_type&)': > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.i:45:19: > error: 'const struct odb::access::object_traits::image_type' > has no member named 'base' > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.i: In > static member function 'static void > odb::access::object_traits::update_version(std::size_t*, const > odb::access::object_traits::image_type&, > odb::pgsql::binding*)': > /home/mine/git/bettercodes/yajp-backend/odbClasses/group-odb.i:53:16: > error: 'const struct odb::access::object_traits::image_type' > has no member named 'base' > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp: In > static member function 'static void > odb::access::object_traits::groups_traits::init(odb::access::object_traits::groups_traits::value_type&, > const odb::access::object_traits::groups_traits::data_image_type&, > odb::database*)': > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:556:9: > error: 'id_type' is not a member of 'obj_traits {aka > odb::access::object_traits}' > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:556:29: > error: expected ';' before 'id' > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:558:13: > error: 'id_type' is not a member of 'obj_traits {aka > odb::access::object_traits}' > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:558:13: > error: 'id_type' is not a member of 'obj_traits {aka > odb::access::object_traits}' > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:559:30: > error: template argument 1 is invalid > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:559:43: > error: invalid type in declaration before '(' token > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:562:23: > error: expression list treated as compound expression in initializer > [-fpermissive] > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:562:23: > error: left operand of comma operator cannot resolve address of > overloaded function > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:564:46: > error: no matching function for call to > 'odb::lazy_weak_ptr::lazy_weak_ptr(odb::database&, overloaded function type>)' > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:564:46: > note: candidates are: > In file included from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node.h:7:0, > ? ? ? ? ? ? ? ? from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.h:21, > ? ? ? ? ? ? ? ? from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:12: > /usr/include/odb/lazy-ptr.hxx:598:24: note: template > odb::lazy_weak_ptr::lazy_weak_ptr(odb::lazy_weak_ptr::database_type&, > const std::weak_ptr<_Tp1>&) > /usr/include/odb/lazy-ptr.hxx:598:24: note: ? template argument > deduction/substitution failed: > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:564:46: > note: ? mismatched types 'const std::weak_ptr<_Tp>' and > 'odb::access::object_traits::id_type(const > odb::access::object_traits::image_type&) {aka long unsigned > int(const odb::access::object_traits::image_type&)}' > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:564:46: > note: ? mismatched types 'const std::weak_ptr<_Tp>' and > 'odb::access::object_traits::id_type(const object_type&) {aka > long unsigned int(const node&)}' > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:564:46: > note: ? could not resolve address from overloaded function > 'odb::access::object_traits::id' > In file included from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node.h:7:0, > ? ? ? ? ? ? ? ? from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.h:21, > ? ? ? ? ? ? ? ? from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:12: > /usr/include/odb/lazy-ptr.hxx:597:24: note: template > odb::lazy_weak_ptr::lazy_weak_ptr(odb::lazy_weak_ptr::database_type&, > const std::shared_ptr<_Tp1>&) > /usr/include/odb/lazy-ptr.hxx:597:24: note: ? template argument > deduction/substitution failed: > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:564:46: > note: ? mismatched types 'const std::shared_ptr<_Tp>' and > 'odb::access::object_traits::id_type(const > odb::access::object_traits::image_type&) {aka long unsigned > int(const odb::access::object_traits::image_type&)}' > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:564:46: > note: ? mismatched types 'const std::shared_ptr<_Tp>' and > 'odb::access::object_traits::id_type(const object_type&) {aka > long unsigned int(const node&)}' > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:564:46: > note: ? could not resolve address from overloaded function > 'odb::access::object_traits::id' > In file included from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node.h:7:0, > ? ? ? ? ? ? ? ? from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.h:21, > ? ? ? ? ? ? ? ? from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:12: > /usr/include/odb/lazy-ptr.hxx:596:25: note: template > odb::lazy_weak_ptr::lazy_weak_ptr(odb::lazy_weak_ptr::database_type&, > const ID&) > /usr/include/odb/lazy-ptr.hxx:596:25: note: ? template argument > deduction/substitution failed: > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:564:46: > note: ? couldn't deduce template parameter 'ID' > In file included from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node.h:7:0, > ? ? ? ? ? ? ? ? from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.h:21, > ? ? ? ? ? ? ? ? from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:12: > /usr/include/odb/lazy-ptr.hxx:568:24: note: template > odb::lazy_weak_ptr::lazy_weak_ptr(const std::shared_ptr<_Tp1>&) > /usr/include/odb/lazy-ptr.hxx:568:24: note: ? template argument > deduction/substitution failed: > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:564:46: > note: ? 'odb::database' is not derived from 'const > std::shared_ptr<_Tp>' > In file included from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node.h:7:0, > ? ? ? ? ? ? ? ? from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.h:21, > ? ? ? ? ? ? ? ? from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:12: > /usr/include/odb/lazy-ptr.hxx:567:24: note: template > odb::lazy_weak_ptr::lazy_weak_ptr(const std::weak_ptr<_Tp1>&) > /usr/include/odb/lazy-ptr.hxx:567:24: note: ? template argument > deduction/substitution failed: > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:564:46: > note: ? 'odb::database' is not derived from 'const std::weak_ptr<_Tp>' > In file included from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node.h:7:0, > ? ? ? ? ? ? ? ? from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.h:21, > ? ? ? ? ? ? ? ? from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:12: > /usr/include/odb/lazy-ptr.hxx:546:24: note: template > odb::lazy_weak_ptr::lazy_weak_ptr(const odb::lazy_weak_ptr&) > /usr/include/odb/lazy-ptr.hxx:546:24: note: ? template argument > deduction/substitution failed: > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:564:46: > note: ? 'odb::database' is not derived from 'const > odb::lazy_weak_ptr' > In file included from /usr/include/odb/lazy-ptr.hxx:643:0, > ? ? ? ? ? ? ? ? from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node.h:7, > ? ? ? ? ? ? ? ? from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.h:21, > ? ? ? ? ? ? ? ? from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:12: > /usr/include/odb/lazy-ptr.ixx:1393:10: note: > odb::lazy_weak_ptr::lazy_weak_ptr(const odb::lazy_weak_ptr&) > [with T = group; odb::lazy_weak_ptr = odb::lazy_weak_ptr] > /usr/include/odb/lazy-ptr.ixx:1393:10: note: ? candidate expects 1 > argument, 2 provided > In file included from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node.h:7:0, > ? ? ? ? ? ? ? ? from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.h:21, > ? ? ? ? ? ? ? ? from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:12: > /usr/include/odb/lazy-ptr.hxx:544:24: note: template > odb::lazy_weak_ptr::lazy_weak_ptr(const odb::lazy_shared_ptr&) > /usr/include/odb/lazy-ptr.hxx:544:24: note: ? template argument > deduction/substitution failed: > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:564:46: > note: ? 'odb::database' is not derived from 'const > odb::lazy_shared_ptr' > In file included from /usr/include/odb/lazy-ptr.hxx:643:0, > ? ? ? ? ? ? ? ? from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node.h:7, > ? ? ? ? ? ? ? ? from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.h:21, > ? ? ? ? ? ? ? ? from > /home/mine/git/bettercodes/yajp-backend/odbClasses/node-odb.cpp:12: > /usr/include/odb/lazy-ptr.ixx:1384:10: note: > odb::lazy_weak_ptr::lazy_weak_ptr() [with T = group] > /usr/include/odb/lazy-ptr.ixx:1384:10: note: ? candidate expects 0 > arguments, 2 provided > make[2]: *** [CMakeFiles/yajpws.dir/odbClasses/node-odb.cpp.o] Error 1 > make[1]: *** [CMakeFiles/yajpws.dir/all] Error 2 > make: *** [all] Error 2 > > node.h: > > #ifndef NODE_H > #define NODE_H > > #include > #include > #include > #include > > #include "activity.h" > > class group ; > > #pragma db object polymorphic > class node { > public: > ? ? ? ?node( ? const std::string &hash, > ? ? ? ? ? ? ? ?int creationTime) : > ? ? ? ? ? ? ? ?hash_(hash), creationTime_(creationTime) {} > ? ? ? ?virtual ~node() = 0 ; > > protected: > ? ? ? ?friend class odb::access ; > ? ? ? ?node() {} > > ? ? ? ?#pragma db id auto > ? ? ? ?unsigned long id_ ; > ? ? ? ?std::string hash_ ; > ? ? ? ?int creationTime_ ; > ? ? ? ?#pragma db value_not_null > ? ? ? ?std::vector > activities_ ; > ? ? ? ?#pragma db value_not_null inverse(nodes_) > ? ? ? ?std::vector > groups_ ; > } ; > > #ifdef ODB_COMPILER > #include "group.h" > #endif > > #endif // NODE_H > > > group.h: > > #ifndef GROUP_H > #define GROUP_H > > #include > #include > > #include "node.h" > > #pragma db object > class group : public node { > public: > ? ? ? ?group( ?const std::string &hash, > ? ? ? ? ? ? ? ?int creationTime, > ? ? ? ? ? ? ? ?const std::string &title) : > ? ? ? ? ? ? ? ?node(hash,creationTime), title_(title) {} > > private: > ? ? ? ?friend class odb::access ; > ? ? ? ?group() {} > > ? ? ? ?std::string title_ ; > ? ? ? ?#pragma db value_not_null > ? ? ? ?std::vector > nodes_ ; > } ; > > #endif // GROUP_H > > > > 2012/6/27 Boris Kolpackov : >> Hi Miguel, >> >> Miguel Revilla Rodr?guez writes: >> >>> I have a polymorphic class called 'node': >>> >>> #pragma db object polymorphic >>> class node { ... } ; >>> >>> Now, node is inherited by several other classes (user, group, etc). >>> And one of those classes (group) is a node that defines a group of >>> nodes. I want to set a many-to-many relationship where a group >>> contains a number of nodes and a node belongs to a number of groups. >> >> This is pretty easy to arrange if both node and group are in the same >> header file (generally a good idea when you have such a tight integration >> between the two). The idea is to forward-declare one of the classes: >> >> class group; >> >> class node >> { >> ?#pragma db value_not_null inverse(nodes_) >> ?std::vector > groups_ ; >> }; >> >> class group: public node >> { >> ?#pragma db value_not_null >> ?std::vector > nodes_ ; >> }; >> >> If you want to place node and group in separate headers, things are >> a bit trickier, but the idea is pretty much the same. You most likely >> need to include the definition of group into node in any case (e.g., >> for destructors to work, etc). In this case simply #include group.h >> after the node definition: >> >> class group; >> >> class node >> { >> ?#pragma db value_not_null inverse(nodes_) >> ?std::vector > groups_ ; >> }; >> >> #include "group.h" >> >> If your application doesn't need group.h in node.h (but the ODB compiler >> does), then you can make the include conditional: >> >> #ifdef ODB_COMPILER >> # ?include "group.h" >> #endif >> >> Boris From boris at codesynthesis.com Thu Jun 28 08:50:29 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Thu Jun 28 08:44:26 2012 Subject: [odb-users] Is this possible? In-Reply-To: References: Message-ID: Hi Miguel, Miguel Revilla Rodr?guez writes: > If both class declarations are in the same file (your first advice) > everything works fine. Yes, I tried both cases and indeed in the separate headers case the ODB compiler generates uncompilable code. I have an idea how we might be able to fix this and will try to do that for the next release. There is also a pretty easy workaround if you need the separate headers. You will need to comment out #include "group-odb.hxx" in node-odb.hxx and add that include to node-odb.cxx instead. Boris From yo at miguelrevilla.com Thu Jun 28 08:51:26 2012 From: yo at miguelrevilla.com (=?UTF-8?Q?Miguel_Revilla_Rodr=C3=ADguez?=) Date: Thu Jun 28 08:51:34 2012 Subject: [odb-users] Is this possible? In-Reply-To: References: Message-ID: Hi, Going the single file way. Hope you get to fix it for the next round. About the workaround, is not very useful for me as odb is run by cmake and that would mean patching the file "by hand" a lot of times. Thanks! 2012/6/28 Boris Kolpackov : > Hi Miguel, > > Miguel Revilla Rodr?guez writes: > >> If both class declarations are in the same file (your first advice) >> everything works fine. > > Yes, I tried both cases and indeed in the separate headers case the > ODB compiler generates uncompilable code. I have an idea how we might > be able to fix this and will try to do that for the next release. > > There is also a pretty easy workaround if you need the separate > headers. You will need to comment out #include "group-odb.hxx" > in node-odb.hxx and add that include to node-odb.cxx instead. > > Boris