From rkuksin91 at mail.ru Thu Oct 3 06:39:27 2013 From: rkuksin91 at mail.ru (=?UTF-8?B?0KDQvtC80LDQvSDQmtGD0LrRgdC40L0=?=) Date: Thu Oct 3 06:39:39 2013 Subject: [odb-users] Separate database schema. "Unknown database" error Message-ID: <1380796767.323360469@f385.i.mail.ru> Hello! Sorry for my English. I'm trying to create several sqlite files with different database schemas. In this example class one ?should be stored in 1.db file whith? one? schema. Class? two? should be stored similary. ---------------------------- header.h: ---------------------------- #ifndef HEADER_H #define HEADER_H #include //1.db file data #pragma db object schema("one") class one { public: ? ? #pragma db id auto ? ? int id; ? ? float a,b,c; }; //2.db file data #pragma db object schema("two") class two { public: ? ? #pragma db id auto ? ? int id; ? ? int a,b,c; }; #endif ---------------------------- database.h: ---------------------------- #ifndef DATABASE_H #define DATABASE_H #include #include #include #include #include #include inline std::shared_ptr create_database (std::string filename, std::string schemaName = "") { ? ? ? using namespace std; ? ? ? using namespace odb::core; ? ? ? shared_ptr db ( ? ? ? new odb::sqlite::database( filename, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE)); ? ? ? { ? ? ? ? ? ? connection_ptr c (db->connection ()); ? ? ? ? ? ? c->execute ("PRAGMA foreign_keys=OFF"); ? ? ? ? ? ? transaction t (c->begin ()); ? ? ? ? ? ? schema_catalog::create_schema (*db, schemaName); ? ? ? ? ? ? t.commit (); ? ? ? ? ? ? c->execute ("PRAGMA foreign_keys=ON"); ? ? ? } ? ? ? return db; } #endif ---------------------------- main.cpp: ---------------------------- #include "database.h" #include "header.h" #include "header-odb.hxx" int main() { ? ? try ? ? { ? ? ? ? auto db1 = create_database("1.db", "one"); ? ? ? ? auto db2 = create_database("2.db", "two"); ? ? ? ? { ? ? ? ? ? ? odb::transaction t(db1->begin()); ? ? ? ? ? ? db1->persist(one()); ? ? ? ? ? ? t.commit(); ? ? ? ? } ? ? ? ? odb::transaction t(db2->begin()); ? ? ? ? db2->persist(two()); ? ? ? ? t.commit(); ? ? } ? ? catch( odb::database_exception & e ) ? ? { ? ? ? ? std::cout << e.what()< References: <1380796767.323360469@f385.i.mail.ru> Message-ID: Hi ?????, ????? ?????? writes: > I'm trying to create several sqlite files with different database > schemas. > > [...] > > #pragma db object schema("one") > class one > > [...] > > schema_catalog::create_schema (*db, schemaName); > > [...] > > --schema-name one Unfortunately, the term 'schema' means two different things in the relational database world. A schema can mean the database structure, that is tables, columns, etc., and when we say "create schema" we mean create the tables, etc. In some databases, such as Oracle, tables, etc., can be placed into separate namespaces and then we could qualify a table with such a namespace, for example, foo.bar. Unfortunately, such namespaces are also called schema. While some databases don't support schemas (namespaces), they still allow us to qualify table names with some other names. For example, in SQLite, we can attach another database file to an existing connection, give it a name, and then use that name to refer to tables in this file. As a result, in ODB, any kind of table qualification is called 'schema'. What it means exactly is databale dependant. A schema can be assigned either with the schema pragma (as you did in your case) or with the --schema option. When the database schema (i.e., the database structure) is embedded into the generated C++ code, it can sometimes be useful to partition it into multiple segments so that we can create databases only with a certain set of tables, etc. This is exactly what you are trying to achieve. To support this, ODB allows us to assign names to schemas on the per-file basis using the --schema-name option. In other words, if you compile foo.hxx and pass --schema-name 'foo', then the schema for all the persistent classes in this file (and any other file compiled with the same option) will be called "foo". Note the subtle difference between option names: --schema and --schema-name. I think now it should be clear what you need to do: 1. Split your header file into two files each containing one class. 2. Remove the schema pragma. You will only need it if you want to attach both files to the same database instance. 3. Compile the two files and assing each a different schema name: odb ... --schema-name one one.hxx odb ... --schema-name two two.hxx 4. Pass the schema name to create_database: auto db1 = create_database("1.db", "one"); auto db2 = create_database("2.db", "two"); Boris From rkuksin91 at mail.ru Thu Oct 3 09:16:36 2013 From: rkuksin91 at mail.ru (=?UTF-8?B?0KDQvtC80LDQvSDQmtGD0LrRgdC40L0=?=) Date: Thu Oct 3 09:16:43 2013 Subject: =?UTF-8?B?UmVbMl06IFtvZGItdXNlcnNdIFNlcGFyYXRlIGRhdGFiYXNlIHNjaGVtYS4g?= =?UTF-8?B?IlVua25vd24gZGF0YWJhc2UiIGVycm9y?= In-Reply-To: References: <1380796767.323360469@f385.i.mail.ru> Message-ID: <1380806196.930183916@f297.i.mail.ru> Thanks for help! ODB is amazing! ------------------------------------------------------------------------------------------------------ ? ?????????. ????? ??????. From boris at codesynthesis.com Sat Oct 5 05:32:16 2013 From: boris at codesynthesis.com (Boris Kolpackov) Date: Sat Oct 5 05:34:41 2013 Subject: [odb-users] libodb-sqlite 2.2.3 bugfix released Message-ID: Hi, A new bugfix release for the SQLite ODB runtime library (libodb-sqlite) is now available. Strictly speaking, this is not a bigfix since it only adds support for lower versions of SQLite than was previously supported. Now ODB supports SQLite 3.3.6 (which is found in RHEL5) and later. You can download the new packages from the ODB download page: http://www.codesynthesis.com/products/odb/download.xhtml SHA1 checksums for the files in this release are as follows: e85307ae589d2daa241dd83404ecb10edb77eb62 libodb-sqlite-2.2.3.tar.bz2 5b404764cba0475703a969103ff97e633135eaf2 libodb-sqlite-2.2.3.tar.gz a1f8d925fab4450f802af13b88bdabeab259e75b libodb-sqlite-2.2.3.zip Boris From Paul.Harrison at manchester.ac.uk Mon Oct 7 14:48:17 2013 From: Paul.Harrison at manchester.ac.uk (Paul Harrison) Date: Mon Oct 7 14:48:21 2013 Subject: [odb-users] Correct way to create query on column of referred to table in one-to-one relationship Message-ID: <18BFC6EF-71F3-49DB-ADCD-9528E3C75D5E@manchester.ac.uk> Hi, I have a model where there is a on-to-one relationship with a child object #pragma db object table("Data_Descriptor") class Data_Descriptor_P { // many members omitted for clarity? #pragma db column("datloc") shared_ptr _data_location;//!< Data location } #pragma db object table("DataLocation") class Data_Location_P { // many members omitted for clarity? #pragma db type("VARCHAR(255)") column("loc") std::string _location;//!< Path to data } And I want to created a query that selects on the _location member of Data_Location_P I have tried typedef odb::query DDQuery; typedef odb::query DLQuery; DDQuery query = DDQuery (DLQuery::location == DLQuery::_val("tmp")) but (on MySQL at least) this fails with mysql exception1054 (42S22): Unknown column 'DataLocation.loc' in 'where clause' because the eventual SQL that is produced is SELECT ?. `Data_Descriptor`.`datloc` FROM `Data_Descriptor` LEFT JOIN `DataLocation` AS `datloc` ON `datloc`.`id`=`Data_Descriptor`.`datloc` WHERE `DataLocation`.`loc` ="tmp" and it seems that MySQL only likes SELECT ?. `Data_Descriptor`.`datloc` FROM `Data_Descriptor` LEFT JOIN `DataLocation` AS `datloc` ON `datloc`.`id`=`Data_Descriptor`.`datloc` WHERE `dataloc.`loc` ="tmp" i.e. the table can only be referred to by the AS alias in the WHERE clause. This seems like a MySQL bug to me, and I will report it as such. However, given that the likely timescale of a fix on MySQL is long, do you have any suggestions for workarounds? As you can see I have been experimenting with some naming pragmas, but have not found a combination that will produce something that MySQL will accept. Regards, Paul Harrison. From boris at codesynthesis.com Mon Oct 7 14:59:28 2013 From: boris at codesynthesis.com (Boris Kolpackov) Date: Mon Oct 7 15:01:53 2013 Subject: [odb-users] Correct way to create query on column of referred to table in one-to-one relationship In-Reply-To: <18BFC6EF-71F3-49DB-ADCD-9528E3C75D5E@manchester.ac.uk> References: <18BFC6EF-71F3-49DB-ADCD-9528E3C75D5E@manchester.ac.uk> Message-ID: Hi Paul, Paul Harrison writes: > typedef odb::query DDQuery; > typedef odb::query DLQuery; > > DDQuery query = DDQuery (DLQuery::location == DLQuery::_val("tmp")) I think what you are looking for is this: typedef odb::query DDQuery; DDQuery q = DDQuery::data_location->location == DLQuery::_val("tmp"); In other words, you can use query members that correspond to object pointers "as if" they were actual pointers. Boris From Paul.Harrison at manchester.ac.uk Mon Oct 7 15:05:31 2013 From: Paul.Harrison at manchester.ac.uk (Paul Harrison) Date: Mon Oct 7 15:05:34 2013 Subject: [odb-users] Correct way to create query on column of referred to table in one-to-one relationship In-Reply-To: <18BFC6EF-71F3-49DB-ADCD-9528E3C75D5E@manchester.ac.uk> References: <18BFC6EF-71F3-49DB-ADCD-9528E3C75D5E@manchester.ac.uk> Message-ID: On 2013-10 -07, at 19:48, Paul Harrison wrote: > Hi, > > I have a model where there is a on-to-one relationship with a child object > > #pragma db object table("Data_Descriptor") > class Data_Descriptor_P { > // many members omitted for clarity? > #pragma db column("datloc") > shared_ptr _data_location;//!< Data location > > } > > #pragma db object table("DataLocation") > class Data_Location_P { > // many members omitted for clarity? > #pragma db type("VARCHAR(255)") column("loc") > std::string _location;//!< Path to data > > } > > And I want to created a query that selects on the _location member of Data_Location_P > > I have tried > > typedef odb::query DDQuery; > typedef odb::query DLQuery; > > DDQuery query = DDQuery (DLQuery::location == DLQuery::_val("tmp")) > > but (on MySQL at least) this fails with > > mysql exception1054 (42S22): Unknown column 'DataLocation.loc' in 'where clause' > > because the eventual SQL that is produced is > > SELECT ?. > `Data_Descriptor`.`datloc` > FROM `Data_Descriptor` > LEFT JOIN `DataLocation` AS `datloc` ON `datloc`.`id`=`Data_Descriptor`.`datloc` > WHERE `DataLocation`.`loc` ="tmp" > > and it seems that MySQL only likes > > SELECT ?. > `Data_Descriptor`.`datloc` > FROM `Data_Descriptor` > LEFT JOIN `DataLocation` AS `datloc` ON `datloc`.`id`=`Data_Descriptor`.`datloc` > WHERE `dataloc.`loc` ="tmp" > > i.e. the table can only be referred to by the AS alias in the WHERE clause. This seems like a MySQL bug to me, and I will report it as such. However, given that the likely timescale of a fix on MySQL is long, do you have any suggestions for workarounds? As you can see I have been experimenting with some naming pragmas, but have not found a combination that will produce something that MySQL will accept. > Actually I have just found what will work? make sure that Data_Location_P table name and the Data_Descriptor location column have pragmas that give them identical names including using the same case, then it ends up with "Data_Descriptor`.`DataLocation`" " FROM `Data_Descriptor`" " LEFT JOIN `DataLocation` AS `DataLocation` ON `DataLocation`.`id`=`Data_Descriptor`.`DataLocation`" WHERE `DataLocation`.`loc` ="tmp" a bit of a hack?. From canismajorwuff at gmail.com Tue Oct 15 16:20:09 2013 From: canismajorwuff at gmail.com (CanisMajorWuff) Date: Wed Oct 16 00:39:36 2013 Subject: [odb-users] make error during ODB runtime build Message-ID: <525DA379.8050505@gmail.com> Hello, Any ideas? Configuring ODB with the command: sh -c "C:/Users/CanisMajor/Downloads/Soft/ODB/2.2.3/configure --prefix='D:/Software/ODB/2.2.3'" checking for a BSD-compatible install... /usr/bin/install -c checking whether build environment is sane... yes checking for a thread-safe mkdir -p... /usr/bin/mkdir -p checking for gawk... gawk checking whether make sets $(MAKE)... yes checking how to create a ustar tar archive... gnutar checking for style of include used by make... GNU checking for gcc... gcc checking whether the C compiler works... yes checking for C compiler default output file name... a.exe checking for suffix of executables... .exe checking whether we are cross compiling... no checking for suffix of object files... o checking whether we are using the GNU C compiler... yes checking whether gcc accepts -g... yes checking for gcc option to accept ISO C89... none needed checking dependency style of gcc... gcc3 checking for ar... ar checking the archiver (ar) interface... ar checking build system type... i686-pc-mingw32 checking host system type... i686-pc-mingw32 checking how to print strings... printf checking for a sed that does not truncate output... /usr/bin/sed checking for grep that handles long lines and -e... /usr/bin/grep checking for egrep... /usr/bin/grep -E checking for fgrep... /usr/bin/grep -F checking for ld used by gcc... d:/mingw/x86_64-w64-mingw32/bin/ld.exe checking if the linker (d:/mingw/x86_64-w64-mingw32/bin/ld.exe) is GNU ld... yes checking for BSD- or MS-compatible name lister (nm)... /mingw/bin/nm checking the name lister (/mingw/bin/nm) interface... BSD nm checking whether ln -s works... no, using cp -pR checking the maximum length of command line arguments... 8192 checking whether the shell understands some XSI constructs... yes checking whether the shell understands "+="... yes checking how to convert i686-pc-mingw32 file names to i686-pc-mingw32 format... func_convert_file_msys_to_w32 checking how to convert i686-pc-mingw32 file names to toolchain format... func_convert_file_msys_to_w32 checking for d:/mingw/x86_64-w64-mingw32/bin/ld.exe option to reload object files... -r checking for objdump... objdump checking how to recognize dependent libraries... file_magic ^x86 archive import|^x86 DLL checking for dlltool... dlltool checking how to associate runtime and link libraries... func_cygming_dll_for_implib checking for archiver @FILE support... @ checking for strip... strip checking for ranlib... ranlib checking command to parse /mingw/bin/nm output from gcc object... ok checking for sysroot... no checking for mt... no checking if : is a manifest tool... no checking how to run the C preprocessor... gcc -E checking for ANSI C header files... yes checking for sys/types.h... yes checking for sys/stat.h... yes checking for stdlib.h... yes checking for string.h... yes checking for memory.h... yes checking for strings.h... yes checking for inttypes.h... yes checking for stdint.h... yes checking for unistd.h... yes checking for dlfcn.h... no checking for as... as checking for dlltool... (cached) dlltool checking for objdump... (cached) objdump checking for objdir... .libs checking if gcc supports -fno-rtti -fno-exceptions... no checking for gcc option to produce PIC... -DDLL_EXPORT -DPIC checking if gcc PIC flag -DDLL_EXPORT -DPIC works... yes checking if gcc static flag -static works... yes checking if gcc supports -c -o file.o... yes checking if gcc supports -c -o file.o... (cached) yes checking whether the gcc linker (d:/mingw/x86_64-w64-mingw32/bin/ld.exe) supports shared libraries... yes checking whether -lc should be explicitly linked in... yes checking dynamic linker characteristics... Win32 ld.exe checking how to hardcode library paths into programs... immediate checking whether stripping libraries is possible... yes checking if libtool supports shared libraries... yes checking whether to build shared libraries... yes checking whether to build static libraries... yes checking for g++... g++ checking whether we are using the GNU C++ compiler... yes checking whether g++ accepts -g... yes checking dependency style of g++... gcc3 checking how to run the C++ preprocessor... g++ -E checking for ld used by g++... d:/mingw/x86_64-w64-mingw32/bin/ld.exe checking if the linker (d:/mingw/x86_64-w64-mingw32/bin/ld.exe) is GNU ld... yes checking whether the g++ linker (d:/mingw/x86_64-w64-mingw32/bin/ld.exe) supports shared libraries... yes checking for g++ option to produce PIC... -DDLL_EXPORT -DPIC checking if g++ PIC flag -DDLL_EXPORT -DPIC works... yes checking if g++ static flag -static works... yes checking if g++ supports -c -o file.o... yes checking if g++ supports -c -o file.o... (cached) yes checking whether the g++ linker (d:/mingw/x86_64-w64-mingw32/bin/ld.exe) supports shared libraries... yes checking dynamic linker characteristics... Win32 ld.exe checking how to hardcode library paths into programs... immediate configure: creating ./config.lt config.lt: creating libtool checking whether to use rpath... yes checking that generated files are newer than configure... done configure: creating ./config.status config.status: creating libodb.pc config.status: creating Makefile config.status: creating odb/Makefile config.status: creating odb/config.h config.status: creating odb/details/config.h config.status: executing depfiles commands config.status: executing libtool commands config.status: executing libtool-rpath-patch commands Making all in odb make.exe[1]: Entering directory `/c/Users/CanisMajor/Downloads/Trash/build/ODB/2.2.3/odb' make.exe all-am make.exe[2]: Entering directory `/c/Users/CanisMajor/Downloads/Trash/build/ODB/2.2.3/odb' make.exe[2]: *** No rule to make target `callback.lo', needed by `libodb.la'. Stop. make.exe[2]: Leaving directory `/c/Users/CanisMajor/Downloads/Trash/build/ODB/2.2.3/odb' make.exe[1]: *** [all] Error 2 make.exe[1]: Leaving directory `/c/Users/CanisMajor/Downloads/Trash/build/ODB/2.2.3/odb' make.exe: *** [all-recursive] Error 1 From boris at codesynthesis.com Wed Oct 16 02:44:04 2013 From: boris at codesynthesis.com (Boris Kolpackov) Date: Wed Oct 16 02:46:28 2013 Subject: [odb-users] make error during ODB runtime build In-Reply-To: <525DA379.8050505@gmail.com> References: <525DA379.8050505@gmail.com> Message-ID: Hi, CanisMajorWuff writes: > make.exe[2]: *** No rule to make target `callback.lo', needed by So you are building libodb-2.2.3 in a separate build directory on MinGW. Here is what I just tried using the MSYS shell that comes in the ODB compiler package for Windows (mingw/msys.bat): $ unzip libodb-2.2.3.zip $ mkdir libodb-2.2.3-build $ cd libodb-2.2.3-build $ ../libodb-2.2.3/configure $ make And everything builds just fine. So there must be something wrong with your MinGW environment. Boris From hjiemin at dso.org.sg Wed Oct 16 22:10:21 2013 From: hjiemin at dso.org.sg (Huang Jiemin) Date: Wed Oct 16 23:52:16 2013 Subject: [odb-users] ODB Support for Boost dynamic_bitset Message-ID: <303F6F35DCEC784ABE5F39CBD6099B694A21F9@Gawain.dsonet.corp.root> Hi, I'm new to ODB and I would like to find out if ODB supports Boost dynamic_bitset to any type in MS SQL? I couldn't find any information on dynamic_bitset in the documentation. Thanks Warmest Regards, Jiemin From boris at codesynthesis.com Thu Oct 17 00:47:56 2013 From: boris at codesynthesis.com (Boris Kolpackov) Date: Thu Oct 17 00:50:20 2013 Subject: [odb-users] ODB Support for Boost dynamic_bitset In-Reply-To: <303F6F35DCEC784ABE5F39CBD6099B694A21F9@Gawain.dsonet.corp.root> References: <303F6F35DCEC784ABE5F39CBD6099B694A21F9@Gawain.dsonet.corp.root> Message-ID: Hi Jiemin, Huang Jiemin writes: > I'm new to ODB and I would like to find out if ODB supports Boost > dynamic_bitset to any type in MS SQL? I couldn't find any information > on dynamic_bitset in the documentation. There is no built-in support for boost::dynamic_bitset. I guess the most natural database type to map it to is BINARY/BLOB. You can easily implement this mapping yourself as explained in this article: http://www.codesynthesis.com/~boris/blog/2012/10/16/custom-cxx-to-database-type-mapping-in-odb/ If you want a quick a dirty solution, then you can map it to string in the database with a help of a virtual data member, for example: #pragma db object class object { ... #pragma db transient boost::dynamic_bitset<> data_; std::string data_as_string () const { std::string s; boost::to_string (data_, s); return s; } void data_from_string (const std::string& s) { data_ = boost::dynamic_bitset<> (s); } #pragma db member(data) virtual(std::string) \ get(data_as_string) set(data_from_string) }; Boris From durga.disc at gmail.com Sun Oct 20 07:15:06 2013 From: durga.disc at gmail.com (dd) Date: Sun Oct 20 07:15:34 2013 Subject: [odb-users] schema_catalog::exists Message-ID: Hi Boris, I tried with below line to find out where test.db exists or not? bool b = odb::schema_catalog::exists(odb::id_sqlite, "test.db"); It's always returning false even though database exists. What is the correct way to find the database existence. If not, I have to create the test.db. Thanks, dd From durga.disc at gmail.com Sun Oct 20 08:39:41 2013 From: durga.disc at gmail.com (dd) Date: Sun Oct 20 08:40:09 2013 Subject: [odb-users] how to compile shared_ptr with person.hxx Message-ID: Hi Boris, Assume, person.hxx has member variable with shared_ptr. odb -d sqlite --generate-query --generate-schema person.hxx It's throwing compilation errors. Any idea? Thanks. From boris at codesynthesis.com Mon Oct 21 02:50:24 2013 From: boris at codesynthesis.com (Boris Kolpackov) Date: Mon Oct 21 02:52:48 2013 Subject: [odb-users] schema_catalog::exists In-Reply-To: References: Message-ID: Hi, dd writes: > I tried with below line to find out where test.db exists or not? > > bool b = odb::schema_catalog::exists(odb::id_sqlite, "test.db"); No, this is not going to work. schema_catalog::exists() checks whether a schema exists in the application, not whether a database file exists on disk. In fact, I am very surprised you got this impression after reading the documentation. Perhaps you *did not* read the documentation? > What is the correct way to find the database existence. If not, I > have to create the test.db. The recommended way is to pass the SQLITE_OPEN_CREATE flag to the odb::sqlite::database constructor. This will create an empty database file if one does not exist. Then you will need detect the empty database case and create the schema. In the upcoming version of ODB there will be a proper way of detecting this as part of the schema evolution support. For now you can run a native query like this: if (db.execute ("SELECT 1 FROM sqlite_master " "WHERE type='table' AND name=''") == 0) { schema_catalog::create_schema (db); } Where is a name of a table corresponding to one of your persistent classes. Boris From boris at codesynthesis.com Mon Oct 21 02:52:25 2013 From: boris at codesynthesis.com (Boris Kolpackov) Date: Mon Oct 21 02:54:48 2013 Subject: [odb-users] how to compile shared_ptr with person.hxx In-Reply-To: References: Message-ID: Hi, dd writes: > Assume, person.hxx has member variable with shared_ptr. > > odb -d sqlite --generate-query --generate-schema person.hxx > > It's throwing compilation errors. What errors? Do you want me to guess? Boris From daniel.the.programmer at gmail.com Tue Oct 29 10:34:50 2013 From: daniel.the.programmer at gmail.com (Daniel) Date: Tue Oct 29 10:35:01 2013 Subject: [odb-users] Why do I get an odb::object_not_persistent error in this test program? Message-ID: <526FC78A.7020600@gmail.com> Hi, I'm getting an odb::object_not_persistent error. I've narrowed the problem down to this (see attachment), yet do not know what I'm doing wrong. This code mimics what happens in the real software program but with a lot less code. I've verified that the error occurs when running this code even when the database is emptied/truncated. Help MUCH appreciated. Thanks, Daniel -------------- next part -------------- A non-text attachment was scrubbed... Name: object_not_persistent error_isolated.tar.gz Type: application/gzip Size: 1115 bytes Desc: not available Url : http://codesynthesis.com/pipermail/odb-users/attachments/20131029/f16b216a/object_not_persistenterror_isolated.tar.bin From boris at codesynthesis.com Wed Oct 30 01:11:11 2013 From: boris at codesynthesis.com (Boris Kolpackov) Date: Wed Oct 30 01:13:35 2013 Subject: [odb-users] Why do I get an odb::object_not_persistent error in this test program? In-Reply-To: <526FC78A.7020600@gmail.com> References: <526FC78A.7020600@gmail.com> Message-ID: Hi Daniel, Daniel writes: > I'm getting an odb::object_not_persistent error. In your updater_thread() function you have this code: if(parent->children.size() > 0) { database_global->erase((*parent->children.begin())->id); parent->children.erase(parent->children.begin()); } That is, you erase the child object from the database and then erase it from the parent's list of children. But you do not update the parent to reflect this change in the database. In other words, you need to add something like this: database_global->update (*parent); Note also that normally you should have gotten a foreign key constraint violation at the end of this transaction. However, because MySQL does not support deferred foreign keys, ODB generates all such constraints commented out (you can see that in the generated .sql file). As a result, you get the object_not_persistent exception in some other transaction instead, which makes it quite a bit harder to figure out. Also, in the upcoming release we've added an option to the ODB compiler to use immediate constraints. While enabling this will require a lot more discipline in the order in which you persist/erase related objects, it will also make it easier to debug cases like this. Boris From boris at codesynthesis.com Wed Oct 30 05:53:02 2013 From: boris at codesynthesis.com (Boris Kolpackov) Date: Wed Oct 30 05:55:26 2013 Subject: [odb-users] ODB 2.3.0 released Message-ID: Hi, We have released ODB 2.3.0. The NEWS file entries for this release are as follows: * Support for database schema evolution, including schema migration, data migration, and soft model changes. For more information, refer to Chapter 13, "Database Schema Evolution" in the ODB manual. * Support for object sections. Sections are an optimization mechanism that allows the partitioning of data members of a persistent class into groups that can be loaded and/or updated separately. For more information, refer to Chapter 9, "Sections" in the ODB manual as well as the 'section' example in the odb-examples package. * Support for automatic mapping of C++11 enum classes in addition to "old" enums. For more information, refer to the ODB manual "Type Mapping" sections for each database system. * Support for defining composite value types inside persistent classes, views, and other composite values. For more information, refer to Section 7.2, "Composite Value Types" in the ODB manual. * Support for pattern matching (SQL LIKE operator) in the C++-integrated queries. For more information, refer to Section 4.1, "ODB Query Language" in the ODB manual. * The schema_catalog::create_schema() function now has a third argument which indicates whether to drop the schema prior to creating the new one. The default is true which is backwards-compatible. The schema_catalog class now also provides the drop_schema() function which allows you to drop the schema without creating the new one. Finally, the exists() function now has the schema name argument which by default is an empty string (the default schema name). For more information, refer to Section 3.4, "Database" in the ODB manual. * The transaction class now provides the default constructor that allows the creation of finalized transactions which can then be re-initialized with the reset() function. The finalized() accessor has also been added which allows querying of the finalization state. For more information, refer to Section 3.5, "Transactions" in the ODB manual. * New option, --fkeys-deferrable-mode, specifies the alternative deferrable mode for foreign keys. By default, the ODB compiler generates deferred foreign keys for databases that support them (SQLite, PostgreSQL, and Oracle) and comments the foreign keys out for databases that don't (MySQL and SQL Server). This option can be used to override this behavior. Refer to the ODB compiler command line interface documentation (man pages) for details. * Starting with MySQL version 5.6.4 it is possible to store fractional seconds up to microsecond precision in TIME, DATETIME, and TIMESTAMP columns. Both Boost and Qt profiles have been updated to support this new functionality. Note, however, that to enable sub-second precision, the corresponding type with the desired precision has to be specified explicitly. For details, refer to the "MySQL Database Type Mapping" sections in the Boost and Qt profile chapters. * New SQLite-specific exception, odb::sqlite::forced_rollback, which is thrown if SQLite forces a transaction to roll back. For more information, refer to Section 16.5.6, "Forced Rollback" in the ODB manual. * New options, --pgsql-server-version, can be used to specify the minimum PostgreSQL server version with which the generated C++ code and schema will be used. Right now this information is used to enable the use of the IF NOT EXISTS clause in the CREATE TABLE statement for the schema version table creation in PostgreSQL 9.1 and later. Refer to the ODB compiler command line interface documentation (man pages) for details. * The --output-name option has been renamed to --input-name, which is more semantically correct. * The generated database schema now explicitly specify NULL for nullable columns. * The generated separate C++ schema file (--schema-format separate) no longer includes the generated header file (-odb.hxx). As a result, it is now possible to use the --generate-schema-only and --at-once options to generate a combined C++ schema file for several headers. This release also adds support for Visual Studio 2005 (VC++ 8.0), including project/solution files for all the runtimes, tests, and examples. A more detailed discussion of the major new features can be found in the following blog post: http://www.codesynthesis.com/~boris/blog/2013/10/30/odb-2-3-0-released/ This release has been tested with a large number of platform/compiler/ architecture/library combinations. Specifically: Platform Compiler Version C++ Std Arch Qt Boost Databases ------------------------------------------------------------------------- GNU/Linux GCC 4.4-4.8 C++98,11 x86 32/64 4,5 Y All GNU/Linux Clang 3.3 C++98,11 x86 64 4 Y All Raspberry Pi GCC 4.7 C++98 arm - - SQLite Solaris Sun CC 12u2 Cstd x86 32/64 - - All ex MS SQL Solaris Sun CC 12u2 STLPort x86 32/64 - - All ex MS SQL Solaris Sun CC 12u2 Cstd SPARC 32/64 - - All ex MS SQL Mac OS X GCC 4.2 C++98 x86 32 4 Y All ex MS SQL Windows VC++ 8.0 C++98 x86 32/64 - Y All Windows VC++ 9.0 C++98 x86 32/64 4 Y All Windows VC++ 10.0 C++11 x86 32/64 4,5 Y All Windows VC++ 11.0 C++11 x86 32/64 4 Y All MinGW-W64 GCC 4.7 C++98 x86 32 5 Y All We would also like to thank everyone who reported bugs, suggested fixes or new features, as well as tested early versions of this release. 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: eebc7fa706bc598a80439d1d6a798430fcfde23b libodb-2.3.0.tar.bz2 8ac9a09a6a86e73951289ee79c022661caea7f96 libodb-2.3.0.tar.gz 4931b091e925b7f578fa2fdb82dcdc02e7bb5fa9 libodb-2.3.0.zip 0e6c8e256834b11a98e946cde23a01d9b8023c4b libodb-boost-2.3.0.tar.bz2 38c8552db872cc32144fb653c19277cfec1df2ec libodb-boost-2.3.0.tar.gz 33dcda84aeae00acc6fd1ac4d47bccfb1fc57838 libodb-boost-2.3.0.zip 29fe362fc0028022ff5c5e6a8b7e434626125916 libodb-mssql-2.3.0.tar.bz2 2cd48850870782c74fdc92c223877c0c05e72494 libodb-mssql-2.3.0.tar.gz 7fc50e8b1b5a392a16cbab3aedacf6f2b56cab68 libodb-mssql-2.3.0.zip 18adaa5535015e3471a5d205e44df42f0e3a3d37 libodb-mysql-2.3.0.tar.bz2 72f92fd60a58cc4b34a8fea23a262dfdaa6c776c libodb-mysql-2.3.0.tar.gz 8c35cb74ac11b81c49e854505577a0e603307b57 libodb-mysql-2.3.0.zip 365bc27ccf5855674b9dd3b976dba02ec59d15a0 libodb-oracle-2.3.0.tar.bz2 2138b5d7f3e27335f9d80e178e6baa8b7bd0c6ef libodb-oracle-2.3.0.tar.gz e20b369200e5bcc36e391cfd7117d20431369032 libodb-oracle-2.3.0.zip 0cc3597602550b7a98c0d532935fdefc51ad9cd7 libodb-pgsql-2.3.0.tar.bz2 2b4e82d4d15135959867158a8e6453e80a36e773 libodb-pgsql-2.3.0.tar.gz 8ac439ec78595ec9cf2d4c20359778bdd9572d91 libodb-pgsql-2.3.0.zip ade562088b28cfefd889649cdc44666a366147e4 libodb-qt-2.3.0.tar.bz2 ff543576ff7048a2b489ba550f3e569c3afc6534 libodb-qt-2.3.0.tar.gz 2c105ee34d3023b41bcc2615d015798873fcdd86 libodb-qt-2.3.0.zip 512a124e0b78ae36deee25d595e3e169bd24d216 libodb-sqlite-2.3.0.tar.bz2 2643d3c2c3f273f3fb223759e4ad10635cc91ce8 libodb-sqlite-2.3.0.tar.gz fb477d054e59a443d2d890b9ca65557293ecb4c3 libodb-sqlite-2.3.0.zip 31d45bd900de198fd136d671c9e2a2ffdb98cf01 odb_2.3.0-1_amd64.deb 1db91284de3965c352158419e5d8bfbae50ad6de odb_2.3.0-1_i386.deb 65c4bab0c453868debeabd609cc1e38198fe85d0 odb-2.3.0-1.i686.rpm 590e10d17dd8ab8b46c65fc1a577bd0d7d471f5a odb-2.3.0-1.x86_64.rpm 1db06f531400af2cf156fe38bcd691c81b4c4ce4 odb-2.3.0-i686-linux-gnu.tar.bz2 7bdde23582d8e6f57d5a2fffd9fa77ab35de5bcc odb-2.3.0-i686-macosx.tar.bz2 e9b4c688f52f1a9abea6c1f1b4adac648d193127 odb-2.3.0-i686-solaris.tar.bz2 0539193c614356fa120b2ebdb1d2e9c6fcdd7dcd odb-2.3.0-i686-windows.zip 7e802e0a8e92887827e3e19ec2c9d201091fa3dc odb-2.3.0-sparc-solaris.tar.bz2 fe18c7154085afec23c18aa940f168de7068f6f3 odb-2.3.0.tar.bz2 53c851e3f3724b72d7c7a74c497c50c195729ad1 odb-2.3.0.tar.gz 0a63f284263d68795359e6ce367a43476262d335 odb-2.3.0-x86_64-linux-gnu.tar.bz2 eabae10279c24bb5d3bdc740ba025766348cd916 odb-2.3.0.zip c044da7df142a0147550c659c282f7d63b9abf86 odb-examples-2.3.0.tar.bz2 e244836bb009317cdd1cb3cd16e8acf2b0d0fc0d odb-examples-2.3.0.tar.gz dc950e8f73bc978500386f414c490eb64daa121c odb-examples-2.3.0.zip d23966564030d899355231756e2b93ec76e300c1 odb-tests-2.3.0.tar.bz2 3f0b615da8f655d0aa58790078ec59ab0037a65e odb-tests-2.3.0.tar.gz 7a3a9dfa1da7da999c2865850f5f4df613d13e39 odb-tests-2.3.0.zip Enjoy, Boris From daniel.the.programmer at gmail.com Wed Oct 30 07:27:52 2013 From: daniel.the.programmer at gmail.com (Daniel) Date: Wed Oct 30 07:28:02 2013 Subject: [odb-users] Why do I get an odb::object_not_persistent error in this test program? In-Reply-To: References: <526FC78A.7020600@gmail.com> Message-ID: <5270ED38.7040300@gmail.com> Hi Boris, Thank you for your quick reply. I've added database_global->update(parent.get()); after parent->children.erase(parent->children.begin()); but the same error still occurs. I've also upgraded to odb-2.3.0 and "--fkeys-deferrable-mode immediate" to the compiler line. It now looks like this: odb -p boost/date-time -d mysql --std c++11 --generate-query --fkeys-deferrable-mode immediate --generate-schema models.h What else could be wrong? Thanks, Daniel On 10/30/2013 06:11 AM, Boris Kolpackov wrote: > Hi Daniel, > > Daniel writes: > >> I'm getting an odb::object_not_persistent error. > In your updater_thread() function you have this code: > > if(parent->children.size() > 0) > { > database_global->erase((*parent->children.begin())->id); > parent->children.erase(parent->children.begin()); > } > > That is, you erase the child object from the database and then > erase it from the parent's list of children. But you do not > update the parent to reflect this change in the database. In > other words, you need to add something like this: > > database_global->update (*parent); > > Note also that normally you should have gotten a foreign key > constraint violation at the end of this transaction. However, > because MySQL does not support deferred foreign keys, ODB > generates all such constraints commented out (you can see > that in the generated .sql file). As a result, you get the > object_not_persistent exception in some other transaction > instead, which makes it quite a bit harder to figure out. > > Also, in the upcoming release we've added an option to the > ODB compiler to use immediate constraints. While enabling > this will require a lot more discipline in the order in > which you persist/erase related objects, it will also make > it easier to debug cases like this. > > Boris From boris at codesynthesis.com Wed Oct 30 08:49:47 2013 From: boris at codesynthesis.com (Boris Kolpackov) Date: Wed Oct 30 08:52:12 2013 Subject: [odb-users] Why do I get an odb::object_not_persistent error in this test program? In-Reply-To: <5270ED38.7040300@gmail.com> References: <526FC78A.7020600@gmail.com> <5270ED38.7040300@gmail.com> Message-ID: Hi Daniel, Daniel writes: > but the same error still occurs. Ok, I've figured this out. The first problem I mentioned in my email is real. It's just there is another one. In your server_thread() you have two transactions. In the first you load all the Parent objects. And in the second you add more children to them. The problem is between these two transactions your updater_thread() can (and does) modify (in the database) one of the loaded object by erasing its children. As a result, when you try to update the object in the second transaction (in server_thread), you attempt to store old (erased) child ids. If you need the two transactions, one way to fix this would be to store just the object ids in the first transaction and actually load the objects in the second. > "--fkeys-deferrable-mode immediate" If you want foreign key constraints in MySQL, then you should use 'not_deferrable' instead of 'immediate'. Once you do this, your code in updater_thread() should look something along these lines (i.e., you need to do things in a certain order): unsigned int id = (*parent->children.begin())->id; parent->children.erase(parent->children.begin()); database_global->update (parent.get ()); database_global->erase(id); Boris From daniel.the.programmer at gmail.com Wed Oct 30 09:31:20 2013 From: daniel.the.programmer at gmail.com (Daniel) Date: Wed Oct 30 09:31:35 2013 Subject: [odb-users] Why do I get an odb::object_not_persistent error in this test program? In-Reply-To: References: <526FC78A.7020600@gmail.com> <5270ED38.7040300@gmail.com> Message-ID: <52710A28.6040400@gmail.com> Hi Boris, Thank you for your help - it all works perfectly now! I now use database_global->reload(parents[0]); at the start of the second transaction in server_thread(). (see attachment) I wonder if this is the right solution? Do I need to use a mutex here, or does this solution always work? Kind regards, Daniel On 10/30/2013 01:49 PM, Boris Kolpackov wrote: > Hi Daniel, > > Daniel writes: > >> but the same error still occurs. > Ok, I've figured this out. The first problem I mentioned in my email > is real. It's just there is another one. > > In your server_thread() you have two transactions. In the first > you load all the Parent objects. And in the second you add more > children to them. The problem is between these two transactions > your updater_thread() can (and does) modify (in the database) one > of the loaded object by erasing its children. As a result, when > you try to update the object in the second transaction (in > server_thread), you attempt to store old (erased) child ids. > > If you need the two transactions, one way to fix this would be > to store just the object ids in the first transaction and actually > load the objects in the second. > > >> "--fkeys-deferrable-mode immediate" > If you want foreign key constraints in MySQL, then you should use > 'not_deferrable' instead of 'immediate'. Once you do this, your > code in updater_thread() should look something along these lines > (i.e., you need to do things in a certain order): > > unsigned int id = (*parent->children.begin())->id; > parent->children.erase(parent->children.begin()); > database_global->update (parent.get ()); > database_global->erase(id); > > Boris -------------- next part -------------- A non-text attachment was scrubbed... Name: main.cpp Type: text/x-c++src Size: 2120 bytes Desc: not available Url : http://codesynthesis.com/pipermail/odb-users/attachments/20131030/0ba682aa/main.cpp From boris at codesynthesis.com Thu Oct 31 01:49:46 2013 From: boris at codesynthesis.com (Boris Kolpackov) Date: Thu Oct 31 01:52:09 2013 Subject: [odb-users] Why do I get an odb::object_not_persistent error in this test program? In-Reply-To: <52710A28.6040400@gmail.com> References: <526FC78A.7020600@gmail.com> <5270ED38.7040300@gmail.com> <52710A28.6040400@gmail.com> Message-ID: Hi Daniel, Daniel writes: > I now use database_global->reload(parents[0]); at the start of the > second transaction in server_thread(). > > I wonder if this is the right solution? A more efficient way would be what I described in my previous email: only load object ids in the first transaction. For a more general solution to this problem (i.e., long-lived application transactions), you may want to take a look at optimistic concurrency (Chapter 12). > Do I need to use a mutex here, or does this solution always work? You can't really use a mutex here since it is the state of the object in the database that is modified concurrently. Boris