From boris at codesynthesis.com Mon Oct 1 04:48:01 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Mon Oct 1 04:25:37 2012 Subject: [odb-users] Query problem In-Reply-To: <6989CEDF160F9A42A3F5FF832CBAA72C1737D0@exbe19.nasstar-t1.net> References: <6989CEDF160F9A42A3F5FF832CBAA72C173789@exbe19.nasstar-t1.net> <6989CEDF160F9A42A3F5FF832CBAA72C1737BE@exbe19.nasstar-t1.net> <6989CEDF160F9A42A3F5FF832CBAA72C1737D0@exbe19.nasstar-t1.net> Message-ID: Hi Davide, [CC'ed odb-users in case someone else runs into this problem.] Davide Anastasia writes: > odb::transaction t(m_db->begin()); > > m_quoteResult = m_db->query( > buildQuery(d.m_day))); > > t.commit(); > > // update iterators > m_quoteCurr = m_quoteResult.begin(); > m_quoteEnd = m_quoteResult.end(); The query result is only valid within the transaction where it was created. Quoting the manual (Section 4.4, "Query Result", second paragraph): "The result instance is only usable within the transaction it was created in. Trying to manipulate the result after the transaction has terminated leads to undefined behavior." Boris From boris at codesynthesis.com Mon Oct 1 05:58:41 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Mon Oct 1 05:35:50 2012 Subject: [odb-users] Prepared statement feature In-Reply-To: <3233D27CC5658E4598557F8521F6B07E2146550D92@RIC-MS01.abw.int> References: <201209271102.q8RB2NqV019699@codesynthesis.com> <3233D27CC5658E4598557F8521F6B07E2146550D06@RIC-MS01.abw.int> <3233D27CC5658E4598557F8521F6B07E2146550D92@RIC-MS01.abw.int> Message-ID: Hi Paul, Thanks for the suggestions. While I don't like your interface any better than mine ;-) and there are some implementation issues with it, it highlighted some of the aspects that I didn't think about (e.g., the desire to define age_pquery in the same header as the persistent class, which would not be possible if it contains references to the odb::query template -- it can only be used after the -odb.hxx header has been included). So based on your suggestions and some more thinking, I came up with the following alternative design: Simple Scenario The query is prepared, executed within a transaction several times, and then discarded (i.e., no caching in the connection). This approach can also work for a single-threaded application which uses a single connection. typedef odb::query query; typedef odb::result result; transaction t (db->begin ()); unsigned short age; prepared_query pq ( db->prepare_query ( "age-query", query::age < query::_ref (age))); age = 20; result r1 (pq->execute ()); age = 30; result r2 (pq->execute ()); age = 40; result r3 (pq->execute ()); ... t.commit (); Complex Scenario Here we want to cache the prepared query so that it can be executed later in other transactions. struct query_params { unsigned short age; }; typedef odb::query query; typedef odb::result result; transaction t (db->begin ()); query_params* params; prepared_query* pq (db->lookup ("age-query", params)); if (pq == 0) { auto_ptr p (new query_params); // Or unique_ptr. prepared_query q ( db->prepare_query ( "age-query", query::age < query::_ref (p->age))); params = p.get (); pq = db->cache (q, p); // Assumes ownership of p. } params->age = 20; result r (pq->execute ()); ... t.commit (); Now if we don't have any by-reference parameters, then this can be simplified to: typedef odb::query query; typedef odb::result result; transaction t (db->begin ()); prepared_query* pq (db->lookup ("age18-query")); if (pq == 0) { prepared_query q ( db->prepare_query ( "age18-query", query::age < 18)); pq = db->cache (q); } result r (pq->execute ()); ... t.commit (); What do you think? Boris From pstath at axxcelera.com Mon Oct 1 15:48:01 2012 From: pstath at axxcelera.com (Stath, Paul) Date: Mon Oct 1 15:47:34 2012 Subject: [odb-users] Prepared statement feature In-Reply-To: References: <201209271102.q8RB2NqV019699@codesynthesis.com> <3233D27CC5658E4598557F8521F6B07E2146550D06@RIC-MS01.abw.int> <3233D27CC5658E4598557F8521F6B07E2146550D92@RIC-MS01.abw.int> Message-ID: <3233D27CC5658E4598557F8521F6B07E2146550E4E@RIC-MS01.abw.int> Boris -- One of the goals I was trying to satisfy was that management of the prepared query statement in the database session would be defined by the life-cycle of the prepared_query<> object. This would eliminate the need to expose any database lookup/cache methods to the user. Any time one can make it simpler for a developer to use a library/framework, the better. Since the prepared query would exist for the lifetime of the prepared_query<> object, the query could be prepared in the database session when the object is constructed. When the destructor of the prepared_query<> is called, the prepared query statement would be cleared from the database session. In your simple scenario, the prepared query would be compiled when the pq() object is constructed, and would be cleaned up when the pq object goes out of scope. While it can be done, why not use the current obd::query<> with query::_ref(age) in the simple scenario? To make a prepared query operate over multiple transactions, the programmer would simply need to construct the prepared_query<> in such a way that it has an extended life-cycle. (i.e. member variable of a long-lived class, or as part of a shared_ptr.) For processing a prepared query that contains by-reference arguments, the execute() method should accept the parameter structure (POD) constructed as an auto_ptr (or unique_ptr). I believe that the above is simpler from a developer point of view, as well as a multi-threaded point of view. By providing the parameters via a "transfer_ptr" in the execute() method, the parameter POD only needs to be protected from concurrent use when actually binding the parameters to the prepared query. Doesn't your approach require the developer to provide their own thread safety to protect the data elements of the parameter POD? -- Paul struct query_params { unsigned short age; }; typedef odb::query query; typedef odb::result result; auto_ptr p (new query_params); // Or unique_ptr. shared_ptr pq (query::age < query::_ref(p->age, p); Then, later on, possibly in multiple worker threads: transaction t (db->begin ()); auto_ptr params; params->age = 20; result r (pq->execute (params)); // pq assumes ownership of params. ... t.commit (); From ststrou at sandia.gov Mon Oct 1 17:25:21 2012 From: ststrou at sandia.gov (Stroud, Sean T) Date: Mon Oct 1 17:25:09 2012 Subject: [odb-users] Question about query caching Message-ID: <8EDFC8F388A1E44BB67C9BAA57091F9E285CC1A0@EXMB03.srn.sandia.gov> Hi, I am new to ODB and have a question about query caching. I created the following data classes: Sensor_Product Product_Header Ephemeris The Sensor_Product has the following data members: - Product_Header *m_header_ptr; - Ephemeris *m_ephemeris_ptr; - int m_id; // the primary key Now say I issue a query on the Sensor_Product class, like this: // Issue the query transaction t(db->begin); query sp_query( query::data_value > 10 ); result sp_result( db->query(sp_query) ); // Cache the results sp_result.cache(); // Iterate over the results for ( result::iterator iter(sp_result.begin(); iter != sp_result.end(); ++iter ) { const Sensor_Product &sp = *iter; cout << sp.m_id << endl; } What I am seeing is that the "Issue the query" section above does a SELECT with two LEFT JOINs to get the Sensor_Product, Product_Header and Ephemeris classes. That makes sense. But then it looks like the "Iterate over the results" section causes more SELECT statements to be issued. In particular, each time the "*iter" expression is executed in the for loop, ODB is issuing two queries: one to select the Product_Header and one to select the Ephemeris. This surprised me since I thought I was caching the results with the "sp_result.cache()" statement. These extra select statements appear to slow things down considerably, so I'd like to understand why they are necessary and (more importantly) if there is a way I can eliminate them. Can someone educate me? Thanks. Sean From uwe.kindler at cetoni.de Mon Oct 1 09:56:12 2012 From: uwe.kindler at cetoni.de (cetoni GmbH - Uwe Kindler) Date: Tue Oct 2 01:30:14 2012 Subject: [odb-users] ODB 2.1.0 - absolute include paths Message-ID: <5069A0FC.5020207@cetoni.de> Hello, I just noticed that ODB 2.1.0 compiler generates absoulte include paths in xxx-odb.h files while older ODB versions simply added the header file without any path. Here an old version of my WellPlateType-odb.h file: ... #include "WellPlateType.h" ... And here the new version generated from ODB 2.1.0: ... #include "C:/usl/env/qt/qtlabb/items/WellPlateType.h" ... Is there an ODB compiler option to toggle between these two versions? The problem is, that we generate the files only if something changed - so not on every build. That means the generated files are also checked into out version control system. But this now only works if all developers do a checkout of the project into the exact same location. So is there any switch - maybe I missed it in the ODB compiler documentation? Thank you and kind regards, Uwe Kindler From boris at codesynthesis.com Tue Oct 2 02:56:33 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Tue Oct 2 02:33:26 2012 Subject: [odb-users] ODB 2.1.0 - absolute include paths In-Reply-To: <5069A0FC.5020207@cetoni.de> References: <5069A0FC.5020207@cetoni.de> Message-ID: Hi Uwe, cetoni GmbH - Uwe Kindler writes: > I just noticed that ODB 2.1.0 compiler generates absoulte include paths > in xxx-odb.h files while older ODB versions simply added the header file > without any path. > > Here an old version of my WellPlateType-odb.h file: > > ... > #include "WellPlateType.h" > ... > > > And here the new version generated from ODB 2.1.0: > > ... > #include "C:/usl/env/qt/qtlabb/items/WellPlateType.h" > ... This is a regression from 2.0.0. I've found and fixed the problem and built a 2.1.1 package for Windows: http://www.codesynthesis.com/~boris/tmp/odb/odb-2.1.1-i686-windows.zip Can you confirm that it works for you? Then I will publish it as an official bugfix release. Thanks for reporting this! Boris From boris at codesynthesis.com Tue Oct 2 03:44:43 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Tue Oct 2 03:21:38 2012 Subject: [odb-users] Question about query caching In-Reply-To: <8EDFC8F388A1E44BB67C9BAA57091F9E285CC1A0@EXMB03.srn.sandia.gov> References: <8EDFC8F388A1E44BB67C9BAA57091F9E285CC1A0@EXMB03.srn.sandia.gov> Message-ID: Hi Sean, Stroud, Sean T writes: > I am new to ODB and have a question about query caching. I created > the following data classes: > > Sensor_Product > Product_Header > Ephemeris > > The Sensor_Product has the following data members: > - Product_Header *m_header_ptr; > - Ephemeris *m_ephemeris_ptr; > - int m_id; // the primary key > > [...] > > // Cache the results > sp_result.cache(); You don't really need to make this call since query results are cached by default. You will need to explicitly pass false as a second argument to database::query() in order to create an un- cached result. > What I am seeing is that the "Issue the query" section above > does a SELECT with two LEFT JOINs to get the Sensor_Product, > Product_Header and Ephemeris classes. This is not quite correct. The JOINs are there to allow you to use referenced object's members in query conditions. The data for the objects themselves is not retrieved by this query, as is evident from the select-list of the query. > But then it looks like the "Iterate over the results" section > causes more SELECT statements to be issued. In particular, each > time the "*iter" expression is executed in the for loop, ODB is > issuing two queries: one to select the Product_Header and one to > select the Ephemeris. When the iterator is dereferenced (*iter), the actual object (Sensor_Product) is instantiated. Since it references two other objects (Product_Header and Ephemeris), those have to be loaded as well. The two SELECT statements that you see achieve exactly that. > This surprised me since I thought I was caching the results with > the "sp_result.cache()" statement. This has really nothing to do with caching. Quoting the manual (Section 4.4, "Query Result"): "If the result is cached, the database state of all the returned objects is stored in the application's memory. Note that the actual objects are still only instantiated on demand during result iteration. It is the raw database state that is cached in memory. In contrast, for uncached results the object's state is sent by the database system one object at a time as the iteration progresses." > These extra select statements appear to slow things down considerably, > so I'd like to understand why they are necessary and (more importantly) > if there is a way I can eliminate them. Yes, you can use lazy pointers to control if and when referenced objects are loaded. Refer to Section 6.4, "Lazy Pointers" in the ODB manual for details. Boris From boris at codesynthesis.com Tue Oct 2 05:04:02 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Tue Oct 2 04:40:56 2012 Subject: [odb-users] Prepared statement feature In-Reply-To: <3233D27CC5658E4598557F8521F6B07E2146550E4E@RIC-MS01.abw.int> References: <201209271102.q8RB2NqV019699@codesynthesis.com> <3233D27CC5658E4598557F8521F6B07E2146550D06@RIC-MS01.abw.int> <3233D27CC5658E4598557F8521F6B07E2146550D92@RIC-MS01.abw.int> <3233D27CC5658E4598557F8521F6B07E2146550E4E@RIC-MS01.abw.int> Message-ID: Hi Paul, Again, thanks for the feedback. See my comments below. Stath, Paul writes: > In your simple scenario, the prepared query would be compiled when the > pq() object is constructed, and would be cleaned up when the pq object > goes out of scope. Yes. More precisely, the query is prepared by the db->prepare_query() call. > While it can be done, why not use the current obd::query<> with > query::_ref(age) in the simple scenario? I am not sure what you mean by this. The simple scenario uses odb::query to construct the query predicate. > To make a prepared query operate over multiple transactions, the > programmer would simply need to construct the prepared_query<> in > such a way that it has an extended life-cycle. (i.e. member variable > of a long-lived class, or as part of a shared_ptr.) The API that I described does not prevent you from doing this, provided you use the same connection (i.e., your database access is single- threaded). With multi-threaded applications things are more complicated since prepared statements (which is what the prepared_query<> will really be, underneath) are connection-specific. I.e., you cannot prepare a statement using one database connection and then execute it on another. So if a multi-threaded application wants to repeatedly execute the same prepared statement from multiple treads, then it will have to create a separate one for each connection. > For processing a prepared query that contains by-reference arguments, > the execute() method should accept the parameter structure (POD) > constructed as an auto_ptr (or unique_ptr). The by-reference parameters are already "bound" to the query during preparation. It is not possible (well, not cheap, to be precisely) to re-bind them for each execution. > Doesn't your approach require the developer to provide their own > thread safety to protect the data elements of the parameter POD? No. In my approach each connection gets its own prepared query and parameter object. And since each connection can only be accessed by a single thread at a time, there is no need for access synchronization. I guess I should have explained this whole connection/multi-threading issue from the beginning (to me it sounds obvious since I know how things work underneath). So let's say we have 10 threads executing the same transaction in a loop, in parallel. Underneath there will be a connection pool with 10 connections. When each thread starts a transaction, it gets one of the connections from this pool. Now it needs to get a prepared query that corresponds to this connection. That's why a thread cannot store a prepared query that it created. And that's where this whole caching business comes into play. A thread looks up the prepared query in the per-connection cache, creating one if it doesn't exist. And, in case of the by-ref parameters, this cache will also store the user-provided parameter object. But, if the application is single-threaded (and thus only uses one connection), then there is no need to use the cache or the parameter object (as shown in the simple scenario). Instead, the prepared query and the by-ref parameters can be stored as local variable, members of some class, or even as global variables. Boris From pstath at axxcelera.com Tue Oct 2 08:07:26 2012 From: pstath at axxcelera.com (Stath, Paul) Date: Tue Oct 2 08:06:52 2012 Subject: [odb-users] Prepared statement feature In-Reply-To: References: <201209271102.q8RB2NqV019699@codesynthesis.com> <3233D27CC5658E4598557F8521F6B07E2146550D06@RIC-MS01.abw.int> <3233D27CC5658E4598557F8521F6B07E2146550D92@RIC-MS01.abw.int> <3233D27CC5658E4598557F8521F6B07E2146550E4E@RIC-MS01.abw.int> Message-ID: <3233D27CC5658E4598557F8521F6B07E2146550E68@RIC-MS01.abw.int> Boris -- Thanks for explaining the connection/multi-threading issue more fully. The ODB library does a really good job of handling connections and multi-threading issues, and not passing these issues up to be handled by the developer. My thinking was that the prepared_query<> class would work like a factory class, creating the prepared query statement in each database connection as necessary. Thus hiding the connection/multi-threading aspects of the connection, much like odb::::connection_factory hides how connection objects are obtained. The prepared_query<> class would hold the query condition, and when the execute method is called, would look up the prepared statement in the current database connection, and if not present would prepare and cache it in the connection, and finally execute it. The next time that connection is used to execute the prepared query, the prepared statement would already be in the cache, and the query could be executed, skipping the prepare/cache steps. It seems to me that there is no need to expose the lookup and cache methods to the user, instead hide them inside the execute method of the prepared query. In the end, either method will work, and will allow the prepared query statement to be cached, eliminating the expensive parse of the query statement for every query. Thanks for taking the time to discuss. -- Paul From uwe.kindler at cetoni.de Tue Oct 2 07:25:20 2012 From: uwe.kindler at cetoni.de (cetoni GmbH - Uwe Kindler) Date: Tue Oct 2 08:09:31 2012 Subject: [odb-users] Pimpl + Relations Message-ID: <506ACF20.70502@cetoni.de> Hi, I implemented two database classes following the pimpl idiom and the ODB pimpl example using virtual data members. You can see one class here: http://codeviewer.org/view/code:2a32 Now I need to implement a To-One relation for this CLensMeasurement Class. At the moment, the CLensMeasurement class has a data member m_Lens (shared pointer) to create this relation. I would like to know, if it is possible to move this member into the private implemantation class LensMeasurmentPrivate and to use virtual member functions instead of the real data member. I already tried this (see line 74 of code snippet). But this did not work - ODB compiler tells me: invalid name in db pragma member. So my question is - ist ist possible to build releations with virtual data members or does a relations always need a real data member. Thank you and kind regards, Uwe From boris at codesynthesis.com Tue Oct 2 08:39:39 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Tue Oct 2 08:16:28 2012 Subject: [odb-users] Pimpl + Relations In-Reply-To: <506ACF20.70502@cetoni.de> References: <506ACF20.70502@cetoni.de> Message-ID: Hi Uwe, cetoni GmbH - Uwe Kindler writes: > I would like to know, if it is possible to move this member into > the private implementation class LensMeasurmentPrivate and to use > virtual member functions instead of the real data member. Yes, any non-transient data member can be made virtual, including object pointers and containers. > I already tried this (see line 74 of code snippet). But this did not > work - ODB compiler tells me: invalid name in db pragma member. Line 74 in your code fragment looks like this: > #pragma db member(boost::shared_ptr) virtual(LensPtr) get(lens) set (setLens) I think you mistakenly used the type rather than the name in the member() clause. It probably should be something along these lines: #pragma db member(Lens) virtual(LensPtr) get(lens) set(setLens) Boris From uwe.kindler at cetoni.de Tue Oct 2 08:38:59 2012 From: uwe.kindler at cetoni.de (cetoni GmbH - Uwe Kindler) Date: Tue Oct 2 09:42:42 2012 Subject: [odb-users] Pimpl + Relations In-Reply-To: References: <506ACF20.70502@cetoni.de> Message-ID: <506AE063.8080702@cetoni.de> Hi Boris, thank you - yes you are right, this was a mistake, but also with your suggestion it does not work here. I now have the following two lines in my code: typedef boost::shared_ptr LensPtr; #pragma db member(Lens1) virtual(LensPtr) get(lens) set(setLens) #pragma db member(Lens2) virtual(boost::shared_ptr) get(lens) set(setLens) For the last line I get the ODB compiler error: name 'boost::shared_ptr' in db pragma virtual does not refer to a type and for the second line of code I get the error: error: modifier expression requires member type to be default-constructible So does this mean I cannot use shared pointers in virtual members? Does this mean, I should use a shared CLens pointer only internally in my private class and use const CLens references in the access functions? Thank you, Uwe From boris at codesynthesis.com Tue Oct 2 10:24:25 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Tue Oct 2 10:01:10 2012 Subject: [odb-users] Pimpl + Relations In-Reply-To: <506AE063.8080702@cetoni.de> References: <506ACF20.70502@cetoni.de> <506AE063.8080702@cetoni.de> Message-ID: Hi Uwe, cetoni GmbH - Uwe Kindler writes: > typedef boost::shared_ptr LensPtr; > #pragma db member(Lens1) virtual(LensPtr) get(lens) set(setLens) This should work in theory. In practice what happens is the ODB compiler checks for a default constructor in LensPtr (which is needed because a by-value modifier is used). It doesn't find it even though boost::shared_ptr is default-constructible because shared_ptr is not fully instantiated. I've fixed this by making sure that virtual data member types are fully instantiated before checking for the default ctor. Can you try a new revision of the 2.1.1 bugfix and see if it works for you: http://www.codesynthesis.com/~boris/tmp/odb/odb-2.1.1-i686-windows.zip Also, you can simplify the above pragma if you use 'lens' as the virtual member name. This way the ODB compiler should find the accessor and modifier functions automatically: #pragma db member(lens) virtual(LensPtr) Boris From boris at codesynthesis.com Wed Oct 3 09:47:19 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Wed Oct 3 09:23:54 2012 Subject: [odb-users] Prepared statement feature In-Reply-To: <3233D27CC5658E4598557F8521F6B07E2146550E68@RIC-MS01.abw.int> References: <201209271102.q8RB2NqV019699@codesynthesis.com> <3233D27CC5658E4598557F8521F6B07E2146550D06@RIC-MS01.abw.int> <3233D27CC5658E4598557F8521F6B07E2146550D92@RIC-MS01.abw.int> <3233D27CC5658E4598557F8521F6B07E2146550E4E@RIC-MS01.abw.int> <3233D27CC5658E4598557F8521F6B07E2146550E68@RIC-MS01.abw.int> Message-ID: Hi Paul, Stath, Paul writes: > My thinking was that the prepared_query<> class would work like a > factory class, creating the prepared query statement in each database > connection as necessary. Thus hiding the connection/multi-threading > aspects of the connection, much like odb::::connection_factory > hides how connection objects are obtained. I agree, that would be nice. However: > The prepared_query<> class would hold the query condition, and when > the execute method is called, would look up the prepared statement > in the current database connection, and if not present would prepare > and cache it in the connection, and finally execute it. > The next time that connection is used to execute the prepared query, > the prepared statement would already be in the cache, and the query > could be executed, skipping the prepare/cache steps. The problem are the by-reference parameters. We either have to create a separate set for each connection or there will have to be access synchronization. The latter I believe is a bad idea since it will constrain parallelism. And if we go with the former, then there cannot be a shared query condition since it is bound to a specific set of by-reference parameters. In other words, we will need to create a separate odb::query object that is bound to a separate set of by-reference parameters. And given the current architecture, I don't see an easy way to clone odb::query but give it a separate set of by-ref parameters. I also thought about the factory idea in the following context: if the same prepared query is used in multiple different transactions, then things can get unmaintainable because now the query condition (i.e., query::age < query::_ref (age)) has to be duplicated in each of them (because they all need to be prepared to handle the case where the statement hasn't yet been prepared and cached; see the complex scenario in my previous email). So I thought that it would be a good idea to allow the specification of a factory that will be called to prepare the statement if the call to lookup() didn't find anything. Here is an example (using C++11 lambda but normal function/functor can also be used): struct query_params { unsigned short age; }; typedef odb::query query; typedef odb::result result; db->prepared_query_factory ( "age-query", [] (const char* name, connection& conn) { auto_ptr p (new query_params); // Or unique_ptr. prepared_query q ( conn.prepare_query ( name, query::age < query::_ref (p->age))); conn.cache (q, p); // Assumes ownership of p. }); transaction t (db->begin ()); query_params* params; prepared_query* pq (db->lookup ("age-query", params)); assert (pq != 0); params->age = 20; result r (pq->execute ()); ... t.commit (); > It seems to me that there is no need to expose the lookup and cache > methods to the user, instead hide them inside the execute method of > the prepared query. One nice thing about my approach is that it is incremental: one can just create a prepared query on the stack, execute it a couple of times, and that's it. No caching involved. The next level is a query that one would like to reuse in the same (single) transaction (code wise, not repetition-wise). Here we can make do with caching in this transaction, keeping everything local. And the final level is when we need to reuse the same query in multiple different transactions (say a query that returns the next sequence number). Here we can use the factory approach to keep things maintainable. > In the end, either method will work, and will allow the prepared > query statement to be cached, eliminating the expensive parse of > the query statement for every query. Ok, I've started working on this and should have something for you to try in a few days. Boris From pstath at axxcelera.com Wed Oct 3 10:28:42 2012 From: pstath at axxcelera.com (Stath, Paul) Date: Wed Oct 3 10:28:00 2012 Subject: [odb-users] Prepared statement feature In-Reply-To: References: <201209271102.q8RB2NqV019699@codesynthesis.com> <3233D27CC5658E4598557F8521F6B07E2146550D06@RIC-MS01.abw.int> <3233D27CC5658E4598557F8521F6B07E2146550D92@RIC-MS01.abw.int> <3233D27CC5658E4598557F8521F6B07E2146550E4E@RIC-MS01.abw.int> <3233D27CC5658E4598557F8521F6B07E2146550E68@RIC-MS01.abw.int> Message-ID: <3233D27CC5658E4598557F8521F6B07E2146550F05@RIC-MS01.abw.int> Boris -- I think I see the issue. (From a previous email in this thread.) > The by-reference parameters are already "bound" to the query during preparation. > It is not possible (well, not cheap, to be precisely) to re-bind them for each execution. In my proposed implementation, the by-reference POD structure was passed as an argument to the prepared_query.execute() method. Which is when I assumed that the by-ref parameters would be bound to the prepared select_statement. Your previous statement seems to indicate that the by-reference arguments have already been bound to the select_statement when the prepared_query class was constructed. Am I following that? > Ok, I've started working on this and should have something for you > to try in a few days. My schedule is kind of tight for October, but I should be able to dedicate some time to testing it in November. -- Paul > -----Original Message----- > From: Boris Kolpackov [mailto:boris@codesynthesis.com] > Sent: Wednesday, October 03, 2012 9:47 AM > To: Stath, Paul > Cc: odb-users@codesynthesis.com > Subject: Re: [odb-users] Prepared statement feature > > Hi Paul, > > Stath, Paul writes: > > > My thinking was that the prepared_query<> class would work like a > > factory class, creating the prepared query statement in each database > > connection as necessary. Thus hiding the connection/multi-threading > > aspects of the connection, much like odb::::connection_factory > > hides how connection objects are obtained. > > I agree, that would be nice. However: > > > > The prepared_query<> class would hold the query condition, and when > > the execute method is called, would look up the prepared statement > > in the current database connection, and if not present would prepare > > and cache it in the connection, and finally execute it. > > The next time that connection is used to execute the prepared query, > > the prepared statement would already be in the cache, and the query > > could be executed, skipping the prepare/cache steps. > > The problem are the by-reference parameters. We either have to create > a separate set for each connection or there will have to be access > synchronization. The latter I believe is a bad idea since it will > constrain parallelism. And if we go with the former, then there > cannot be a shared query condition since it is bound to a specific > set of by-reference parameters. In other words, we will need to > create a separate odb::query object that is bound to a separate > set of by-reference parameters. And given the current architecture, > I don't see an easy way to clone odb::query but give it a separate > set of by-ref parameters. > > I also thought about the factory idea in the following context: if > the same prepared query is used in multiple different transactions, > then things can get unmaintainable because now the query condition > (i.e., query::age < query::_ref (age)) has to be duplicated in > each of them (because they all need to be prepared to handle the > case where the statement hasn't yet been prepared and cached; see > the complex scenario in my previous email). So I thought that it > would be a good idea to allow the specification of a factory that > will be called to prepare the statement if the call to lookup() > didn't find anything. Here is an example (using C++11 lambda but > normal function/functor can also be used): > > struct query_params > { > unsigned short age; > }; > > typedef odb::query query; > typedef odb::result result; > > db->prepared_query_factory ( > "age-query", > [] (const char* name, connection& conn) > { > auto_ptr p (new query_params); // Or unique_ptr. > > prepared_query q ( > conn.prepare_query ( > name, query::age < query::_ref (p->age))); > > conn.cache (q, p); // Assumes ownership of p. > }); > > transaction t (db->begin ()); > > query_params* params; > prepared_query* pq (db->lookup ("age-query", params)); > assert (pq != 0); > > params->age = 20; > result r (pq->execute ()); > > ... > > t.commit (); > > > > It seems to me that there is no need to expose the lookup and cache > > methods to the user, instead hide them inside the execute method of > > the prepared query. > > One nice thing about my approach is that it is incremental: one can > just create a prepared query on the stack, execute it a couple of > times, > and that's it. No caching involved. The next level is a query that one > would like to reuse in the same (single) transaction (code wise, not > repetition-wise). Here we can make do with caching in this transaction, > keeping everything local. And the final level is when we need to reuse > the same query in multiple different transactions (say a query that > returns the next sequence number). Here we can use the factory approach > to keep things maintainable. > > > > In the end, either method will work, and will allow the prepared > > query statement to be cached, eliminating the expensive parse of > > the query statement for every query. > > Ok, I've started working on this and should have something for you > to try in a few days. > > Boris From ststrou at sandia.gov Wed Oct 3 15:32:57 2012 From: ststrou at sandia.gov (Stroud, Sean T) Date: Wed Oct 3 15:32:42 2012 Subject: [odb-users] Compile error with shared_ptr to db value Message-ID: <8EDFC8F388A1E44BB67C9BAA57091F9E285CC49F@EXMB03.srn.sandia.gov> Hi, I am getting errors trying to compile the odb-generated code for the example below: #include #include #include #include #pragma db value class job { public: job(); private: friend class odb::access; std::string m_name; std::string m_description; }; #pragma db object class person { public: person(); private: friend class odb::access; #pragma db id int m_id; // With this one, the generated person-odb.cxx file fails to compile std::tr1::shared_ptr m_job_shared_ptr; // But this one is fine std::auto_ptr m_job_auto_ptr; }; After I run the odb compiler on person.h, I get errors trying to compile the resulting person-odb.cxx file: person-odb.cxx: In static member function ???static bool odb::access::object_traits::init(odb::access::object_traits::image_type&, const person&, odb::pgsql::statement_kind)???: person-odb.cxx:355: error: incomplete type ???odb::wrapper_traits >??? used in nested name specifier person-odb.cxx: In static member function ???static void odb::access::object_traits::init(person&, const odb::access::object_traits::image_type&, odb::database*)???: person-odb.cxx:404: error: incomplete type ???odb::wrapper_traits >??? used in nested name specifier However if I comment out the declaration of the "m_job_shared_ptr" member then I do not get these errors. Since auto_ptr compiles fine, I would expect shared_ptr to compile fine as well. Possibly a bug? IF not, what am I doing wrong? Thanks, Sean From boris at codesynthesis.com Thu Oct 4 09:16:33 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Thu Oct 4 08:52:47 2012 Subject: [odb-users] Prepared statement feature In-Reply-To: <3233D27CC5658E4598557F8521F6B07E2146550F05@RIC-MS01.abw.int> References: <201209271102.q8RB2NqV019699@codesynthesis.com> <3233D27CC5658E4598557F8521F6B07E2146550D06@RIC-MS01.abw.int> <3233D27CC5658E4598557F8521F6B07E2146550D92@RIC-MS01.abw.int> <3233D27CC5658E4598557F8521F6B07E2146550E4E@RIC-MS01.abw.int> <3233D27CC5658E4598557F8521F6B07E2146550E68@RIC-MS01.abw.int> <3233D27CC5658E4598557F8521F6B07E2146550F05@RIC-MS01.abw.int> Message-ID: Hi Paul, Stath, Paul writes: > In my proposed implementation, the by-reference POD structure was passed > as an argument to the prepared_query.execute() method. Which is when I > assumed that the by-ref parameters would be bound to the prepared > select_statement. > > Your previous statement seems to indicate that the by-reference arguments > have already been bound to the select_statement when the prepared_query > class was constructed. Am I following that? More precisely, the by-reference parameters are bound to the odb::query object. So to pass a single odb::query but then "split" the parameters into multiple sets won't be easy. Boris From boris at codesynthesis.com Thu Oct 4 09:32:07 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Thu Oct 4 09:08:21 2012 Subject: [odb-users] Compile error with shared_ptr to db value In-Reply-To: <8EDFC8F388A1E44BB67C9BAA57091F9E285CC49F@EXMB03.srn.sandia.gov> References: <8EDFC8F388A1E44BB67C9BAA57091F9E285CC49F@EXMB03.srn.sandia.gov> Message-ID: Hi Sean, Stroud, Sean T writes: > Possibly a bug? Yes, it is a bug, thanks for reporting it. This whole TR1 thing is quite a mess. Besides not all compilers supporting it, those that do each have a different way to include the headers. Add to that the fact that Boost provides TR1 implementation that is just aliased to its custom types (e.g, boost::shared_ptr), and I often wish there was no TR1 at all. In any case, I've fixed this bug and built a bugfix binary in case you would like to give it a try: http://www.codesynthesis.com/~boris/tmp/odb/odb-2.1.1-x86_64-linux-gnu.tar.bz2 Boris From dctomm at gmail.com Thu Oct 4 17:20:25 2012 From: dctomm at gmail.com (Doug Tomm) Date: Thu Oct 4 17:19:32 2012 Subject: [odb-users] callback is not being called Message-ID: <23CA1062-5310-42D5-95A3-2BE8FAD7EF40@gmail.com> ODB version: 2.0.0 compiler: gcc 4.1.2 OS: CentOS 5 hello, i have defined a class with a persist callback, but that callback is not being called, for any event. everything works -- when i persist the object instance, it appears in the database. but except that the callback is never invoked. how do i make this work? here are snippets from my code: #pragma db object table("account") callback(oninsert) class Account { private: void oninsert(::odb::callback_event event, ::odb::database& db) { std::cout << "whee" << std::endl; // other goings-on here } the only place in the generated code where i see my callback is in the .ixx file: inline void access::object_traits< Account >:: callback (database& db, object_type& x, callback_event e) { ODB_POTENTIALLY_UNUSED (db); ODB_POTENTIALLY_UNUSED (x); ODB_POTENTIALLY_UNUSED (e); static_cast< Account& > (x).oninsert (e, db); } many thanks, doug From oded at geek.co.il Thu Oct 4 17:56:09 2012 From: oded at geek.co.il (Oded Arbel) Date: Thu Oct 4 17:55:16 2012 Subject: [odb-users] Queries matching on NVARCHAR fields fail to return records when using "short data" Message-ID: Hi guys. I'm using MS-SQL Server 2008, and I noticed that when I use queries that match on NVARCHAR fields, the matching always fails if the field is short enough to be considered "short data" (according to section 17.1 of the manual). My model class looks something like this: typedef std::wstring short_string; #pragma db value(short_string) type("NVARCHAR(36)") typedef std::wstring long_text; #pragma db value(long_text) type("NVARCHAR(MAX)") namespace model { #pragma db object table("some_item") class SomeItem { public: ~SomeItem() {} SomeItem(unsigned int otheritem):_id(0) { } // getters, setters, business logic etc.. private: unsigned int _id; public: unsigned int id() const { return _id; }; private: // serialization support friend class odb::access; #pragma db member(_id) id auto column("job_item_id") protected: #pragma db column("other_item_id") std::shared_ptr _otheritem; short_string _uuid; odb::nullable _fqdn; int _state; #pragma db type("NVARCHAR(128)") odb::nullable _name; }; } And my query looks something like this: std::vector> getStuff(unsigned int otherId, const std::wstring& someName) { typedef odb::query query; try { std::vector> out; odb::transaction t(getDB()->begin()); odb::result rs(getDB()->query(query::otheritem == query::_val(otherId) && query::name == someName && query::state == query::_val(SOME_KNOWN_STATE) )); for (auto it(rs.begin()); it != rs.end(); ++it) { out.push_back(std::shared_ptr(new SomeItem(*it))); } return out; } catch (const odb::exception &e) { // handle errors } } (There are few peculiarities in this code which I would be happy to discuss as well, but more on that later). Now with the default setting, this query always returns an empty list even though all the fields are properly populated in the database. I've tried commenting out the query::name part, and then it returns what I expect. I also tried _val and _ref for matching on the item name, but to no avail. After I rebuilt the ODB implementation using --mssql-short-limit 100, it started working - now queries that match on name return the expected results. But matching on "uuid" (which is a "short string" so should use short data even with the new setting), indeed still fails. Is there something obvious I'm missing here? -- Oded From boris at codesynthesis.com Fri Oct 5 05:08:07 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Fri Oct 5 04:44:08 2012 Subject: [odb-users] Queries matching on NVARCHAR fields fail to return records when using "short data" In-Reply-To: References: Message-ID: Hi Oded, Oded Arbel writes: > I'm using MS-SQL Server 2008, and I noticed that when I use queries > that match on NVARCHAR fields, the matching always fails if the field > is short enough to be considered "short data" (according to section > 17.1 of the manual). I've done some testing and found the bug. It only affects short data national characters. I've prepared the libodb-mssql-2.1.1 bugfix: http://www.codesynthesis.com/~boris/tmp/odb/libodb-mssql-2.1.1.zip Can you give it a try and confirm it works for you. Then I will publish it as an official bugfix release. > My model class looks something like this: > > typedef std::wstring short_string; > #pragma db value(short_string) type("NVARCHAR(36)") > typedef std::wstring long_text; > #pragma db value(long_text) type("NVARCHAR(MAX)") Unfortunately, this won't work since typedef does not create a new type, just another name for the same one. So with the above fragment any std::wstring, short_string, or long_text data member that doesn't specify the type explicitly will default to NVARCHAR(MAX). Boris From boris at codesynthesis.com Fri Oct 5 05:13:07 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Fri Oct 5 04:49:03 2012 Subject: [odb-users] callback is not being called In-Reply-To: <23CA1062-5310-42D5-95A3-2BE8FAD7EF40@gmail.com> References: <23CA1062-5310-42D5-95A3-2BE8FAD7EF40@gmail.com> Message-ID: Hi Doug, Doug Tomm writes: > i have defined a class with a persist callback, but that callback > is not being called, for any event. everything works -- when i > persist the object instance, it appears in the database. but > except that the callback is never invoked. > > void oninsert(::odb::callback_event event, ::odb::database& db) You need to make it const: void oninsert(::odb::callback_event event, ::odb::database& db) const Quoting the manual (Section 12.1.7, "callback"): "The callback function for the *_persist, *_update, and *_erase events is always called on the constant object reference while for the *_load events ? always on the unrestricted reference. If only the non-const version of the callback function is provided, then only the *_load events will be delivered. If only the const version is provided, then all the events will be delivered to this function. Finally, if both versions are provided, then the *_load events will be delivered to the non-const version while all others ? to the const version." Boris From dctomm at gmail.com Fri Oct 5 11:22:32 2012 From: dctomm at gmail.com (Douglas Tomm) Date: Fri Oct 5 11:21:35 2012 Subject: [odb-users] callback is not being called In-Reply-To: References: <23CA1062-5310-42D5-95A3-2BE8FAD7EF40@gmail.com> Message-ID: that did the trick - works perfectly now. thank you! d On Oct 5, 2012, at 2:13 AM, Boris Kolpackov wrote: > Hi Doug, > > Doug Tomm writes: > >> i have defined a class with a persist callback, but that callback >> is not being called, for any event. everything works -- when i >> persist the object instance, it appears in the database. but >> except that the callback is never invoked. >> >> void oninsert(::odb::callback_event event, ::odb::database& db) > > You need to make it const: > > void oninsert(::odb::callback_event event, ::odb::database& db) const > > Quoting the manual (Section 12.1.7, "callback"): > > "The callback function for the *_persist, *_update, and *_erase events is > always called on the constant object reference while for the *_load events ? > always on the unrestricted reference. > > If only the non-const version of the callback function is provided, then only > the *_load events will be delivered. If only the const version is provided, > then all the events will be delivered to this function. Finally, if both > versions are provided, then the *_load events will be delivered to the > non-const version while all others ? to the const version." > > Boris From ststrou at sandia.gov Fri Oct 5 16:31:21 2012 From: ststrou at sandia.gov (Stroud, Sean T) Date: Fri Oct 5 16:30:45 2012 Subject: [odb-users] odb compiler assert when db value pragma placed on subclass Message-ID: <8EDFC8F388A1E44BB67C9BAA57091F9E285CCB5B@EXMB03.srn.sandia.gov> Hi, I get an assert from odb on the following program: File foo.h: class Bar { }; #pragma db value class Foo : public Bar { public: int m_seconds; }; Here is what I get when I run odb: % odb -d mysql foo.h cc1plus: common.cxx:68: virtual void object_members_base::traverse(semantics::class_&): Assertion `context::top_object != 0' failed. *** WARNING *** there are active plugins, do not report this as a bug unless you can reproduce it without enabling any plugins. Event | Plugins PLUGIN_START_UNIT | odb PLUGIN_PRAGMAS | odb PLUGIN_OVERRIDE_GATE | odb In file included from /home/ststrou/ODB2.1/odb-2.1.0-x86_64-linux-gnu/x86_64-linux-gnu/bin/../lib64/gcc/../../include/odb/container-traits.hxx:196:0, from :9: /home/ststrou/ODB2.1/odb-2.1.0-x86_64-linux-gnu/x86_64-linux-gnu/bin/../lib64/gcc/../../include/odb/std-vector-traits.hxx:65:1: internal compiler error: Aborted Please submit a full bug report, with preprocessed source if appropriate. See for instructions. Note the following: - The assert does not happen if I delete the "#pragma db value" line - The assert does not happen if I eliminate the Foo -> Bar inheritance I assume this is a bug. However, I was wondering what odb will do once this bug is fixed. Will the odb compiler support this kind of situation (i.e. db value pragma on a subclass)? Or will it reject my program with an error message? Does it matter if the base class has data members or not? Does it matter if it inherits from multiple classes? Thanks, Sean From oded at geek.co.il Sun Oct 7 05:34:00 2012 From: oded at geek.co.il (Oded Arbel) Date: Sun Oct 7 05:32:48 2012 Subject: [odb-users] Queries matching on NVARCHAR fields fail to return records when using "short data" In-Reply-To: References: Message-ID: On Fri, Oct 5, 2012 at 11:08 AM, Boris Kolpackov wrote: > I've done some testing and found the bug. It only affects short data > national characters. I've prepared the libodb-mssql-2.1.1 bugfix: > Thanks for the quick turnaround! Unfortunately we're still working with 2.0, and at this point I'd rather not upgrade to 2.1 (I may be able to push to 2.1 later this year). In the mean time, is it possible for you to push this as a bugfix on 2.0? TIA > My model class looks something like this: > > > > typedef std::wstring short_string; > > #pragma db value(short_string) type("NVARCHAR(36)") > > typedef std::wstring long_text; > > #pragma db value(long_text) type("NVARCHAR(MAX)") > > Unfortunately, this won't work since typedef does not create a new > type, just another name for the same one. So with the above fragment > any std::wstring, short_string, or long_text data member that doesn't > specify the type explicitly will default to NVARCHAR(MAX). > >From the use of #pragma db value() in the manual, I understood that this use is OK (though it doesn't state that specifically). Interesting though that with the setting I specified in my previous email ( short-limit=100), selecting on a field defined as "long_text" succeeds while selecting on a field defined as "short_string" fails (none of which specify #pragma db type specifically in the class decleration) - so it looks like there is some difference in how ODB treats these typedefs - unless it has something to do with the long_text field being actually odb::nullable? Best regards, -- Oded From boris at codesynthesis.com Sun Oct 7 08:52:20 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Sun Oct 7 08:27:38 2012 Subject: [odb-users] Queries matching on NVARCHAR fields fail to return records when using "short data" In-Reply-To: References: Message-ID: Hi Oded, Oded Arbel writes: > Thanks for the quick turnaround! Unfortunately we're still working with > 2.0, and at this point I'd rather not upgrade to 2.1 (I may be able to push > to 2.1 later this year). In the mean time, is it possible for you to push > this as a bugfix on 2.0? We normally only do backports under commercial technical support. But I guess we can make an exception this time: http://www.codesynthesis.com/~boris/tmp/odb/libodb-mssql-2.0.2.zip Boris From Davide.Anastasia at qualitycapital.com Mon Oct 8 03:55:57 2012 From: Davide.Anastasia at qualitycapital.com (Davide Anastasia) Date: Mon Oct 8 03:56:13 2012 Subject: [odb-users] ODB and InfiniDB Message-ID: <6989CEDF160F9A42A3F5FF832CBAA72C173A3F@exbe19.nasstar-t1.net> Hi all, I am trying to get ODB working with InfiniDB: as anybody have experience with this database? InfiniDB is a columnar storage engine for MySQL: it does share with MySQL most of its internal operations and it works with MySQL API. However, I am currently experiencing unstable connection to this database, so I wonder whether there is any particular reason why ODB should not work properly with this engine. Have a good start of the week, 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 boris at codesynthesis.com Mon Oct 8 08:13:45 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Mon Oct 8 07:48:46 2012 Subject: [odb-users] ODB and InfiniDB In-Reply-To: <6989CEDF160F9A42A3F5FF832CBAA72C173A3F@exbe19.nasstar-t1.net> References: <6989CEDF160F9A42A3F5FF832CBAA72C173A3F@exbe19.nasstar-t1.net> Message-ID: Hi Davide, Davide Anastasia writes: > I am trying to get ODB working with InfiniDB: as anybody have experience > with this database? No, we haven't tested ODB with this database. > However, I am currently experiencing unstable connection to this > database, so I wonder whether there is any particular reason why ODB > should not work properly with this engine. I cann't think of any. ODB works fine with stock MySQL so it must be something on InfiniDB side. One thing that you may want to look into is connection timeouts and pings. MySQL has a configurable connection inactivity timeout after which it drop the connection. It also allows the client to ping the connection to make sure it is still alive. ODB does that by default to make sure it gives out a valid connection. Boris From boris at codesynthesis.com Mon Oct 8 08:56:16 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Mon Oct 8 08:31:19 2012 Subject: [odb-users] odb compiler assert when db value pragma placed on subclass In-Reply-To: <8EDFC8F388A1E44BB67C9BAA57091F9E285CCB5B@EXMB03.srn.sandia.gov> References: <8EDFC8F388A1E44BB67C9BAA57091F9E285CCB5B@EXMB03.srn.sandia.gov> Message-ID: Hi Sean, Stroud, Sean T writes: > I get an assert from odb on the following program: > > class Bar > { > }; > > #pragma db value > class Foo : public Bar > { > public: > int m_seconds; > }; You've uncovered another corner case bug, thanks! It is now fixed and I can build you a binary if you would like. > However, I was wondering what odb will do once this bug is fixed. Will > the odb compiler support this kind of situation (i.e. db value pragma > on a subclass)? ODB treats this as "transient inheritance". That is, whatever data members are defined in Bar, they will be ignored for database persistence purposes. On the other hand, if you want Bar's state to be saved in the database, then you will need to make it a composite value as well. Both of the above cases support multiple inheritance. Boris From dctomm at gmail.com Mon Oct 8 14:02:22 2012 From: dctomm at gmail.com (Doug Tomm) Date: Mon Oct 8 14:01:00 2012 Subject: [odb-users] commits don't change "on update current timestamp" column Message-ID: ODB version: 2.0.0 MySQL version: 5.1.35 OS: CentOS 5 i have an object model for which i want to store modification times in the database. the table looks something like this: CREATE TABLE `record` ( `update_me` tinyint(4) NOT NULL DEFAULT '0', `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8 and the corresponding data members for the object look like this: #pragma db type("timestamp") column("modified") not_null boost::posix_time::ptime m_modified; and the problem i'm having is that after committing an update to the object, the 'modified' column is never changed. when i manually update the update_me column in a row with an UPDATE statement, the modified time is correctly updated. but i can't seem to cause this to change programmatically. i am using the boost/date-time and boost/date-time/posix-time profiles with the ODB compiler. thanks for any pointers or clues. doug From boris at codesynthesis.com Mon Oct 8 15:30:19 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Mon Oct 8 15:05:15 2012 Subject: [odb-users] commits don't change "on update current timestamp" column In-Reply-To: References: Message-ID: Hi Doug, Doug Tomm writes: > #pragma db type("timestamp") column("modified") not_null > boost::posix_time::ptime m_modified; > > and the problem i'm having is that after committing an update to > the object, the 'modified' column is never changed. when i manually > update the update_me column in a row with an UPDATE statement, the > modified time is correctly updated. This is probably because the UPDATE statement executed by ODB also includes a value for the 'modified' column. One way to prevent ODB from doing this would be to make the member readonly. You can either declare it const: const boost::posix_time::ptime m_modified; Or mark it as readonly: #pragma db type("timestamp") column("modified") not_null readonly boost::posix_time::ptime m_modified; Boris From dctomm at gmail.com Mon Oct 8 15:30:26 2012 From: dctomm at gmail.com (Doug Tomm) Date: Mon Oct 8 15:29:03 2012 Subject: [odb-users] commits don't change "on update current timestamp" column In-Reply-To: References: Message-ID: <0B1C0579-7439-43C2-9ECF-EAD9F74E4399@gmail.com> yes, that was it! using the readonly pragma solved it; i turned on statement tracing to see for myself. many thanks! d On Oct 8, 2012, at 12:30 PM, Boris Kolpackov wrote: > Hi Doug, > > Doug Tomm writes: > >> #pragma db type("timestamp") column("modified") not_null >> boost::posix_time::ptime m_modified; >> >> and the problem i'm having is that after committing an update to >> the object, the 'modified' column is never changed. when i manually >> update the update_me column in a row with an UPDATE statement, the >> modified time is correctly updated. > > This is probably because the UPDATE statement executed by ODB > also includes a value for the 'modified' column. One way to > prevent ODB from doing this would be to make the member > readonly. You can either declare it const: > > const boost::posix_time::ptime m_modified; > > Or mark it as readonly: > > #pragma db type("timestamp") column("modified") not_null readonly > boost::posix_time::ptime m_modified; > > Boris From eric.b.sum at lmco.com Tue Oct 9 17:13:19 2012 From: eric.b.sum at lmco.com (Sum, Eric B) Date: Tue Oct 9 17:12:01 2012 Subject: [odb-users] Type Mapping Question Message-ID: Hi, I am using a sqlite database and am trying to create a custom mapping of my own C++ struct to a "BLOB" type in sqlite. I am following odb-examples/mapping as a guide. I see in this example that in the person class, it has a date member, and the customized traits specialization for the date class allows odb to understand how to map the date member to its specified representation in the database when persisting and how to load the database representation into a date object. My question is will odb handle the case where there is not just one individual date member of the person class but rather a container of it? In other words, if there was std::vector as a member of person, would odb still handle this correctly with the same traits specialization? My guess is yes, but I just want to check. Thanks, Eric From boris at codesynthesis.com Wed Oct 10 05:30:58 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Wed Oct 10 05:05:24 2012 Subject: [odb-users] Type Mapping Question In-Reply-To: References: Message-ID: Hi Eric, Sum, Eric B writes: > My question is will odb handle the case where there is not just one > individual date member of the person class but rather a container > of it? Yes. Boris From chris.richards at yellowfeather.co.uk Wed Oct 10 12:27:15 2012 From: chris.richards at yellowfeather.co.uk (Chris Richards) Date: Wed Oct 10 12:51:21 2012 Subject: [odb-users] Unable to build with static libraries Message-ID: <5075A1E3.4070001@yellowfeather.co.uk> Hi, I've just tried building ODB with static linking and am getting a linker error building the examples. I have downloaded v2.1.0, and run configure and make as below: ./configure --disable-shared make sudo make install I have done this for lidodb, libodb-boost and libodb-mysql. When I try to build the ODB examples with: ./configure --disable-shared --with-database=mysql make I get lots of undefined references to 'mysql_stmt_xxx' methods. Could you let me know how to build against static libraries? BTW This is on CentOS 5, with gcc v4.1.2 and boost 1.46.1 Thanks, Chris From boris at codesynthesis.com Wed Oct 10 13:30:02 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Wed Oct 10 13:04:32 2012 Subject: [odb-users] Unable to build with static libraries In-Reply-To: <5075A1E3.4070001@yellowfeather.co.uk> References: <5075A1E3.4070001@yellowfeather.co.uk> Message-ID: Hi Chris, Chris Richards writes: > When I try to build the ODB examples with: > > ./configure --disable-shared --with-database=mysql > make > > I get lots of undefined references to 'mysql_stmt_xxx' methods. Hm, for some reason libtool doesn't pass dependency libraries when linking statically. I will have to look into this. In the meantime, an easy workaround is to configure examples like this: ./configure --with-database=mysql LDFLAGS=-L/usr/lib/mysql LIBS=-lmysqlclient_r Change /usr/lib/mysql to /usr/lib64/mysql in the above command line if you are using a 64-bit distribution. Boris From chris.richards at yellowfeather.co.uk Thu Oct 11 04:43:28 2012 From: chris.richards at yellowfeather.co.uk (Chris Richards) Date: Thu Oct 11 04:41:49 2012 Subject: [odb-users] Unable to build with static libraries In-Reply-To: References: <5075A1E3.4070001@yellowfeather.co.uk> Message-ID: <507686B0.7060403@yellowfeather.co.uk> Hi Boris, The examples now build OK, but it looks as though they are still using the shared libraries. When I run 'ldd driver' on the hello example I get the following: [chrisr@localhost hello]$ ldd driver linux-gate.so.1 => (0x00e40000) libboost_date_time.so.1.46.1 => not found libboost_system.so.1.46.1 => not found libmysqlclient_r.so.15 => /usr/lib/mysql/libmysqlclient_r.so.15 (0x005a0000) libpthread.so.0 => /lib/libpthread.so.0 (0x00570000) libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x03cc1000) libm.so.6 => /lib/libm.so.6 (0x0053e000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00349000) libc.so.6 => /lib/libc.so.6 (0x003e3000) libcrypt.so.1 => /lib/libcrypt.so.1 (0x03ede000) libnsl.so.1 => /lib/libnsl.so.1 (0x00af4000) libz.so.1 => /usr/lib/libz.so.1 (0x0058b000) libssl.so.6 => /lib/libssl.so.6 (0x0026d000) libcrypto.so.6 => /lib/libcrypto.so.6 (0x00101000) /lib/ld-linux.so.2 (0x003bf000) libgssapi_krb5.so.2 => /usr/lib/libgssapi_krb5.so.2 (0x00ce0000) libkrb5.so.3 => /usr/lib/libkrb5.so.3 (0x00d57000) libcom_err.so.2 => /lib/libcom_err.so.2 (0x00cd0000) libk5crypto.so.3 => /usr/lib/libk5crypto.so.3 (0x00244000) libresolv.so.2 => /lib/libresolv.so.2 (0x00b5b000) libdl.so.2 => /lib/libdl.so.2 (0x00569000) libkrb5support.so.0 => /usr/lib/libkrb5support.so.0 (0x00d4c000) libkeyutils.so.1 => /lib/libkeyutils.so.1 (0x00b56000) libselinux.so.1 => /lib/libselinux.so.1 (0x00ada000) libsepol.so.1 => /lib/libsepol.so.1 (0x00a92000) Do I need to reconfigure and rebuild libodb-mysql with LDFLAGS and LIBS set? Regards, Chris > Boris Kolpackov > 10 October 2012 18:30 > Hi Chris, > > > Hm, for some reason libtool doesn't pass dependency libraries when > linking statically. I will have to look into this. > > In the meantime, an easy workaround is to configure examples like > this: > > ./configure --with-database=mysql LDFLAGS=-L/usr/lib/mysql > LIBS=-lmysqlclient_r > > Change /usr/lib/mysql to /usr/lib64/mysql in the above command line if > you are using a 64-bit distribution. > > Boris > Chris Richards > 10 October 2012 17:27 > Hi, > > I've just tried building ODB with static linking and am getting a > linker error building the examples. I have downloaded v2.1.0, and run > configure and make as below: > > ./configure --disable-shared > make > sudo make install > > I have done this for lidodb, libodb-boost and libodb-mysql. When I try > to build the ODB examples with: > > ./configure --disable-shared --with-database=mysql > make > > I get lots of undefined references to 'mysql_stmt_xxx' methods. > > Could you let me know how to build against static libraries? > > BTW This is on CentOS 5, with gcc v4.1.2 and boost 1.46.1 > > > Thanks, > Chris From chris.richards at yellowfeather.co.uk Thu Oct 11 04:51:33 2012 From: chris.richards at yellowfeather.co.uk (Chris Richards) Date: Thu Oct 11 04:49:51 2012 Subject: [odb-users] Unable to build with static libraries In-Reply-To: <507686B0.7060403@yellowfeather.co.uk> References: <5075A1E3.4070001@yellowfeather.co.uk> <507686B0.7060403@yellowfeather.co.uk> Message-ID: <50768895.9090207@yellowfeather.co.uk> Hi Boris, I should point out that I would like to link against the static libraries for Boost and MySQL. Chris > Chris Richards > 11 October 2012 09:43 > Hi Boris, > > The examples now build OK, but it looks as though they are still using > the shared libraries. When I run 'ldd driver' on the hello example I > get the following: > > [chrisr@localhost hello]$ ldd driver > linux-gate.so.1 => (0x00e40000) > libboost_date_time.so.1.46.1 => not found > libboost_system.so.1.46.1 => not found > libmysqlclient_r.so.15 => > /usr/lib/mysql/libmysqlclient_r.so.15 (0x005a0000) > libpthread.so.0 => /lib/libpthread.so.0 (0x00570000) > libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x03cc1000) > libm.so.6 => /lib/libm.so.6 (0x0053e000) > libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00349000) > libc.so.6 => /lib/libc.so.6 (0x003e3000) > libcrypt.so.1 => /lib/libcrypt.so.1 (0x03ede000) > libnsl.so.1 => /lib/libnsl.so.1 (0x00af4000) > libz.so.1 => /usr/lib/libz.so.1 (0x0058b000) > libssl.so.6 => /lib/libssl.so.6 (0x0026d000) > libcrypto.so.6 => /lib/libcrypto.so.6 (0x00101000) > /lib/ld-linux.so.2 (0x003bf000) > libgssapi_krb5.so.2 => /usr/lib/libgssapi_krb5.so.2 (0x00ce0000) > libkrb5.so.3 => /usr/lib/libkrb5.so.3 (0x00d57000) > libcom_err.so.2 => /lib/libcom_err.so.2 (0x00cd0000) > libk5crypto.so.3 => /usr/lib/libk5crypto.so.3 (0x00244000) > libresolv.so.2 => /lib/libresolv.so.2 (0x00b5b000) > libdl.so.2 => /lib/libdl.so.2 (0x00569000) > libkrb5support.so.0 => /usr/lib/libkrb5support.so.0 (0x00d4c000) > libkeyutils.so.1 => /lib/libkeyutils.so.1 (0x00b56000) > libselinux.so.1 => /lib/libselinux.so.1 (0x00ada000) > libsepol.so.1 => /lib/libsepol.so.1 (0x00a92000) > > > Do I need to reconfigure and rebuild libodb-mysql with LDFLAGS and > LIBS set? > > Regards, > Chris > > Boris Kolpackov > 10 October 2012 18:30 > Hi Chris, > > > Hm, for some reason libtool doesn't pass dependency libraries when > linking statically. I will have to look into this. > > In the meantime, an easy workaround is to configure examples like > this: > > ./configure --with-database=mysql LDFLAGS=-L/usr/lib/mysql > LIBS=-lmysqlclient_r > > Change /usr/lib/mysql to /usr/lib64/mysql in the above command line if > you are using a 64-bit distribution. > > Boris > Chris Richards > 10 October 2012 17:27 > Hi, > > I've just tried building ODB with static linking and am getting a > linker error building the examples. I have downloaded v2.1.0, and run > configure and make as below: > > ./configure --disable-shared > make > sudo make install > > I have done this for lidodb, libodb-boost and libodb-mysql. When I try > to build the ODB examples with: > > ./configure --disable-shared --with-database=mysql > make > > I get lots of undefined references to 'mysql_stmt_xxx' methods. > > Could you let me know how to build against static libraries? > > BTW This is on CentOS 5, with gcc v4.1.2 and boost 1.46.1 > > > Thanks, > Chris From boris at codesynthesis.com Thu Oct 11 05:55:49 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Thu Oct 11 05:29:57 2012 Subject: [odb-users] Unable to build with static libraries In-Reply-To: <50768895.9090207@yellowfeather.co.uk> References: <5075A1E3.4070001@yellowfeather.co.uk> <507686B0.7060403@yellowfeather.co.uk> <50768895.9090207@yellowfeather.co.uk> Message-ID: Hi Chris, Chris Richards writes: > I should point out that I would like to link against the static > libraries for Boost and MySQL. The autotools build system doesn't really support such selective static linking (i.e., some libraries should be linked statically while other dynamically). In fact, with some linkers you won't even be able to do that unless a static library is the only option. With GNU ld, you can use the -Bstatic and -Bdynamic options to specify which libraries should be linked statically and which dynamically. Here is how you can build the hello example to link to all the ODB, Boost, and MySQL libraries statically and to everything else dynamically: odb -d mysql --generate-query --generate-schema person.hxx g++ -c -DDATABASE_MYSQL person-odb.cxx driver.cxx g++ -o driver driver.o person-odb.o -Wl,-Bstatic -lodb-mysql -lodb -lmysqlclient_r -Wl,-Bdynamic -lpthread -lz In your case (CentOS/RH/Fedora), you will also need to add -L/usr/lib/mysql (or -L/usr/lib64/mysql) to the last command. Boris From boris at codesynthesis.com Tue Oct 16 12:25:20 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Tue Oct 16 11:57:51 2012 Subject: [odb-users] Custom C++ to Database Type Mapping in ODB Message-ID: Hi, I just published a comprehensive, step-by-step guide to adding persistence support for a custom value type. Specifically, it considers cases of simple (single-column) vs composite (multi-column) value types, our own vs third- party types, as well as, for simple value types, mapping to core vs extended database types: http://www.codesynthesis.com/~boris/blog/2012/10/16/custom-cxx-to-database-type-mapping-in-odb/ Boris From boris at codesynthesis.com Fri Oct 19 09:19:20 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Fri Oct 19 08:51:01 2012 Subject: [odb-users] Prepared statement feature In-Reply-To: References: <3233D27CC5658E4598557F8521F6B07E2146550D06@RIC-MS01.abw.int> <3233D27CC5658E4598557F8521F6B07E2146550D92@RIC-MS01.abw.int> <3233D27CC5658E4598557F8521F6B07E2146550E4E@RIC-MS01.abw.int> <3233D27CC5658E4598557F8521F6B07E2146550E68@RIC-MS01.abw.int> <3233D27CC5658E4598557F8521F6B07E2146550F05@RIC-MS01.abw.int> Message-ID: Hi Paul, Ok, the prepared query feature is implemented and I think the interface turned out to be quite clean. If you would like to read the documentation in the meantime, I've published the updated manual here: http://www.codesynthesis.com/~boris/tmp/odb/manual.xhtml#4.5 Let me know when you are ready to test this and I will package you a snapshot. Boris From pstath at axxcelera.com Fri Oct 19 12:49:35 2012 From: pstath at axxcelera.com (Stath, Paul) Date: Fri Oct 19 12:46:47 2012 Subject: [odb-users] Prepared statement feature In-Reply-To: References: <3233D27CC5658E4598557F8521F6B07E2146550D06@RIC-MS01.abw.int> <3233D27CC5658E4598557F8521F6B07E2146550D92@RIC-MS01.abw.int> <3233D27CC5658E4598557F8521F6B07E2146550E4E@RIC-MS01.abw.int> <3233D27CC5658E4598557F8521F6B07E2146550E68@RIC-MS01.abw.int> <3233D27CC5658E4598557F8521F6B07E2146550F05@RIC-MS01.abw.int> Message-ID: <3233D27CC5658E4598557F8521F6B07E21536C3CE3@RIC-MS01.abw.int> Boris -- The documentation looks good. I think that being able to register a factory method elegantly solves the only objection I had about your design. I'll be happy to test this, but probably can't put any time towards it until early Nov. I'm building ODB from the release source tar-ball. I would be happy to simply use git to download the source, just let me know the branch name Where the prepared query work can be found. Thanks. -- Paul > -----Original Message----- > From: Boris Kolpackov [mailto:boris@codesynthesis.com] > Sent: Friday, October 19, 2012 9:19 AM > To: Stath, Paul > Cc: odb-users@codesynthesis.com > Subject: Re: [odb-users] Prepared statement feature > > Hi Paul, > > Ok, the prepared query feature is implemented and I think the interface > turned out to be quite clean. If you would like to read the > documentation > in the meantime, I've published the updated manual here: > > http://www.codesynthesis.com/~boris/tmp/odb/manual.xhtml#4.5 > > Let me know when you are ready to test this and I will package you > a snapshot. > > Boris From pstath at axxcelera.com Fri Oct 19 13:03:11 2012 From: pstath at axxcelera.com (Stath, Paul) Date: Fri Oct 19 13:00:20 2012 Subject: [odb-users] Enable/Disable query support via pragma In-Reply-To: <201210191600.q9JG03IR011146@codesynthesis.com> References: <201210191600.q9JG03IR011146@codesynthesis.com> Message-ID: <3233D27CC5658E4598557F8521F6B07E21536C3CE4@RIC-MS01.abw.int> Boris -- It would be nice if there was an ODB pragma which could be used to enable/disable the generation of query support code for a persistent class. This would be similar to the "db session" pragma that can be used to enable/disable session support on a per object basis. In the rather simplistic data model for my project, I have two objects that are retrieved using a query, while the remaining objects are always loaded by primary key. Without a pragma, I currently run the ODB compiler twice, once for the persistent object that do not require query support, and a second time for the two classes that do need query support. -- Paul Stath From SawZ at meaust.meap.com Sun Oct 21 20:41:14 2012 From: SawZ at meaust.meap.com (Saw, Zach) Date: Mon Oct 22 07:46:09 2012 Subject: [odb-users] Building ODB compiler on Windows Message-ID: Hi, According to INSTALL file, building the ODB compiler on Windows requires custom procedures. We'd like to build it ourselves under Windows. Could you provide us with the procedures? Thanks in advance. Regards, Zach __________________________________________________________________________________________________________________________________________________ The information contained in this email and any attachment/s may be privileged and confidential and are intended for the recipient designated only. If you have received this email in error, do not use, disseminate, distribute, or copy this email and any attachment/s. However, please notify us either on telephone +612 9684 7777 or the sender via return e-mail and delete all copies of this transmission together with any attachment/s. Mitsubishi Electric Australia Pty. Ltd. has implemented anti-virus software, and whilst all care is taken, it is the recipient's responsibility to ensure that any attachments are scanned for viruses prior to use. From boris at codesynthesis.com Mon Oct 22 08:41:39 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Mon Oct 22 08:12:26 2012 Subject: [odb-users] Enable/Disable query support via pragma In-Reply-To: <3233D27CC5658E4598557F8521F6B07E21536C3CE4@RIC-MS01.abw.int> References: <201210191600.q9JG03IR011146@codesynthesis.com> <3233D27CC5658E4598557F8521F6B07E21536C3CE4@RIC-MS01.abw.int> Message-ID: Hi Paul, Stath, Paul writes: > It would be nice if there was an ODB pragma which could be used to > enable/disable the generation of query support code for a persistent > class. This would be similar to the "db session" pragma that can be > used to enable/disable session support on a per object basis. Added to the TODO list for the next release. The minor issue here is that object pointers and views require query support in objects to which they point to or on which they are based. We will be able to diagnose this if both are defined in the same header but not if they are defined in separate. But I guess we already have this problem with object pointers, so there is nothing really new. Thanks for the suggestion! Boris From boris at codesynthesis.com Mon Oct 22 08:49:21 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Mon Oct 22 08:20:10 2012 Subject: [odb-users] Building ODB compiler on Windows In-Reply-To: References: Message-ID: Hi Zach, Saw, Zach writes: > According to INSTALL file, building the ODB compiler on Windows requires > custom procedures. We'd like to build it ourselves under Windows. Could > you provide us with the procedures? The following earlier post provides an overview of the process and points to further resources: http://www.codesynthesis.com/pipermail/odb-users/2012-July/000673.html Boris From jneuhart at tlirr.com Wed Oct 24 13:21:24 2012 From: jneuhart at tlirr.com (Jordan J. Neuhart) Date: Wed Oct 24 13:23:18 2012 Subject: [odb-users] Using ODB with qmake on Windows Message-ID: <681FA42AB546F84C8CFDFCAA6D89A62803CAB72B@husker.tlirr.local> Greetings, I'm new to odb and I would like to use it on a Qt project that I am working on. I'd like to be able to run the odb compiler as a pre-compilation step in qmake, but I can't seem to get it to work. Does anyone have any experience with this and would be willing to share their solution? Sincerely, Jordan Neuhart Database Administrator T-L Irrigation Co. P.O. Box 1047 151 East Hwy 6 & AB Road Hastings, NE 68902-1047 office: 402-462-4128 ext. 264 800-330-4264 ext. 264 cell: 402-217-1377 email: jjn@tlirr.com From boris at codesynthesis.com Thu Oct 25 05:07:30 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Thu Oct 25 04:37:37 2012 Subject: [odb-users] Using ODB with qmake on Windows In-Reply-To: <681FA42AB546F84C8CFDFCAA6D89A62803CAB72B@husker.tlirr.local> References: <681FA42AB546F84C8CFDFCAA6D89A62803CAB72B@husker.tlirr.local> Message-ID: Hi Jordan, Jordan J. Neuhart writes: > I'm new to odb and I would like to use it on a Qt project that I am > working on. I'd like to be able to run the odb compiler as a > pre-compilation step in qmake, but I can't seem to get it to work. Does > anyone have any experience with this and would be willing to share their > solution? Are you using qmake as part of the QtCreator? What is your target toolchain (i.e., VC++ or MinGW)? There is a page on the Wiki that describes how to setup ODB with QtCreator on Linux: http://wiki.codesynthesis.com/Using_ODB_with_Qt_Creator_on_Linux It includes a section of qmake .pro file that contains the rules for compiling headers with ODB. I think it should work on Windows with possibly two modifications: 1. The 'odb.commands = ...' line assumes that the ODB compiler executable is in the PATH. If that's not the case, then you will need to change it to something like this: odb.commands = C:\odb-X.Y.Z\bin\odb.exe ... 2. The 'odbh.commands = @true' line needs to be changed to something equivalent for the Windows cmd shell: odbh.commands = rem Can you try this and let us know if it works? Boris From jneuhart at tlirr.com Thu Oct 25 11:27:20 2012 From: jneuhart at tlirr.com (Jordan J. Neuhart) Date: Thu Oct 25 12:11:39 2012 Subject: [odb-users] Using ODB with qmake on Windows Message-ID: <681FA42AB546F84C8CFDFCAA6D89A62803CAB83C@husker.tlirr.local> Boris, I just realized that I forgot to answer your question. I am using qmake as part of QtCreator and my target toolchain is VC++, and I am using Qt 4.8.3. I am also using sqlite as my database. I followed the directions on the link you provided and gave your suggestion a try, modifying for sqlite of course. When I build the project in QtCreator, I keep getting the following error: ------------------------------------------------------------------------ ---------------------------------- jom 1.0.6 - empower your cores Error: Invalid macro invocation found in C:\Users\jjn\test\Makefile.Release line 102 command failed with exit code 2 09:08:59: The process "C:\QtSDK\QtCreator\bin\jom.exe" exited with code 2. Error while building project test (target: Desktop) When executing build step 'Make' ------------------------------------------------------------------------ --------------------------------- I have attached my .pro file. The problem seems to stem from the line: odb.input = ODB_FILES For some reason, the build process is interpreting ODB_FILES as a macro. If I change the line to: odb.input = $$ODB_FILES Then the build gets a little farther, but stops with this error: ------------------------------------------------------------------------ ---------------------------------- Error: dependent 'employee-odb.cxx' does not exist. command failed with exit code 2 09:12:14: The process "C:\QtSDK\QtCreator\bin\jom.exe" exited with code 2. Error while building project test (target: Desktop) When executing build step 'Make' ------------------------------------------------------------------------ ---------------------------------- Also, if I then change the line: odbh.input = ODB_FILES to odbh.input = $$ODB_FILES then I get a little farther, but still fail with the following VC++ compiler error: C:\Users\jjn\test\driver.cxx:15: error: C1083: Cannot open include file: 'employee-odb.hxx': No such file or directory So it seems that the odb header file is not getting compiled for some reason. The odb compiler is in my PATH variable, and I have the "odb-sqlite.lib", "odb-qt.lib", and "odb.lib" libraries sitting at the same level as my .hxx and .cxx files in the folder hierarchy. I think I have all of the headers in my INCLUDEPATH as well. Any suggestions for what to try next? Also, what is the purpose of the 'odbh' extra compiler that just issues the 'rem' command? Sincerely, Jordan -----Original Message----- From: Boris Kolpackov [mailto:boris@codesynthesis.com] Sent: Thursday, October 25, 2012 4:08 AM To: Jordan J. Neuhart Cc: odb-users@codesynthesis.com Subject: Re: [odb-users] Using ODB with qmake on Windows Hi Jordan, Jordan J. Neuhart writes: > I'm new to odb and I would like to use it on a Qt project that I am > working on. I'd like to be able to run the odb compiler as a > pre-compilation step in qmake, but I can't seem to get it to work. > Does anyone have any experience with this and would be willing to > share their solution? Are you using qmake as part of the QtCreator? What is your target toolchain (i.e., VC++ or MinGW)? There is a page on the Wiki that describes how to setup ODB with QtCreator on Linux: http://wiki.codesynthesis.com/Using_ODB_with_Qt_Creator_on_Linux It includes a section of qmake .pro file that contains the rules for compiling headers with ODB. I think it should work on Windows with possibly two modifications: 1. The 'odb.commands = ...' line assumes that the ODB compiler executable is in the PATH. If that's not the case, then you will need to change it to something like this: odb.commands = C:\odb-X.Y.Z\bin\odb.exe ... 2. The 'odbh.commands = @true' line needs to be changed to something equivalent for the Windows cmd shell: odbh.commands = rem Can you try this and let us know if it works? Boris -------------- next part -------------- A non-text attachment was scrubbed... Name: test.pro Type: application/octet-stream Size: 1745 bytes Desc: test.pro Url : http://codesynthesis.com/pipermail/odb-users/attachments/20121025/5e3d82a2/test.obj From boris at codesynthesis.com Thu Oct 25 12:50:25 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Thu Oct 25 12:20:13 2012 Subject: [odb-users] Using ODB with qmake on Windows In-Reply-To: <681FA42AB546F84C8CFDFCAA6D89A62803CAB83C@husker.tlirr.local> References: <681FA42AB546F84C8CFDFCAA6D89A62803CAB83C@husker.tlirr.local> Message-ID: <20121025165025.GA10645@onega.codesynthesis.com> Hi Jordan, Jordan J. Neuhart writes: > The problem seems to stem from the line: > > odb.input = ODB_FILES > > For some reason, the build process is interpreting ODB_FILES as a macro. > If I change the line to: > > odb.input = $$ODB_FILES > > Then the build gets a little farther, but stops with this error: I am pretty sure it should be just ODB_FILES. The idea for the rules was taken from this thread: http://www.qtcentre.org/threads/47670-qmake-Custom-code-generation-that-produces-both-header-and-cpp-files Maybe you can try that sample .pro file and see if it works. I will also try to find some time tomorrow to try this myself. > C:\Users\jjn\test\driver.cxx:15: error: C1083: Cannot open include file: > 'employee-odb.hxx': No such file or directory > > So it seems that the odb header file is not getting compiled for some > reason. I think it is not being compiled because of your change to $$ODB_FILES. > Also, what is the purpose of the 'odbh' extra compiler that just > issues the 'rem' command? It makes sure that the *-odb.hxx file is generated before any file that includes it is compiled. That post that I mentioned above explains this in more detail. Let us know if you manage to make any progress on this. Boris From alexander.prokhorov at datadvance.net Fri Oct 26 04:40:46 2012 From: alexander.prokhorov at datadvance.net (Alexander A. Prokhorov) Date: Fri Oct 26 08:20:57 2012 Subject: [odb-users] schema validation Message-ID: <508A4C8E.4060201@datadvance.net> Dear all, Here is the deal - I use odb to maintain a SQL-based document format for a standalone application, with SQLite backend, of course. Application is quite agile, schema often experiences minor changes, and it's very desirable to perform a meaningful schema check every time I open a new SQLite file. Otherwise, as I understand, user may encounter some database-related exceptions/errors in runtime, which is highly undesirable. So, the question is, is there any recommended way to match current schema (in odb::schema_catalog, I suppose) to be subset of schema in some database? Or I should implement some custom version system? Thanks in advance. -- Alexander A. Prokhorov Head of Software Development DATADVANCE Mob. +7 903 6249039 alexander.prokhorov@datadvance.net prokher@datadvance.net This message may contain confidential information constituting a trade secret of DATADVANCE. Any distribution, use or copying of the information contained in this message is ineligible except under the internal regulations of DATADVANCE and may entail liability in accordance with the current legislation of the Russian Federation. If you have received this message by mistake please immediately inform me of it. Thank you! From boris at codesynthesis.com Fri Oct 26 09:02:40 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Fri Oct 26 08:32:15 2012 Subject: [odb-users] schema validation In-Reply-To: <508A4C8E.4060201@datadvance.net> References: <508A4C8E.4060201@datadvance.net> Message-ID: Hi Alexander, Alexander A. Prokhorov writes: > Application is quite agile, schema often experiences minor changes, and > it's very desirable to perform a meaningful schema check every time I > open a new SQLite file. > > Otherwise, as I understand, user may encounter some database-related > exceptions/errors in runtime, which is highly undesirable. > > So, the question is, is there any recommended way to match current > schema (in odb::schema_catalog, I suppose) to be subset of schema in > some database? There is no automatic database schema versioning in ODB yet (we may add something like this in the future as part of the schema evolution work). In the meantime, it should be quite easy to implement this by storing the version of the schema in the database itself (this also seems to be the recommended way to do schema versioning). You could even create a small persistent class to assist with this, something along these lines: #pragma db object struct schema_version { schema_version () {} schema_version (unsigned short mj, unsigned short mn) : id (1), major (mj), minor (mn) #pragma db id unsigned short id; unsigned short major; unsigned short minor }; Then when creating a new database, you would also store the version: schema_version sv (2, 3); db.persis (sv); And when opening an existing database, you would check the version: schema_version sv; db.load (1, sv); if (sv.major < 2) { // Incompatible schema version. } Boris From alexander.prokhorov at datadvance.net Fri Oct 26 08:37:21 2012 From: alexander.prokhorov at datadvance.net (Alexander A. Prokhorov) Date: Fri Oct 26 08:35:48 2012 Subject: [odb-users] schema validation In-Reply-To: References: <508A4C8E.4060201@datadvance.net> Message-ID: <508A8401.5080901@datadvance.net> Thanks! On 26.10.2012 17:02, Boris Kolpackov wrote: > Hi Alexander, > > Alexander A. Prokhorov writes: > >> Application is quite agile, schema often experiences minor changes, and >> it's very desirable to perform a meaningful schema check every time I >> open a new SQLite file. >> >> Otherwise, as I understand, user may encounter some database-related >> exceptions/errors in runtime, which is highly undesirable. >> >> So, the question is, is there any recommended way to match current >> schema (in odb::schema_catalog, I suppose) to be subset of schema in >> some database? > There is no automatic database schema versioning in ODB yet (we may > add something like this in the future as part of the schema evolution > work). > > In the meantime, it should be quite easy to implement this by storing > the version of the schema in the database itself (this also seems to > be the recommended way to do schema versioning). You could even create > a small persistent class to assist with this, something along these > lines: > > #pragma db object > struct schema_version > { > schema_version () {} > schema_version (unsigned short mj, unsigned short mn) > : id (1), major (mj), minor (mn) > > #pragma db id > unsigned short id; > > unsigned short major; > unsigned short minor > }; > > Then when creating a new database, you would also store the version: > > schema_version sv (2, 3); > db.persis (sv); > > And when opening an existing database, you would check the version: > > schema_version sv; > db.load (1, sv); > > if (sv.major < 2) > { > // Incompatible schema version. > } > > Boris -- Alexander A. Prokhorov Head of Software Development DATADVANCE Mob. +7 903 6249039 alexander.prokhorov@datadvance.net prokher@datadvance.net This message may contain confidential information constituting a trade secret of DATADVANCE. Any distribution, use or copying of the information contained in this message is ineligible except under the internal regulations of DATADVANCE and may entail liability in accordance with the current legislation of the Russian Federation. If you have received this message by mistake please immediately inform me of it. Thank you! From boris at codesynthesis.com Fri Oct 26 10:48:36 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Fri Oct 26 10:18:09 2012 Subject: [odb-users] Using ODB with qmake on Windows In-Reply-To: <20121025165025.GA10645@onega.codesynthesis.com> References: <681FA42AB546F84C8CFDFCAA6D89A62803CAB83C@husker.tlirr.local> <20121025165025.GA10645@onega.codesynthesis.com> Message-ID: Hi Jordan, Ok, I did some debugging and the culprit turned out to be this line: odb.depends = ${ODB_FILES} Instead it should read: odb.depends = $$ODB_FILES With this change I got as far as compiling the generated code. Can you give this a try and let us know if it works for you? And if it does, then a working test.pro file would be much appreciated. Boris From candy.chiu.ad at gmail.com Fri Oct 26 13:48:05 2012 From: candy.chiu.ad at gmail.com (Candy Chiu) Date: Fri Oct 26 13:44:18 2012 Subject: [odb-users] libodb-mssql wstring possible memory issue Message-ID: Boris, I am going through how wchar_t strings are handled. In odb/mssql/traits.hxx, line 803, template <> struct LIBODB_MSSQL_EXPORT default_value_traits { static void set_image (ucs2_char* b, std::size_t c, std::size_t& n, bool& is_null, const std::wstring& v) { is_null = false; n = v.size (); if (n > c) // <------------- if (n * sizeof(ucs2_char) > c) ... n = c; functions::assign (b, v.c_str (), n); } }; Suppose the capacity of the buffer is the same as the length of the string (n=c>0). In traits.hxx, line 775, static void assign (ucs2_char* b, const wchar_t* s, std::size_t n) { if (n != 0) std::memcpy (b, s, n * sizeof (ucs2_char)); } memcpy copys 2n bytes of data into a n byte buffer. From boris at codesynthesis.com Fri Oct 26 14:48:39 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Fri Oct 26 14:18:06 2012 Subject: [odb-users] libodb-mssql wstring possible memory issue In-Reply-To: References: Message-ID: Hi Candy, Candy Chiu writes: > if (n > c) // <------------- if (n * sizeof(ucs2_char) > c) ... The buffer capacity (c) here is in 2-byte characters, not bytes. Boris From jneuhart at tlirr.com Fri Oct 26 17:34:18 2012 From: jneuhart at tlirr.com (Jordan J. Neuhart) Date: Fri Oct 26 23:31:35 2012 Subject: [odb-users] Using ODB with qmake on Windows In-Reply-To: References: <681FA42AB546F84C8CFDFCAA6D89A62803CAB83C@husker.tlirr.local> <20121025165025.GA10645@onega.codesynthesis.com> Message-ID: <681FA42AB546F84C8CFDFCAA6D89A62803CABA2C@husker.tlirr.local> Boris, I made the change, and I got as far as you did. The project builds find now, and the generated code is built, but the application crashes when I attempt to run it from within Qt creator. When I have more time, I will do some debugging and see if I can find the cause. Thanks, Jordan -----Original Message----- From: Boris Kolpackov [mailto:boris@codesynthesis.com] Sent: Friday, October 26, 2012 9:49 AM To: Jordan J. Neuhart Cc: odb-users@codesynthesis.com Subject: Re: [odb-users] Using ODB with qmake on Windows Hi Jordan, Ok, I did some debugging and the culprit turned out to be this line: odb.depends = ${ODB_FILES} Instead it should read: odb.depends = $$ODB_FILES With this change I got as far as compiling the generated code. Can you give this a try and let us know if it works for you? And if it does, then a working test.pro file would be much appreciated. Boris From jneuhart at tlirr.com Fri Oct 26 18:12:49 2012 From: jneuhart at tlirr.com (Jordan J. Neuhart) Date: Fri Oct 26 23:31:36 2012 Subject: [odb-users] Using ODB with qmake on Windows In-Reply-To: References: <681FA42AB546F84C8CFDFCAA6D89A62803CAB83C@husker.tlirr.local> <20121025165025.GA10645@onega.codesynthesis.com> Message-ID: <681FA42AB546F84C8CFDFCAA6D89A62803CABA3A@husker.tlirr.local> Boris, Nevermind, I didn't realize that those were just import libraries. My bad, I was thinking that they were statically linked. Once I moved the dlls over into the Release folder with the .exe, all was well. Is it possible to compile the odb libraries as static libraries? I have attached my working .pro file for you. In summary, the only changes that were made were: Changing ${ODB_FILES} to $$ODB_FILES and changing the suppress unknown pragmas flag to -wd4068 to suppress pragma warnings for MSVC. Thanks again, Jordan -----Original Message----- From: Boris Kolpackov [mailto:boris@codesynthesis.com] Sent: Friday, October 26, 2012 9:49 AM To: Jordan J. Neuhart Cc: odb-users@codesynthesis.com Subject: Re: [odb-users] Using ODB with qmake on Windows Hi Jordan, Ok, I did some debugging and the culprit turned out to be this line: odb.depends = ${ODB_FILES} Instead it should read: odb.depends = $$ODB_FILES With this change I got as far as compiling the generated code. Can you give this a try and let us know if it works for you? And if it does, then a working test.pro file would be much appreciated. Boris -------------- next part -------------- A non-text attachment was scrubbed... Name: test.pro Type: application/octet-stream Size: 1746 bytes Desc: test.pro Url : http://codesynthesis.com/pipermail/odb-users/attachments/20121026/aac44266/test.obj From boris at codesynthesis.com Mon Oct 29 10:53:43 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Mon Oct 29 10:22:21 2012 Subject: [odb-users] Using ODB with qmake on Windows In-Reply-To: <681FA42AB546F84C8CFDFCAA6D89A62803CABA3A@husker.tlirr.local> References: <681FA42AB546F84C8CFDFCAA6D89A62803CAB83C@husker.tlirr.local> <20121025165025.GA10645@onega.codesynthesis.com> <681FA42AB546F84C8CFDFCAA6D89A62803CABA3A@husker.tlirr.local> Message-ID: Hi Jordan, Jordan J. Neuhart writes: > Is it possible to compile the odb libraries as static libraries? Not at the moment but this is on our TODO list. Unfortunately, it is not as easy as simply adding the necessary configurations to VC++ project files. libodb and some of the other runtimes use DllMain() to perform some once-off initializations which we will have to figure out how to do in a different way. Probably static initialization will work in this case but we need to make sure. > I have attached my working .pro file for you. In summary, the only > changes that were made were: > > Changing ${ODB_FILES} to $$ODB_FILES > > and > > changing the suppress unknown pragmas flag to -wd4068 to suppress pragma > warnings for MSVC. Great, thanks for sharing this. The first change (${ODB_FILES}) was actually necessary even for Linux. So it's good to know that the same rules work pretty much unchanged for both generated GNU makefiles and Nmake makefiles. Boris From boris at codesynthesis.com Mon Oct 29 11:03:38 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Mon Oct 29 10:32:14 2012 Subject: [odb-users] ODB 2.2.0.a1 available Message-ID: Hi, The first alpha version for the upcoming ODB 2.2.0 is now available. The NEWS file entries so far are: * Static multi-database support. It allows an application to simultaneously work with multiple database systems using their static interfaces (i.e., odb::::database instead of odb::database). * Support for prepared queries. Prepared queries are a thin wrapper around the underlying database system's prepared statements functionality. They provide a way to perform potentially expensive query preparations tasks only once and then executing the query multiple time. For more information, refer to Section 4.5, "Prepared Queries" in the ODB manual as well as the 'prepared' example in the odb-examples package. * Support for early connection release. Now the database connection is released when commit()/rollback() is called rather than when the transaction instance goes out of scope. We are still working on the dynamic multi-database support as well as the documentation for both static and dynamic. Below is a quick guide to using the static support. ========================================================================== As an example, let's say we want to use both PostgreSQL and SQLite in our application. To access these two databases with ODB we will need to generate (a) common database support code, (b) PostgreSQL support code, and (c) SQLite support code: odb -m static -d common -q person.hxx odb -m static -d pgsql -q -s person.hxx odb -m static -d sqlite -q -s person.hxx Note the -m (short for --multi-database) option which enables the multi- database support. We could have also used a single invocation of the ODB compiler: odb -m static -d common -d pgsql -d sqlite -q -s person.hxx The above commands (either version) will produce the following set of files: person-odb.?xx - common code person-odb-pgsql.?xx - Postgres-specific code person-odb-sqlite.?xx - SQLite-specific code person-pgsql.sql - database schema for Postgres (for SQLite by default the schema is embedded in person-odb-sqlite.cxx) In our own code, compared to single-database support, we will need to do the following two things differently: 1. We will need to include person-odb-{pgsql,sqlite}.hxx instead of person-odb.hxx. 2. We will need to use the static, database-specific interface instead of the common, database-independent one. For example, we will need to use odb::pgsql::database instead of odb::database, etc., when working with objects stored in Postgres. Here is an example: #include #include #include #include #include "person.hxx" #include "person-odb-pgsql.hxx" #include "person-odb-sqlite.hxx" namespace pg = odb::pgsql; namespace sl = odb::sqlite; int main () { pg::database pdb ("boris", "secret", "test_db"); sl::database sdb ("test.db"); person p1 (...); person p2 (...); // Postgres transaction. // { pg::transaction t (pdb.begin ()); pdb.persist (p1); t.commit (); } // SQLite transaction. // { sl::transaction t (sdb.begin ()); sdb.persist (p2); t.commit (); } // Postgres query transaction. // { typedef pg::query query; typedef odb::result result; // Note: odb:: , not pg:: . pg::transaction t (pdb.begin ()); result r (pdb.query (query::age < 30)); t.commit (); } } Note that odb::result is always database-independent (i.e., there is no odb::pgsql::result class template). It is also possible to make one of the databases the default database so that it can be accessed via the common interface, just like with the single-database support. For that we use the --default-database option: odb -m static -d common -d pgsql -d sqlite --default-database pgsql \ -q -s person.hxx With multi-database support it is now possible to restrict ODB pragmas to apply only to specific databases. For example: #pragma db object class person { ... #pragma db pgsql:type("VARCHAR(128)") sqlite:type("TEXT") std::string name_; unsigned short age_; #pragma db pgsql index member(age_) }; The first example shows a database prefix (e.g., pgsql:) that only applies to the following specifier. The second example shows the database prefix that applies to the whole pragma. In this case the database name must immediately follow the 'db' keyword. Similar to pragmas, ODB compiler options that determine the kind of output (e.g., --schema-format) or alter the output itself (e.g., prologue and epilogue options) can now be prefixed with the database name. For example: --odb-file-suffix common:-odb-common ========================================================================== This pre-release is available from: http://www.codesynthesis.com/download/odb/pre-release/ The SHA1 sums for all the files in this pre-release are provided at the end of the email. Testing and feedback are much appreciated. Enjoy, Boris 3247f50afef3bff8cf33765ef0157246d9ffaef8 libodb-2.2.0.a1.tar.bz2 7b4e80987dff77e6fa9ad58ecaf86b09bfd15389 libodb-2.2.0.a1.tar.gz 1ace5fddcac763e3bba532486e1ac0be24f82d48 libodb-2.2.0.a1.zip 61ca1acb08b3d857323217c38d1d459de9001e28 libodb-mssql-2.2.0.a1.tar.bz2 b44caa46f50a998235cb100e8413edfddabad80d libodb-mssql-2.2.0.a1.tar.gz d481a26fe34e7db9aa34b5a0f26e07d72cb20c7d libodb-mssql-2.2.0.a1.zip fcd6e2a956d02c4b0ae499b12937e1d79f9d8dd7 libodb-mysql-2.2.0.a1.tar.bz2 3007aec103e3f02d4269e6772a1038ab78c7be87 libodb-mysql-2.2.0.a1.tar.gz a8d3768435d3939bf6c4ce49cdd9ac72ec9eb39c libodb-mysql-2.2.0.a1.zip 4aa77014ebe31af946d52ff137cce6af128fc2d9 libodb-oracle-2.2.0.a1.tar.bz2 75ea118e5c26098330d43d30034fe1a203f940bd libodb-oracle-2.2.0.a1.tar.gz 843068a5310bd330a753159959e4fedf054f3737 libodb-oracle-2.2.0.a1.zip f65ac2602597d2eaafd618d2132e277afa4c0322 libodb-pgsql-2.2.0.a1.tar.bz2 d23dec3420104c8a4ae8466b731dd5bd9f216360 libodb-pgsql-2.2.0.a1.tar.gz 78d186ea49321b877a3e136a07c97abff450375b libodb-pgsql-2.2.0.a1.zip eee8de6b3a689eacaa851755aea83ec29f3fa12e libodb-qt-2.2.0.a1.tar.bz2 ee69ef8c777732656958457032aaa7d5dec5a05c libodb-qt-2.2.0.a1.tar.gz e0e16e6e973f1943ea638d3d8982d98370dfe6ef libodb-qt-2.2.0.a1.zip 8f7982cd14d0aaf69a328e664e6207bfc7c2a2bd libodb-sqlite-2.2.0.a1.tar.bz2 ebe704c17e2182bd41352206e61d078e935bf7bb libodb-sqlite-2.2.0.a1.tar.gz b273ad1be20c7ff8a450a216a89b893ae78f2a62 libodb-sqlite-2.2.0.a1.zip d966000b22ffddaa6c40d98ca2cf583f16bf4180 odb-2.2.0.a1-i686-linux-gnu.tar.bz2 8012cd0e1ce2b27e5cd108a938cf66fb2a58372c odb-2.2.0.a1-i686-windows.zip 4b3ac77b4d9fa0957daaa12728d5a1a143dbbd9f odb-2.2.0.a1.tar.bz2 48014dc5f12758754b5b7342e039e713f771572f odb-2.2.0.a1.tar.gz f4a382462429e9bb18d7f15790b15c75a664b4d4 odb-2.2.0.a1-x86_64-linux-gnu.tar.bz2 7209a4cf9d3c140db0e695b8261f55954d75d41f odb-2.2.0.a1.zip a951d68dcc9971e56e077740f843c1d1d9b8cdfa odb-examples-2.2.0.a1.tar.bz2 992d309fe5445eb06ebaf4b7e10b4bbccbad800c odb-examples-2.2.0.a1.tar.gz 613ba4dd1219ebcd91d84da057fe4faf7426be7f odb-examples-2.2.0.a1.zip c155e5f4b5b6ffc3715415196e22f490bc9e39aa odb-tests-2.2.0.a1.tar.bz2 823595b17729ba199953075af0467a7617a14c97 odb-tests-2.2.0.a1.tar.gz 7cd02c40ef08ee3bdc250552688c0276ab8bc260 odb-tests-2.2.0.a1.zip From boris at codesynthesis.com Mon Oct 29 11:20:15 2012 From: boris at codesynthesis.com (Boris Kolpackov) Date: Mon Oct 29 10:48:52 2012 Subject: [odb-users] Prepared statement feature In-Reply-To: <3233D27CC5658E4598557F8521F6B07E21536C3CE3@RIC-MS01.abw.int> References: <3233D27CC5658E4598557F8521F6B07E2146550D92@RIC-MS01.abw.int> <3233D27CC5658E4598557F8521F6B07E2146550E4E@RIC-MS01.abw.int> <3233D27CC5658E4598557F8521F6B07E2146550E68@RIC-MS01.abw.int> <3233D27CC5658E4598557F8521F6B07E2146550F05@RIC-MS01.abw.int> <3233D27CC5658E4598557F8521F6B07E21536C3CE3@RIC-MS01.abw.int> Message-ID: Hi Paul, Stath, Paul writes: > I'll be happy to test this, but probably can't put any time towards > it until early Nov. We just published 2.2.0.a1 pre-release which includes prepared statement support: http://www.codesynthesis.com/pipermail/odb-announcements/2012/000020.html > I would be happy to simply use git to download the source, just let me > know the branch name where the prepared query work can be found. There is actually some extra steps required to "bootstrap" the git code to get to the state that you find in the distribution. In particular, the autotools and VC++ projects are auto-generated and are not maintained in the git repository. If you are interested in details, see the INSTALL-GIT file. Boris