From boris at codesynthesis.com Wed Dec 7 01:22:52 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Wed Dec 7 01:32:11 2011 Subject: [odb-users] ODB 1.7.0 released Message-ID: Hi, We have released ODB 1.7.0. The NEWS file entries for this release are as follows: * Support for the Oracle database. The provided connection factories include 'new' (a new connection is created every time one is requested) and 'pool' (a pool of connections is maintained). The Boost and Qt profiles have been updated to support this database. For more information, refer to Chapter 16, "Oracle Database" in the ODB manual. Note also that the Oracle runtime (libodb-oracle) is licensed under a different license compared to other database runtimes. For more information, refer to the ODB License page: http://www.codesynthesis.com/products/odb/license.xhtml * Support for optimistic concurrency. For more information refer to Chapter 11, "Optimistic Concurrency" in the ODB manual as well as the 'optimistic' example in the odb-examples package. * Support for read-only objects, composite value types, and data members. The new readonly pragma can be used to declare one of these entities as read-only. Constant data members are automatically treated as read-only. For more information, refer to Section 12.1.4 "readonly (object)", Section 12.3.6 "readonly (composite value)", and Section 12.4.10 "readonly (data member)" in the ODB manual. * Support for persistent classes without object identifiers. Such classes have to be explicitly declared as not having an object id and they have limited functionality. For more information, refer to Section 12.1.5 "id" in the ODB manual. * Support for SQL statement execution tracing. For more information, refer to Section 3.12 "Tracing SQL Statement Execution" in the ODB manual. * Support for mapping char[N], unsigned char[N], and std::vector to the BLOB (or equivalent) types. For more information, refer to Chapters 13 (for MySQL), 14 (for SQLite), 15 (for PostgreSQL), and 16 (for Oracle) in the ODB manual. * Query result iterator now provides the id() function which allows one to get the object id without loading the object. For more information, refer to Section 4.4 "Query Result" in the ODB manual. * Support for microsecond precision in Boost and Qt date-time types mapping to PostgreSQL date-time data types. Additionally, Qt QDateTime values stored in a PostgreSQL database can now be earlier than the UNIX epoch. We would like to thank everyone who reported bugs, shared test results, or helped test one of the pre-releases. Source code and pre-compiled binary packages for this release are available from the ODB download page: http://www.codesynthesis.com/products/odb/download.xhtml SHA1 checksums for the files in this release are as follows: 0d3b0a28f8532004e63bb0365622c3a658c06205 libodb-1.7.0.tar.bz2 a5e5b0bf02a47c59304de26a8fce686a6b4aae2c libodb-1.7.0.tar.gz f2c226e29a9c3d8a2eb95c7677b8f8d6afa3ed36 libodb-1.7.0.zip 740535a34068d86b07a76905f0eb7ecd101936fa libodb-boost-1.7.0.tar.bz2 a923ccfd25d3e8347acac96cf38786397b8d4486 libodb-boost-1.7.0.tar.gz c5e59f3564c50729b82fd05e05cb7982fbcd5ba7 libodb-boost-1.7.0.zip 29db3f052af9b3258fe0a0f8f716f9e6f227e714 libodb-mysql-1.7.0.tar.bz2 2a54a48c35c089514ad434e9e73e042e831bbd0c libodb-mysql-1.7.0.tar.gz 560a779fe2430faf988285b22c232492753aaa25 libodb-mysql-1.7.0.zip fe134e9a244ce8f986d0110d3b3531b74b3591bf libodb-oracle-1.7.0.tar.bz2 043684bd2d653505aec0171702de9d6590490334 libodb-oracle-1.7.0.tar.gz 01c28424a029550370bcd3cb46fa13de76fcf62e libodb-oracle-1.7.0.zip a9123cf7913d92b9628fddfe0d5a7b84278a0857 libodb-pgsql-1.7.0.tar.bz2 65c315c9598076790a3a7583f3d27f5a4cb934a7 libodb-pgsql-1.7.0.tar.gz 42ad4f9b2c7e629dd4758326958c4030a980d77f libodb-pgsql-1.7.0.zip a4a649541a587b14062d3e8745f5b463c0ecd1fb libodb-qt-1.7.0.tar.bz2 70c3a7ba3c9bd866a78bfdc61d33ae916eb56833 libodb-qt-1.7.0.tar.gz eb647c83e6b4c8a01fbe7ea8c4ea7a4341ea7ae1 libodb-qt-1.7.0.zip 741cb49b209cf77831f5acfc9c24d4aefa842b12 libodb-sqlite-1.7.0.tar.bz2 6fa65296b293e7f395bba2412db581b993c398ad libodb-sqlite-1.7.0.tar.gz 10b014e36d9f7693537f4a8e1128e5984f1be6b1 libodb-sqlite-1.7.0.zip 08074365c117cfe0d12d14722785d0014ce9edf1 odb-1.7.0-i686-linux-gnu.tar.bz2 9348c65ca0ee2322ec54d66cd2a7acaaaf04ccf3 odb-1.7.0-i686-macosx.tar.bz2 f54907dd1841fd6ca856850af00ec7f416f42bd0 odb-1.7.0-i686-solaris.tar.bz2 71c15eff6168737339d46cae550915d83450120d odb-1.7.0-i686-windows.zip d869bd861c248ab3ce44d3ad4734db99ddfbfaa5 odb-1.7.0-sparc-solaris.tar.bz2 2129fecf4ed48fa693475bc91c993e20753b4f4c odb-1.7.0.tar.bz2 8f9a1eab52a53dfe1d999819ea42cae69355f3a7 odb-1.7.0.tar.gz 4081899d36f4e1c10e002ecefc298e1f690daf71 odb-1.7.0-x86_64-linux-gnu.tar.bz2 8db754e797ee0ba5f519cd912b0cb9f56fb576cd odb-1.7.0.zip 7e5fafcb0b79211202e43505014d5234ff0e0743 odb-examples-1.7.0.tar.bz2 2870fe8d3b7d4e9e887391a899e326f5d554b648 odb-examples-1.7.0.tar.gz 5ebf67b694441b80bc7de5d987dbb95e79c3a211 odb-examples-1.7.0.zip 8cc2d39ddd91a79cccab623c131ee5cf8b9ee6ff odb-tests-1.7.0.tar.bz2 8a6a75bedc7f24eb6a6cfaa843d9189b2198919d odb-tests-1.7.0.tar.gz add1e682b822e2accae75fe02ef339c0c79a1b88 odb-tests-1.7.0.zip Enjoy, Boris From quejacq at gmail.com Thu Dec 8 19:56:40 2011 From: quejacq at gmail.com (quejacq@gmail.com) Date: Fri Dec 9 02:19:23 2011 Subject: [odb-users] Composite values, multiple values in primary key, and foreign constraints Message-ID: Hello, I came across ODB last week while searching for a good ORM solution in C++, so please excuse if the answers to my questions seem obvious to advanced users. 1. I'm trying to define a composite value for the class boost::asio::ip::address, which can contain either an IPv4 or IPv6 address. Because MySQL (for example) cannot handle the 128 bits of an IPv6 address in a single integer field, I have to split it up in at least two columns. >From what I understand in the manual and examples, I can create composite value types using the "db value" pragma. However, it seems to me that I am only able to do so if I create the classes myself and use the pragmas accordingly. When using the "distant pragma" (i.e. #pragma dv value(boost::asio::ip::addess)), I get an error in boost asio's address.hpp: "unnamed type in data member declaration". Anyway, event if it worked, it leads to a problem where, in the end, ip::address contains either an ip::address_v4 or ip::address_v6, and while ip::address_v6 contains an array of 16 unsigned chars, while ip::address_v4 has one of 4, so the "automatic" mapping will IMHO fail. Is there any way to map a class defined in some third-party library and define someting like a value_traits for it to provide the requested mapping? 2. Every example carefully avoids the case of multiple values in the primary key. While I thought it would be a simple matter of using multiple "db id" pragmas, this leads to an error returned by the odb compiler. How can I have a primary key made of a tuple? Do I have to define another class just reserved for them? 3. The only mention of foreign keys in the manual is inside raw SQL queries to the DBMS. How can I define foreign key constraints among tables of the database? Thank you for answering, Quentin From boris at codesynthesis.com Fri Dec 9 07:33:36 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Fri Dec 9 07:43:29 2011 Subject: [odb-users] Composite values, multiple values in primary key, and foreign constraints In-Reply-To: References: Message-ID: Hi Quentin, quejacq@gmail.com writes: > 1. I'm trying to define a composite value for the class > boost::asio::ip::address, which can contain either an IPv4 or IPv6 address. > Because MySQL (for example) cannot handle the 128 bits of an IPv6 address > in a single integer field, I have to split it up in at least two columns. > >From what I understand in the manual and examples, I can create composite > value types using the "db value" pragma. However, it seems to me that I am > only able to do so if I create the classes myself and use the pragmas > accordingly. There are two ways to store a value type like this in the database: as a simple value (single column) or as a composite value (multi-column). Which way is better really depends on the application and Section 3.1, "Concepts and Terminology" in the ODB Manual has more information on this. Though in this particular case it seems like the simple value would be preferably (see below). Let's cover the composite value case first. If you had written the class yourself, then that would have been easy: you could simply add a friend declaration to the class and made sure that the types for all its data members are also mapped. However, we cannot modify a third-party class like asio::ip::address to add a friend declaration and its data member are private. So this is a problem. The way I see how this will be supported in the future is via the feature we call "virtual members". Essentially, the idea is to support accessing/modifying private data members using accessors instead of directly. For more information on virtual member, see this thread: http://www.codesynthesis.com/pipermail/odb-users/2011-October/000352.html Provided we had virtual members and could map asio::ip::address to a composite value type, I don't think this will be an ideal mapping. If you look at the data members declared in this type, there are three: type_ (enum), ipv4_address_, and ipv6_address_. If mapped to a composite value, this type will occupy (at least) three columns in the database with only two actually containing any useful data. I think this is a bit wasteful. Let's now examine the simple value case, which I think is generally preferable. The basic idea is to store it in a single column using some format. To implement it you will need to provide the value_traits template specialization. The 'mapping' example shows how to do this. The simplest format that we can use to store asio::ip::address is probably as a string. The class already has the {to,from}_string() functions so this should be quite easy to implement. Another, more compact format, would be to store it as a 17-byte array (1 byte as a type indicator and 16 bytes for storage). > 2. Every example carefully avoids the case of multiple values in the > primary key. While I thought it would be a simple matter of using multiple > "db id" pragmas, this leads to an error returned by the odb compiler. How > can I have a primary key made of a tuple? Do I have to define another class > just reserved for them? Currently ODB only supports simple values as object ids though we have support for composite ids high up in our TODO list. However, I don't think we will support the "multiple ids" case (i.e., where you can mark several data members as object ids). In many places in its API ODB returns object ids and returning such a multi-id will be messy. > 3. The only mention of foreign keys in the manual is inside raw SQL queries > to the DBMS. How can I define foreign key constraints among tables of the > database? ODB maps relationships between C++ objects to foreign key constraints between database tables. For instance, in the 'relationship' example we have: #pragma db object class employer { ... }; #pragma db object class employee { ... shared_ptr employer_; }; And in the generated database schema in the employee table we have (using the PostgreSQL schema as an example): CONSTRAINT "employer_fk" FOREIGN KEY ("employer") REFERENCES "employer" ("name") INITIALLY DEFERRED Is this what you are looking for? Boris From vaioinman at googlemail.com Fri Dec 9 18:13:47 2011 From: vaioinman at googlemail.com (Cuong Minh Tran) Date: Fri Dec 9 22:59:28 2011 Subject: [odb-users] Problem - Using ODB inside a DLL Message-ID: <78EC4707-6DA3-4C28-A09B-3727D66ADC25@gmail.com> Hi everyone, I am trying to use the set ODB - MYSQL/SQLite version 1.6 in my COM DLL, developed in MSVC 2010. I had no issues with compiling libodb, libodb-mysql/sqlite on the same machine with my COM. My COM code also compiles without a problem. However, I want to trigger the COM in my application, the execution always fails at the (*) line: ... // create database pointer std::auto_ptr db ( create_database ( ) ); (*) odb::transaction t (db->begin ()); //persist an simple object ? The Output has these lines: ... GME.exe': Loaded 'C:\Program Files\GME\Bin\odb-mysql-1.6-vc10.dll', Symbols loaded. 'GME.exe': Loaded 'C:\Program Files\GME\Bin\libmysql.dll', Exports loaded. 'GME.exe': Loaded 'C:\WINDOWS\system32\mfc100.dll', Cannot find or open the PDB file 'GME.exe': Loaded 'C:\WINDOWS\system32\dnsapi.dll', Exports loaded. 'GME.exe': Loaded 'C:\WINDOWS\system32\iphlpapi.dll', Exports loaded. 'GME.exe': Loaded 'C:\WINDOWS\system32\winrnr.dll', Exports loaded. 'GME.exe': Loaded 'C:\WINDOWS\system32\wshbth.dll', Exports loaded. 'GME.exe': Loaded 'C:\WINDOWS\system32\rasadhlp.dll', Exports loaded. The thread 'RtlAllocateHeap' (0x260) has exited with code 0 (0x0). The thread 'RtlAllocateHeap' (0xc60) has exited with code 0 (0x0). First-chance exception at 0x03435937 (odb-1.6-vc10.dll) in GME.exe: 0xC0000005: Access violation reading location 0x00000000. The thread 'RPC Callback Thread' (0xe04) has exited with code 0 (0x0). The thread 'WmiFreeBuffer' (0xc90) has exited with code 0 (0x0). The thread 'Win32 Thread' (0x954) has exited with code 1 (0x1). The thread 'Win32 Thread' (0x670) has exited with code 0 (0x0). The Disassembly has these lines: std::auto_ptr db ( create_database ( ) ); lea edx,[ebp-1ACh] push edx call create_database (451EFD0h) mov esi,dword ptr [eax] add esp,4 mov dword ptr [eax],0 mov dword ptr [ebp-1CCh],esi mov ecx,dword ptr [ebp-1ACh] mov bl,63h mov byte ptr [ebp-4],bl test ecx,ecx je 04523116 mov eax,dword ptr [ecx] mov edx,dword ptr [eax] push 1 call edx odb::transaction t (db->begin ()); mov eax,dword ptr [esi] mov edx,dword ptr [eax+4] mov ecx,esi call edx push 1 push eax lea ecx,[ebp-284h] call dword ptr [__imp_odb::transaction::transaction (46675A4h)] It looks like libodb could have an issue some where. Could someone please offer some help? Many thanks and best regards, Cuong Tran PS. I tried the libodb and libodb-sqlite 1.6 in a standalone command line MSVC application and they worked fine. From boris at codesynthesis.com Sun Dec 11 08:22:12 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Sun Dec 11 08:21:11 2011 Subject: [odb-users] Problem - Using ODB inside a DLL In-Reply-To: <78EC4707-6DA3-4C28-A09B-3727D66ADC25@gmail.com> References: <78EC4707-6DA3-4C28-A09B-3727D66ADC25@gmail.com> Message-ID: Hi Cuong, Cuong Minh Tran writes: > I am trying to use the set ODB - MYSQL/SQLite version 1.6 in my COM DLL, > developed in MSVC 2010. I had no issues with compiling libodb, > libodb-mysql/sqlite on the same machine with my COM. My COM code also > compiles without a problem. However, I want to trigger the COM in my > application, the execution always fails at the (*) line: > > ... > // create database pointer > std::auto_ptr db ( create_database ( ) ); > (*) odb::transaction t (db->begin ()); > //persist an simple object It is hard to say what's going on without knowing exactly how you created your "COM DLL" and without seeing the create_database() database implementation. One fairly common cause would be if ODB is unable to connect to the database (which in this case will happen during the db->begin () call) though you said that everything works fine in plain Win32 setup so it is probably not it. In any case, I went ahead and created a test "COM DLL" project as described on this page: http://msdn.microsoft.com/en-us/library/dssw0ch4(v=VS.90).aspx I then added code similar to the above to the property's get_XXX() function. However, everything is working fine for me. Could you try this project and see if it works for you? http://www.codesynthesis.com/~boris/tmp/odb/com_dll.zip You will need to make some modifications in Object1.cpp to use your MySQL connection parameters before you can run the test. If it works for you as well, then you can try to modify it to resemble your code until it fails. Then I would be able to take a look. Boris From vaioinman at googlemail.com Sun Dec 11 14:59:27 2011 From: vaioinman at googlemail.com (Cuong Minh Tran) Date: Mon Dec 12 02:16:04 2011 Subject: [odb-users] Problem - Using ODB inside a DLL In-Reply-To: References: <78EC4707-6DA3-4C28-A09B-3727D66ADC25@gmail.com> Message-ID: Hi Boris, Great thanks to your reply. I will try your COM DLL project and communicate the progress. Nonetheless, looking back through the archives, I found my problem to be very much like this: http://www.codesynthesis.com/pipermail/odb-users/2011-June/000127.html But the archive does not seem to contain the solution. Best regards, Cuong On 11 Dec 2011, at 13:22, Boris Kolpackov wrote: > Hi Cuong, > > Cuong Minh Tran writes: > >> I am trying to use the set ODB - MYSQL/SQLite version 1.6 in my COM DLL, >> developed in MSVC 2010. I had no issues with compiling libodb, >> libodb-mysql/sqlite on the same machine with my COM. My COM code also >> compiles without a problem. However, I want to trigger the COM in my >> application, the execution always fails at the (*) line: >> >> ... >> // create database pointer >> std::auto_ptr db ( create_database ( ) ); >> (*) odb::transaction t (db->begin ()); >> //persist an simple object > > It is hard to say what's going on without knowing exactly how you > created your "COM DLL" and without seeing the create_database() > database implementation. One fairly common cause would be if ODB > is unable to connect to the database (which in this case will > happen during the db->begin () call) though you said that > everything works fine in plain Win32 setup so it is probably not > it. > > In any case, I went ahead and created a test "COM DLL" project as > described on this page: > > http://msdn.microsoft.com/en-us/library/dssw0ch4(v=VS.90).aspx > > I then added code similar to the above to the property's get_XXX() > function. However, everything is working fine for me. Could you try > this project and see if it works for you? > > http://www.codesynthesis.com/~boris/tmp/odb/com_dll.zip > > You will need to make some modifications in Object1.cpp to use > your MySQL connection parameters before you can run the test. > > If it works for you as well, then you can try to modify it to > resemble your code until it fails. Then I would be able to take > a look. > > Boris From boris at codesynthesis.com Mon Dec 12 09:10:12 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Mon Dec 12 09:09:04 2011 Subject: [odb-users] Problem - Using ODB inside a DLL In-Reply-To: References: <78EC4707-6DA3-4C28-A09B-3727D66ADC25@gmail.com> Message-ID: Hi Cuong, Cuong Minh Tran writes: > Nonetheless, looking back through the archives, I found my problem to be > very much like this: > > http://www.codesynthesis.com/pipermail/odb-users/2011-June/000127.html > > But the archive does not seem to contain the solution. In that case the problem seemed to be missing sqlite3.dll. I checked the output from your original post and I see that libmysql.dll was loaded successfully. I think the best way to figure out what's going on is to create a small test case that reproduces the problem. Then I would be able to try to find out the cause. Boris From ekimka at gmail.com Tue Dec 13 07:05:50 2011 From: ekimka at gmail.com (Konstantin Mikhailov) Date: Tue Dec 13 07:06:18 2011 Subject: [odb-users] Different database schemas - postgresql Message-ID: Is it possible to specify different database schema for different persistent objects/tables ? We need simulanteous access to the tables located in the different schemas. I've tried to embed schema in the table name in the form #pragma db object table("myschema.test") class Test { public: // ~~ Accessors int id() const throw() { return id_; } void id(int id) { id_ = id; } private: friend class odb::access; // ~~ Fields #pragma db id auto int id_; }; But in *-odb.cxx i've got: const char access::object_traits< ::Test >::find_statement[] = "SELECT " "\"myschema.test\".\"id\"" " FROM \"myschema.test\"" " WHERE \"myschema.test\".\"id\"=$1"; Unfortunatelly it will not work due to double quotes around the table name. From boris at codesynthesis.com Tue Dec 13 10:18:11 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Tue Dec 13 10:16:54 2011 Subject: [odb-users] Different database schemas - postgresql In-Reply-To: References: Message-ID: Hi Konstantin, Konstantin Mikhailov writes: > Is it possible to specify different database schema > for different persistent objects/tables? No, not yet. But we have been thinking about adding this support for some time now. > We need simulanteous access to the tables located in the > different schemas. What will be the best way to implement the mapping of objects to schemas in your case? We have thought of three mechanisms: 1. By specifying the schema in the 'db table' pragma, as you have already tried: #pragma db object table("myschema.test") Or, to just specify the schema name and get the auto-derived table name: #pragma db object table("myschema.") 2. By mapping a C++ namespace to a database schema. This will result in all the persistent classes in this namespace having tables in this schema. The syntax is not yet finalized, but it could look something like this: #pragma db namespace database("myschema") namespace N { ... } Or: #pragma db namespace(N) database("myschema") While something like this might seem more natural: #pragma db namespace(N) schema("myschema") We don't want to use the term 'schema' because (a) not all databases have this notion (some, like MySQL and SQLite use the term 'database' for this while others, like SQL Server can have much more that just the schema appearing before the table, as in: server.db.schema.table) and (b) the term schema is quite overloaded (i.e., we also generate a "database schema"). So, instead, we are thinking of using a more neutral 'database namespace' term. So in the above example, the more verbose alternative would be: #pragma db namespace(N) database_namespace("myschema") 3. By specifying the schema on the command line, for example, with with the --database-namespace option: --database-namespace myschema This will lead to all the classes in this header that don't have a schema assigned using one of the above two methods, having tables in myschema. Which option will work best for your case? Boris From ekimka at gmail.com Tue Dec 13 12:39:46 2011 From: ekimka at gmail.com (Konstantin Mikhailov) Date: Tue Dec 13 12:40:14 2011 Subject: [odb-users] Different database schemas - postgresql In-Reply-To: References: Message-ID: Hi Boris. On Tue, Dec 13, 2011 at 9:18 PM, Boris Kolpackov wrote: > Hi Konstantin, > > Konstantin Mikhailov writes: > > > Is it possible to specify different database schema > > for different persistent objects/tables? > > No, not yet. But we have been thinking about adding this > support for some time now. > > > > We need simulanteous access to the tables located in the > > different schemas. > > What will be the best way to implement the mapping of objects > to schemas in your case? We have thought of three mechanisms: > > 1. By specifying the schema in the 'db table' pragma, as you > have already tried: > > #pragma db object table("myschema.test") > > Or, to just specify the schema name and get the auto-derived > table name: > > #pragma db object table("myschema.") > > This option looks confusing alittle i think. I'm also think that separate pragma option to specify database schema/namespace will be more clear. > 2. By mapping a C++ namespace to a database schema. This will > result in all the persistent classes in this namespace having > tables in this schema. The syntax is not yet finalized, but > it could look something like this: > > #pragma db namespace database("myschema") > namespace N > { > ... > } > > In my opinion this option looks like most elegant one (i prefer something shorter abit #pragma db namespace("myschema") for example). Unfortunately there will be significant overhead to specify database schema/namespace in each header file. We've found that one header file for each table is most optimal for us (we have over 50 header files at the moment and will be much more in the nearest future). btw, we've also found that write all header files by the hand is too difficult/tedious. so we're using simple homemade xml format to generate all hxx headers required by odb. > Or: > > #pragma db namespace(N) database("myschema") > > While something like this might seem more natural: > > #pragma db namespace(N) schema("myschema") > > We don't want to use the term 'schema' because (a) not all > databases have this notion (some, like MySQL and SQLite use > the term 'database' for this while others, like SQL Server > can have much more that just the schema appearing before > the table, as in: server.db.schema.table) and (b) the term > schema is quite overloaded (i.e., we also generate a "database > schema"). So, instead, we are thinking of using a more neutral > 'database namespace' term. So in the above example, the more > verbose alternative would be: > > #pragma db namespace(N) database_namespace("myschema") > > > 3. By specifying the schema on the command line, for example, > with with the --database-namespace option: > > --database-namespace myschema > > This will lead to all the classes in this header that don't > have a schema assigned using one of the above two methods, > having tables in myschema. > > Which option will work best for your case? In our case last option will be most interresting one, since i don't need to edit hxx files just spread them in different folders for example and run odb in each directory with correct arguments. > Boris > From boris at codesynthesis.com Wed Dec 14 09:20:58 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Wed Dec 14 09:19:35 2011 Subject: [odb-users] Different database schemas - postgresql In-Reply-To: References: Message-ID: Hi Konstantin, Konstantin Mikhailov writes: > On Tue, Dec 13, 2011 at 9:18 PM, Boris Kolpackov wrote: > > > 1. By specifying the schema in the 'db table' pragma, as you > > have already tried: > > > > #pragma db object table("myschema.test") > > > > Or, to just specify the schema name and get the auto-derived > > table name: > > > > #pragma db object table("myschema.") > > > > > This option looks confusing alittle i think. I'm also think that separate > pragma option to specify database schema/namespace will be more clear. I agree, the latter case ("myschema.") is a bit stretched and a separate specifier is probably better, as in: #pragma db object namespace("myschema") class test { ... }; However, I think it is a good idea to allow "myschema.test" as a shortcut when specifying both the namespace and the table name: #pragma db object table("myschema.test") class test { ... }; With the more verbose option being: #pragma db object namespace("myschema") table("test") class test { ... }; > > 2. By mapping a C++ namespace to a database schema. This will > > result in all the persistent classes in this namespace having > > tables in this schema. The syntax is not yet finalized, but > > it could look something like this: > > > > #pragma db namespace database("myschema") > > namespace N > > { > > ... > > } > > > In my opinion this option looks like most elegant one (i prefer > something shorter abit #pragma db namespace("myschema") for example). While I agree '#pragma db namespace("myschema")' looks much better, the problem with this syntax is that it is inconsistent with the rest of the pragmas, which have the so-called 'qualifier' follow the 'db' keyword. The qualifier qualifies what kind of C++ object this pragma applies to (e.g., 'object', 'value', 'member'). So if we follow this convention, then the syntax should be something like this: #pragma db namespace namespace("myschema") namespace N { namespace M { } } #pragma db namespace(N::M) namespace("myschema1") #pragma db namespace() namespace("myschema2") // Global namespace. The 'namespace namespace' part looks odd but I haven't been able to think of a better combination (if you have any ideas, let me know). Also, thinking about the future, we may want to specify other database aspects on the C++ namespace basis. For example, we could specify table options that apply to all the persistent classes in a C++ namespace: #pragma db namespace table_options("tablespace mytablespace") namespace N { } > Unfortunately there will be significant overhead to specify database > schema/namespace in each header file. You can always create a common header file that provides the C++ namespace to database namespace mapping and then either #include it into each persistent class header or include it into the ODB compilation using the --odb-epilogue option. In any case, I will try to implement support for something along these lines in the next week or two. I will let you know when I have something for you to try. Boris From luischivaldes at gmail.com Wed Dec 14 12:14:26 2011 From: luischivaldes at gmail.com (=?ISO-8859-1?Q?Luis_Vald=E9s?=) Date: Wed Dec 14 12:14:35 2011 Subject: [odb-users] Problem on building libodb-oracle-1.7.0 Message-ID: Hi I am having a problem while configuring "libodb-oracle-1.7.0" on Windows 7 32 bits using MinGW32 Here is my configure sentence ./configure CPPFLAGS="-IC:/MinGW/odb-1.7.0-i686-windows/libodb-1.7.0/odb -IC:/Oracle/product/10.2.0/client_1/oci/include" LDFLAGS="-LC:/MinGW/odb-1.7.0-i686-windows/libodb-1.7.0/odb/.libs -LC:/Oracle/product/10.2.0/client_1/oci/lib/msvc" Here is the problem on the config log libtool: link: g++ -g -O2 -mthreads -o .libs/conftest conftest.o -LC:/MinGW/odb-1.7.0-i686-windows/libodb-1.7.0/odb/.libs -LC:/Oracle/product/10.2.0/client_1/oci/lib/msvc -L/c/Oracle/product/10.2.0/client_1/lib -lclntsh -mthreads c:/mingw/bin/../lib/gcc/mingw32/4.6.1/../../../../mingw32/bin/ld.exe: cannot find -lclntsh collect2: ld returned 1 exit status configure:16916: $? = 1 configure:16966: result: no configure:16968: error: oci is not found; consider using --with-oci=DIR I dont have libclntsh in my oracle client lib. What can I do? Best Regards -- Luis Valdes From luisvaldes88 at gmail.com Wed Dec 14 12:40:06 2011 From: luisvaldes88 at gmail.com (=?ISO-8859-1?Q?Luis_Vald=E9s?=) Date: Wed Dec 14 12:40:13 2011 Subject: [odb-users] Re: Problem on building libodb-oracle-1.7.0 In-Reply-To: References: Message-ID: I just change the name of oci.lib to libclntsh.lib and it worked. oci.lib is the name of the file on windows. :D El 14 de diciembre de 2011 14:14, Luis Vald?s escribi?: > Hi > > I am having a problem while configuring "libodb-oracle-1.7.0" on Windows > 7 32 bits using MinGW32 > > Here is my configure sentence > > > ./configure CPPFLAGS="-IC:/MinGW/odb-1.7.0-i686-windows/libodb-1.7.0/odb > -IC:/Oracle/product/10.2.0/client_1/oci/include" > LDFLAGS="-LC:/MinGW/odb-1.7.0-i686-windows/libodb-1.7.0/odb/.libs > -LC:/Oracle/product/10.2.0/client_1/oci/lib/msvc" > > > Here is the problem on the config log > > libtool: link: g++ -g -O2 -mthreads -o .libs/conftest conftest.o > -LC:/MinGW/odb-1.7.0-i686-windows/libodb-1.7.0/odb/.libs > -LC:/Oracle/product/10.2.0/client_1/oci/lib/msvc > -L/c/Oracle/product/10.2.0/client_1/lib -lclntsh -mthreads > c:/mingw/bin/../lib/gcc/mingw32/4.6.1/../../../../mingw32/bin/ld.exe: > cannot find -lclntsh > collect2: ld returned 1 exit status > configure:16916: $? = 1 > configure:16966: result: no > configure:16968: error: oci is not found; consider using --with-oci=DIR > > I dont have libclntsh in my oracle client lib. > What can I do? > > Best Regards > > > -- > Luis Valdes > -- Luis Valdes From boris at codesynthesis.com Wed Dec 14 14:14:55 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Wed Dec 14 14:13:31 2011 Subject: [odb-users] Re: Problem on building libodb-oracle-1.7.0 In-Reply-To: References: Message-ID: Hi Luis, Luis Vald?s writes: > I just change the name of oci.lib to libclntsh.lib and it worked. Yes, that's what we did, except we used the libclntsh.a name. I actually wrote a blob post about this just a couple of days ago: http://www.codesynthesis.com/~boris/blog/2011/12/09/oci-mingw/ Boris From luisvaldes88 at gmail.com Thu Dec 15 07:21:33 2011 From: luisvaldes88 at gmail.com (=?ISO-8859-1?Q?Luis_Vald=E9s?=) Date: Thu Dec 15 08:05:34 2011 Subject: [odb-users] Re: Problem on building libodb-oracle-1.7.0 In-Reply-To: References: Message-ID: > > Boris, here is the email. Thank you for your answer! I just finished testing it and it works great! I changed the example a little to match with my own schema and it works on the first try. And the best part is that it just do its part with oracle. I tryied another ORM library, QxOrm, I liked it but ODB is lighter than QxOrm. I will try to make a short tutorial in spanish. Great Job ! From quejacq at gmail.com Fri Dec 16 08:47:17 2011 From: quejacq at gmail.com (quejacq@gmail.com) Date: Fri Dec 16 08:51:31 2011 Subject: [odb-users] Composite values, multiple values in primary key, and foreign constraints In-Reply-To: References: Message-ID: Hi Boris, Thank you very much for your answer. 1. Storing IP addresses as string is fine as long as you don't need to do binary operations on these addresses, such as network mask matching. This is why I was searching for an integer. Moreover, IPv4 addresses can be stored in the IPv6 format, so keeping one (or more) columns dedicated to just one "kind" of address is IMHO not a god solution. The best solution for storing as a uinque column is postgresql's inet (or cidr) type. Alas, MySQL doesn't provide an equivalent field. As a result, I was hoping to do the manual mapping myself, with the help of some sort of value_traits class. But, inferring from the declaration of value_traits in the ODB source code, I suppose this is not currently possible. I don't think the "virtual members" you mentionned will solve this particular problem either. They would allow ODB to read/write to the asio::boost:ip_address object, but I am unable to understand how it will help me map either an IPv4 or an IPv6 address to the same database multiple fields. 2. OK, I understand the technical difficulty. What would you suggest instead? Create a table that assigns a unique ID for each composite primary key, and use that as a foreign key in the other table ? 3. Yes, thank you. I did not realise ODB "magically" managed to find the foreign key. Anyway, thank you again for your fast answer. I don't think ODB will do it for me on this project, but I will keep an eye on it as I believe it is a really good solution for ORM in C++. Still, congratulations on what you have achieved so far :). All the best, Quentin On Fri, Dec 9, 2011 at 1:33 PM, Boris Kolpackov wrote: > Hi Quentin, > > quejacq@gmail.com writes: > > > 1. I'm trying to define a composite value for the class > > boost::asio::ip::address, which can contain either an IPv4 or IPv6 > address. > > Because MySQL (for example) cannot handle the 128 bits of an IPv6 address > > in a single integer field, I have to split it up in at least two columns. > > >From what I understand in the manual and examples, I can create > composite > > value types using the "db value" pragma. However, it seems to me that I > am > > only able to do so if I create the classes myself and use the pragmas > > accordingly. > > There are two ways to store a value type like this in the database: as > a simple value (single column) or as a composite value (multi-column). > Which way is better really depends on the application and Section 3.1, > "Concepts and Terminology" in the ODB Manual has more information on > this. Though in this particular case it seems like the simple value > would be preferably (see below). > > Let's cover the composite value case first. If you had written the > class yourself, then that would have been easy: you could simply add > a friend declaration to the class and made sure that the types for > all its data members are also mapped. > > However, we cannot modify a third-party class like asio::ip::address > to add a friend declaration and its data member are private. So this > is a problem. The way I see how this will be supported in the future > is via the feature we call "virtual members". Essentially, the idea > is to support accessing/modifying private data members using accessors > instead of directly. For more information on virtual member, see this > thread: > > http://www.codesynthesis.com/pipermail/odb-users/2011-October/000352.html > > Provided we had virtual members and could map asio::ip::address to a > composite value type, I don't think this will be an ideal mapping. If > you look at the data members declared in this type, there are three: > type_ (enum), ipv4_address_, and ipv6_address_. If mapped to a composite > value, this type will occupy (at least) three columns in the database > with only two actually containing any useful data. I think this is a > bit wasteful. > > Let's now examine the simple value case, which I think is generally > preferable. The basic idea is to store it in a single column using > some format. To implement it you will need to provide the value_traits > template specialization. The 'mapping' example shows how to do this. > > The simplest format that we can use to store asio::ip::address is > probably as a string. The class already has the {to,from}_string() > functions so this should be quite easy to implement. Another, more > compact format, would be to store it as a 17-byte array (1 byte as > a type indicator and 16 bytes for storage). > > > > 2. Every example carefully avoids the case of multiple values in the > > primary key. While I thought it would be a simple matter of using > multiple > > "db id" pragmas, this leads to an error returned by the odb compiler. How > > can I have a primary key made of a tuple? Do I have to define another > class > > just reserved for them? > > Currently ODB only supports simple values as object ids though we have > support for composite ids high up in our TODO list. However, I don't > think we will support the "multiple ids" case (i.e., where you can mark > several data members as object ids). In many places in its API ODB > returns object ids and returning such a multi-id will be messy. > > > > 3. The only mention of foreign keys in the manual is inside raw SQL > queries > > to the DBMS. How can I define foreign key constraints among tables of the > > database? > > ODB maps relationships between C++ objects to foreign key constraints > between database tables. For instance, in the 'relationship' example > we have: > > #pragma db object > class employer > { > ... > }; > > #pragma db object > class employee > { > ... > > shared_ptr employer_; > }; > > And in the generated database schema in the employee table we have > (using the PostgreSQL schema as an example): > > CONSTRAINT "employer_fk" > FOREIGN KEY ("employer") > REFERENCES "employer" ("name") > INITIALLY DEFERRED > > Is this what you are looking for? > > Boris > From boris at codesynthesis.com Fri Dec 16 09:10:10 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Fri Dec 16 09:08:32 2011 Subject: [odb-users] Composite values, multiple values in primary key, and foreign constraints In-Reply-To: References: Message-ID: Hi Quentin, quejacq@gmail.com writes: > 1. Storing IP addresses as string is fine as long as you don't need to do > binary operations on these addresses, such as network mask matching. This > is why I was searching for an integer. Moreover, IPv4 addresses can be > stored in the IPv6 format, so keeping one (or more) columns dedicated to > just one "kind" of address is IMHO not a god solution. I agree. That's why I said in my previous email that storing asio::id_address as a composite (i.e., multi-column) value is probably a bad idea. > The best solution for storing as a uinque column is postgresql's inet (or > cidr) type. Alas, MySQL doesn't provide an equivalent field. As a result, I > was hoping to do the manual mapping myself, with the help of some sort of > value_traits class. But, inferring from the declaration of value_traits in > the ODB source code, I suppose this is not currently possible. I am not sure what made you think so. You can map any C++ type to any database type by providing the value_traits specialization. While there is no 16-byte integer type in MySQL (or any other database that I am aware of), the next best thing will probably be a binary representation. You can definitely map asio::id_address to, say, MySQL BINARY(16). The 'mapping' example in the odb-examples package provides a couple of cases that show how to implement this. For instance, it re-maps the C++ bool type to MySQL VARCHAR(5) and stores the boolean values as "true" and "false" string literals. > 2. OK, I understand the technical difficulty. What would you suggest > instead? Create a table that assigns a unique ID for each composite > primary key, and use that as a foreign key in the other table ? Yes, I guess that would be a temporary and not very elegant work around. The other option would be to map (using the value_traits approach mentioned above) a composite ID to a single column by "packing" multiple members into a single-column representation. For instance, if we had a name struct: struct name { string first; string last; }; Then we could map it to a database string type and store the two fields as "first last" or "last,first". > Anyway, thank you again for your fast answer. I don't think ODB will do it > for me on this project, but I will keep an eye on it as I believe it is a > really good solution for ORM in C++. Still, congratulations on what you > have achieved so far :). Thanks, I am glad you like it. Boris