From dcoffey at netharmonix.com Mon Aug 1 10:54:24 2011 From: dcoffey at netharmonix.com (Dan Coffey) Date: Mon Aug 1 10:54:30 2011 Subject: [odb-users] error adding QString to person example 1.5.0 Message-ID: <4E36BE20.4090801@netharmonix.com> Hi Boris, I'm building your examples using Qt Creator. I've renamed the person class - Rdolls All worked will until I add a QString to the Rdolls class. Qt will compile correctly but when I post process I get this error: rdolls.h:22:11: error: unable to map C++ type '::QString' used in data member 'middle_' to a database type rdolls.h:22:11: info: use '#pragma db type' to specify the database type line 22 is QString middle_; (I also tried this using the employee class in the qt directory and get the same error, Qt will compile but I get this same post processing error) #ifndef RDOLLS_H #define RDOLLS_H *#include * #include #include #include "rdolls_global.h" #pragma db object class RDOLLSSHARED_EXPORT Rdolls { public: Rdolls(); private: friend class odb::access; #pragma db id auto unsigned long id_; QString middle_; std::string first_; std::string last_; unsigned short age_; }; #endif // RDOLLS_H Without the two lines: * #include * QStringmiddle_; The Rdolls class builds correctly in Qt. And I then post process with the command: odb -d mysql --generate-query --generate-schema rdolls.h -I/usr/local/include/mysql -I/usr/local/include/qt4/ -I/usr/local/include/boost -I/usr/local/include -I/usr/local/include/odb And the expected files are generated and I have loaded the sql into the mysql db. -rw-r--r-- 1 Dan Coffey Administrators 15638 Aug 1 09:40 rdolls-odb.cxx -rw-r--r-- 1 Dan Coffey Administrators 4616 Aug 1 09:40 rdolls-odb.hxx -rw-r--r-- 1 Dan Coffey Administrators 1359 Aug 1 09:40 rdolls-odb.ixx -rw-r--r-- 1 Dan Coffey Administrators 326 Aug 1 09:40 rdolls.sql Thanks, Dan From boris at codesynthesis.com Mon Aug 1 11:49:08 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Mon Aug 1 11:51:43 2011 Subject: [odb-users] error adding QString to person example 1.5.0 In-Reply-To: <4E36BE20.4090801@netharmonix.com> References: <4E36BE20.4090801@netharmonix.com> Message-ID: Hi Dan, Dan Coffey writes: > rdolls.h:22:11: error: unable to map C++ type '::QString' used in data > member 'middle_' to a database type Did you add "--profile qt" to the ODB compiler command line to enable the Qt profile? See Chapter 16 in the ODB manual for details. Boris From dcoffey at netharmonix.com Mon Aug 1 12:51:12 2011 From: dcoffey at netharmonix.com (Dan Coffey) Date: Mon Aug 1 12:51:19 2011 Subject: [odb-users] error adding QString to person example 1.5.0 In-Reply-To: References: <4E36BE20.4090801@netharmonix.com> Message-ID: <4E36D980.3050604@netharmonix.com> Hi Boris, Thanks for you help, that fixed it. Dan On 8/1/2011 11:49 AM, Boris Kolpackov wrote: > Hi Dan, > > Dan Coffey writes: > >> rdolls.h:22:11: error: unable to map C++ type '::QString' used in data >> member 'middle_' to a database type > Did you add "--profile qt" to the ODB compiler command line to enable > the Qt profile? See Chapter 16 in the ODB manual for details. > > Boris From dcoffey at netharmonix.com Tue Aug 2 13:30:49 2011 From: dcoffey at netharmonix.com (Dan Coffey) Date: Tue Aug 2 13:30:55 2011 Subject: [odb-users] Building GOF Composite Pattern ODB-1.5.0 Message-ID: <4E383449.7070406@netharmonix.com> Hi Boris, I'm trying to build the GOF composite pattern. Abstract Class - Rdolls Leaf Class - RdollsLeaf #include"rdolls.h" #pragmadbobject class RdollsLeaf : public Rdolls Group Class -RdollsGroup #include"rdolls.h" class Rdolls; #pragmadbobject class RdollsGroup : public Rdolls RdollsGroup has one relationship to it's base class Rdolls on line 22: QMapcontains; If I change RdollsGroup's one relationship to it's base class Rdolls on line 22: QMapcontains; then no errors are generated from odb ... processing. It seems that when I try and use a class that I defined (RdollsGroup) then I have a problem. How do I fix this so I can use a QMap were either of both the key and value are locally defined? Both Rdolls and RdollsLeaf are processed correctly by odb. When I run the: odb -d mysql --profile qt --profile boost --generate-query --generate-schema rdollsgroup.h I get the following error: rdollsgroup.h:22:25: error: unable to map C++ type '*::Rdolls*' used in data member 'contains' to a database type rdollsgroup.h:22:25: info: use '#pragma db value_type' to specify the database type Thanks, Dan From boris at codesynthesis.com Wed Aug 3 10:20:13 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Wed Aug 3 10:22:50 2011 Subject: [odb-users] Building GOF Composite Pattern ODB-1.5.0 In-Reply-To: <4E383449.7070406@netharmonix.com> References: <4E383449.7070406@netharmonix.com> Message-ID: Hi Dan, Dan Coffey writes: > QMap contains; Maybe that should be: QMap Or, better yet: QMap > If that doesn't help, please send a minimal but complete header file that fails to compile so that I can take a look. Without seeing the actual C++ declarations I am just guessing. Boris From dcoffey at netharmonix.com Wed Aug 3 12:15:40 2011 From: dcoffey at netharmonix.com (Dan Coffey) Date: Wed Aug 3 12:15:50 2011 Subject: [odb-users] Building GOF Composite Pattern ODB-1.5.0 In-Reply-To: References: <4E383449.7070406@netharmonix.com> Message-ID: <4E39742C.4010402@netharmonix.com> Hi Boris, QMap > works with the odb commands. I also tried QMap contains; but this will cause odb to fail. QMap > contains; which works with the ODB preprocessor. In the odb manual example code (pg 58) you have - std::map age_weight_map_; Is it possible to have a developer defined class as the value? Attached are the .h files, process.out which has the odb processing commands and results. All of these compile in Qt Creator without error, I then run the odb commands and the output is process.out. I also include the Qt files. Thanks, Dan On 8/3/2011 10:20 AM, Boris Kolpackov wrote: > Hi Dan, > > Dan Coffey writes: > >> QMap contains; > Maybe that should be: > > QMap > > Or, better yet: > > QMap > > > If that doesn't help, please send a minimal but complete header > file that fails to compile so that I can take a look. Without > seeing the actual C++ declarations I am just guessing. > > Boris -------------- next part -------------- ProjectExplorer.Project.ActiveTarget 0 ProjectExplorer.Project.EditorSettings true true System false false 2 true 1 true false true 0 2 true 1 true true true false ProjectExplorer.Project.Target.0 Desktop Desktop Qt4ProjectManager.Target.DesktopTarget 0 0 0 ProjectExplorer.ToolChain.Mingw:C:/Qt/qtcreator-2.2.1/mingw/bin/gcc.ex e.x86-windows-msys-pe-32bit.C:/Qt/qtcreator-2.2.1/pythongdb/gdb-i686-p c-mingw32.exe -d mysql --generate-query rdolls.h odb false %{buildDir} Custom Process Step ProjectExplorer.ProcessStep qmake QtProjectManager.QMakeBuildStep false false Make Qt4ProjectManager.MakeStep false 3 Build ProjectExplorer.BuildSteps.Build Make Qt4ProjectManager.MakeStep true clean 1 Clean ProjectExplorer.BuildSteps.Clean 2 false Qt 4.7.3 for Desktop - MinGW 4.4 (Qt SDK) Debug Qt4ProjectManager.Qt4BuildConfiguration 2 D:/Development/C++/TestCode/ODB/rdolls/rdolls-build-desktop 5 ProjectExplorer.ToolChain.Mingw:C:/Qt/qtcreator-2.2.1/mingw/bin/gcc.ex e.x86-windows-msys-pe-32bit.C:/Qt/qtcreator-2.2.1/pythongdb/gdb-i686-p c-mingw32.exe true ProjectExplorer.ToolChain.Mingw:C:/Qt/qtcreator-2.2.1/mingw/bin/gcc.ex e.x86-windows-msys-pe-32bit.C:/Qt/qtcreator-2.2.1/pythongdb/gdb-i686-p c-mingw32.exe qmake QtProjectManager.QMakeBuildStep false false Make Qt4ProjectManager.MakeStep false 2 Build ProjectExplorer.BuildSteps.Build Make Qt4ProjectManager.MakeStep true clean 1 Clean ProjectExplorer.BuildSteps.Clean 2 false Qt 4.7.3 for Desktop - MinGW 4.4 (Qt SDK) Release Qt4ProjectManager.Qt4BuildConfiguration 0 D:/Development/C++/TestCode/ODB/rdolls/rdolls-build-desktop 5 ProjectExplorer.ToolChain.Mingw:C:/Qt/qtcreator-2.2.1/mingw/bin/gcc.ex e.x86-windows-msys-pe-32bit.C:/Qt/qtcreator-2.2.1/pythongdb/gdb-i686-p c-mingw32.exe true ProjectExplorer.ToolChain.Mingw:C:/Qt/qtcreator-2.2.1/mingw/bin/gcc.ex e.x86-windows-msys-pe-32bit.C:/Qt/qtcreator-2.2.1/pythongdb/gdb-i686-p c-mingw32.exe qmake QtProjectManager.QMakeBuildStep false false Make Qt4ProjectManager.MakeStep false 2 Build ProjectExplorer.BuildSteps.Build Make Qt4ProjectManager.MakeStep true clean 1 Clean ProjectExplorer.BuildSteps.Clean 2 false Qt in PATH Debug Qt4ProjectManager.Qt4BuildConfiguration 2 D:/Development/C++/TestCode/ODB/rdolls/rdolls-build-desktop 8 ProjectExplorer.ToolChain.Mingw:C:/Qt/qtcreator-2.2.1/mingw/bin/gcc.ex e.x86-windows-msys-pe-32bit.C:/Qt/qtcreator-2.2.1/pythongdb/gdb-i686-p c-mingw32.exe true ProjectExplorer.ToolChain.Mingw:C:/Qt/qtcreator-2.2.1/mingw/bin/gcc.ex e.x86-windows-msys-pe-32bit.C:/Qt/qtcreator-2.2.1/pythongdb/gdb-i686-p c-mingw32.exe qmake QtProjectManager.QMakeBuildStep false false Make Qt4ProjectManager.MakeStep false 2 Build ProjectExplorer.BuildSteps.Build Make Qt4ProjectManager.MakeStep true clean 1 Clean ProjectExplorer.BuildSteps.Clean 2 false Qt in PATH Release Qt4ProjectManager.Qt4BuildConfiguration 0 D:/Development/C++/TestCode/ODB/rdolls/rdolls-build-desktop 8 ProjectExplorer.ToolChain.Mingw:C:/Qt/qtcreator-2.2.1/mingw/bin/gcc.ex e.x86-windows-msys-pe-32bit.C:/Qt/qtcreator-2.2.1/pythongdb/gdb-i686-p c-mingw32.exe true 4 0 Deploy ProjectExplorer.BuildSteps.Deploy 1 No deployment ProjectExplorer.DefaultDeployConfiguration 1 2 false %{buildDir} Custom Executable ProjectExplorer.CustomExecutableRunConfiguration 3768 true false 1 ProjectExplorer.Project.TargetCount 1 ProjectExplorer.Project.Updater.EnvironmentId {4de63817-bbc0-4458-9419-bb6437c60248} ProjectExplorer.Project.Updater.FileVersion 9 -------------- next part -------------- #ifndef RDOLLS_H #define RDOLLS_H #include #include //ODB includes #include #include #include #include #include "rdolls_global.h" //#include "rdollsgroup.h" //Forward Declarations class RdollsGroup; #pragma db object class RDOLLSSHARED_EXPORT Rdolls { public: Rdolls(); private: friend class odb::access; #pragma db id auto unsigned long id_; QString last_; QString first_; unsigned short age_; //smart ptr to RdollsGroup QLazyWeakPointer group; //This will cause odb to fail //QList Below has the following error from Qt Creator build: // error: invalid application of 'sizeof' to incomplete type 'RdollsGroup' //QList listOfGroups_; QList > listOfGroups;//This will cause odb to fail //Collection of contained Rdolls instances QMap contains; //This will cause odb to fail //Below all work with odb QMap > contains_ptrs; QList > contains_; //Pointer to Rdolls instance that contain this #pragma db inverse(contains_) QLazySharedPointer containedIn_; //Rdolls containedIn; }; #endif // RDOLLS_H -------------- next part -------------- #ifndef RDOLLSGROUP_H #define RDOLLSGROUP_H #include #include #include #include #include #include "rdolls.h" //class Rdolls; #pragma db object class RdollsGroup : public Rdolls { public: RdollsGroup(); private: friend class odb::access; QMap > contains; }; #endif // RDOLLSGROUP_H -------------- next part -------------- #ifndef RDOLLSLEAF_H #define RDOLLSLEAF_H #include #include #include #include #include "rdolls.h" #pragma db object class RdollsLeaf : public Rdolls { public: RdollsLeaf(); private: friend class odb::access; }; #endif // RDOLLSLEAF_H -------------- next part -------------- + odb -d mysql --profile qt --profile boost --generate-query --generate-schema rdolls.h -I/usr/local/include/mysql -I/usr/local/include/qt4/ -I/usr/local/include/boost -I/usr/local/include -I/usr/local/include/odb -I/d/Development/C++/TestCode/rdolls/rdolls -I/d/Development/C++/TestCode/rdolls/rdolls/rdollsgroup.h rdolls.h:34:33: error: unable to map C++ type '::QLazyWeakPointer< ::RdollsGroup >' used in data member 'group' to a database type rdolls.h:34:33: info: use '#pragma db type' to specify the database type + odb -d mysql --profile qt --profile boost --generate-query --generate-schema rdollsleaf.h -I/usr/local/include/mysql -I/usr/local/include/qt4/ -I/usr/local/include/boost -I/usr/local/include -I/usr/local/include/odb -I/d/Development/C++/TestCode/rdolls/rdolls rdolls.h:34:33: error: unable to map C++ type '::QLazyWeakPointer< ::RdollsGroup >' used in data member 'group' to a database type rdolls.h:34:33: info: use '#pragma db type' to specify the database type + odb -d mysql --profile qt --profile boost --generate-query --generate-schema rdollsgroup.h -I/usr/local/include/mysql -I/usr/local/include/qt4/ -I/usr/local/include/boost -I/usr/local/include -I/usr/local/include/odb -I/d/Development/C++/TestCode/rdolls/rdolls/rdolls.h rdolls.h:43:25: error: unable to map C++ type '::Rdolls' used in data member 'contains' to a database type rdolls.h:43:25: info: use '#pragma db value_type' to specify the database type -------------- next part -------------- #------------------------------------------------- # # Project created by QtCreator 2011-07-28T14:19:10 # #------------------------------------------------- QT += network TARGET = rdolls TEMPLATE = lib DEFINES += RDOLLS_LIBRARY SOURCES += rdolls.cpp \ rdollsgroup.cpp \ rdollsleaf.cpp #rdolls-odb.cxx is generated by odb, the odb script must be run #before rdolls-odb.cxx is compiled with rdolls.cpp #comment out the next line before and uncomment after - dpc 8.1.11 #SOURCES += rdolls-odb.cxx HEADERS += rdolls.h\ rdolls_global.h \ rdollsgroup.h \ rdollsleaf.h INCLUDEPATH += c:/MinGW/msys/1.0/local/include INCLUDEPATH += c:/MinGW/msys/1.0/local/include/qt4 INCLUDEPATH += c:/MinGW/msys/1.0/local/include/boost LIBS += c:/MinGW/msys/1.0/local/lib/*.a #LIBS += c:/MinGW/msys/1.0/local/lib/odb/* LIBS += c:/MinGW/msys/1.0/local/lib/odb/mysql/*.a LIBS += c:/MinGW/msys/1.0/local/lib/odb/mysql/*.lib LIBS += c:/MinGW/msys/1.0/local/lib/odb/mysql/*.dll #Qt LIBS += c:/MinGW/msys/1.0/local/lib/qt4/*.dll #Not Needed libs the .a causes ld errors #LIBS += c:/MinGW/msys/1.0/local/lib/qt4/*.a #LIBS += c:/MinGW/msys/1.0/local/lib/qt4/*.lib symbian { MMP_RULES += EXPORTUNFROZEN TARGET.UID3 = 0xED6D8BE0 TARGET.CAPABILITY = TARGET.EPOCALLOWDLLDATA = 1 addFiles.sources = rdolls.dll addFiles.path = !:/sys/bin DEPLOYMENT += addFiles } unix:!symbian { maemo5 { target.path = /opt/usr/lib } else { target.path = /usr/lib } INSTALLS += target } From dcoffey at netharmonix.com Wed Aug 3 13:12:28 2011 From: dcoffey at netharmonix.com (Dan Coffey) Date: Wed Aug 3 13:12:34 2011 Subject: [odb-users] Building GOF Composite Pattern ODB-1.5.0 In-Reply-To: <4E39742C.4010402@netharmonix.com> References: <4E383449.7070406@netharmonix.com> <4E39742C.4010402@netharmonix.com> Message-ID: <4E39817C.4010209@netharmonix.com> Hi Boris, I've commented out all of the lines that cause odb processing errors (attached src on last email) I then compiled the files (Rdolls ...) using Qt Creator Then I ran the odb command for each .cpp file without errors and the *-odb.[ch]xx and *.ixx files were created without errors. The Qt .pro file was modified to include all of the created *-odb.[ch]xx files. When I do a rebuild all in Qt I get the following errors from the rdollsgroup-odb.hxx file /D:\Development\C++\TestCode\ODB\rdolls\rdolls-build-desktop\..\rdolls\rdollsgroup-odb.hxx:118: error: redefinition of 'struct odb::access::object_traits::contains_traits' D:\Development\C++\TestCode\ODB\rdolls\rdolls-build-desktop\..\rdolls\rdollsgroup-odb.hxx:107: error: previous definition of 'struct odb::access::object_traits::contains_traits'/ Thanks, Dan Env: XP SP3 minGW Qt 4.7 g++ 4.5.2 On 8/3/2011 12:15 PM, Dan Coffey wrote: > Hi Boris, > > QMap > > > works with the odb commands. I also tried > QMap contains; but this will cause odb to fail. > QMap > contains; which works with > the ODB preprocessor. > > In the odb manual example code (pg 58) you have - std::map short, float> age_weight_map_; > Is it possible to have a developer defined class as the value? > > Attached are the .h files, process.out which has the odb processing > commands and results. > All of these compile in Qt Creator without error, I then run the odb > commands and the output is process.out. > I also include the Qt files. > > Thanks, > > Dan > > On 8/3/2011 10:20 AM, Boris Kolpackov wrote: >> Hi Dan, >> >> Dan Coffey writes: >> >>> QMap contains; >> Maybe that should be: >> >> QMap >> >> Or, better yet: >> >> QMap > >> >> If that doesn't help, please send a minimal but complete header >> file that fails to compile so that I can take a look. Without >> seeing the actual C++ declarations I am just guessing. >> >> Boris -------------- next part -------------- // This file was generated by ODB, object-relational mapping (ORM) // compiler for C++. // #ifndef RDOLLSGROUP_ODB_HXX #define RDOLLSGROUP_ODB_HXX #include #if (ODB_VERSION != 10500UL) #error ODB runtime version mismatch #endif #include // Begin prologue. // #include #if LIBODB_QT_VERSION != 1050000 // 1.5.0 # error ODB and C++ compilers see different libodb-qt versions #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // // End prologue. #include "rdollsgroup.h" #include "rdolls-odb.hxx" #include #include #include #include #include #include #ifdef BOOST_TR1_MEMORY_HPP_INCLUDED # include #endif #include #include #include #include #include #include #include #include namespace odb { // RdollsGroup // template <> class access::object_traits< ::RdollsGroup > { public: typedef ::RdollsGroup object_type; typedef ::boost::shared_ptr< ::RdollsGroup > pointer_type; typedef object_traits< ::Rdolls >::id_type id_type; typedef object_traits< ::Rdolls >::id_image_type id_image_type; struct image_type: object_traits< ::Rdolls >::image_type { std::size_t version; }; struct query_columns: object_traits< ::Rdolls >::query_columns { }; // contains_ptrs // struct contains_ptrs_traits: access::object_traits< ::Rdolls >::contains_ptrs_traits { static const std::size_t cond_column_count = 1UL; static const std::size_t data_column_count = 3UL; static const char* const insert_one_statement; static const char* const select_all_statement; static const char* const delete_all_statement; }; // contains_ // struct contains_traits: access::object_traits< ::Rdolls >::contains_traits { static const std::size_t cond_column_count = 1UL; static const std::size_t data_column_count = 3UL; static const char* const insert_one_statement; static const char* const select_all_statement; static const char* const delete_all_statement; }; // contains // struct contains_traits { static const std::size_t cond_column_count = 1UL; static const std::size_t data_column_count = 3UL; static const char* const insert_one_statement; static const char* const select_all_statement; static const char* const delete_all_statement; typedef ::QMap< ::QString, ::QSharedPointer< ::Rdolls > > container_type; typedef odb::access::container_traits< container_type > container_traits; typedef container_traits::key_type key_type; typedef container_traits::value_type value_type; typedef map_functions functions_type; typedef mysql::container_statements< contains_traits > statements_type; struct cond_image_type { // key // details::buffer key_value; unsigned long key_size; my_bool key_null; std::size_t version; }; struct data_image_type { // key // details::buffer key_value; unsigned long key_size; my_bool key_null; // value // unsigned long long value_value; my_bool value_null; std::size_t version; }; static void bind (MYSQL_BIND*, const MYSQL_BIND* id, std::size_t id_size, cond_image_type&); static void bind (MYSQL_BIND*, const MYSQL_BIND* id, std::size_t id_size, data_image_type&); static void grow (data_image_type&, my_bool*); static void init (data_image_type&, const key_type&, const value_type&); static void init (key_type&, value_type&, const data_image_type&, database&); static void insert_one (const key_type&, const value_type&, void*); static bool load_all (key_type&, value_type&, void*); static void delete_all (void*); static void persist (const container_type&, const mysql::binding& id, statements_type&); static void load (container_type&, const mysql::binding& id, statements_type&); static void update (const container_type&, const mysql::binding& id, statements_type&); static void erase (const mysql::binding& id, statements_type&); }; static id_type id (const object_type&); static id_type id (const image_type&); static bool grow (image_type&, my_bool*); static void bind (MYSQL_BIND*, image_type&, bool); static void bind (MYSQL_BIND*, id_image_type&); static bool init (image_type&, const object_type&); static void init (object_type&, const image_type&, database&); static void init (id_image_type&, const id_type&); typedef mysql::query query_base_type; struct query_type: query_base_type, query_columns { query_type (); query_type (const std::string&); query_type (const query_base_type&); }; struct container_statement_cache_type; static const std::size_t in_column_count = 4UL; static const std::size_t out_column_count = 5UL; static const char* const persist_statement; static const char* const find_statement; static const char* const update_statement; static const char* const erase_statement; static const char* const query_clause; static void callback (database&, object_type&, callback_event); static void callback (database&, const object_type&, callback_event); static void persist (database&, object_type&); static void update (database&, const object_type&); static void erase (database&, const id_type&); static pointer_type find (database&, const id_type&); static bool find (database&, const id_type&, object_type&); template static result query (database&, const query_type&); public: static bool find_ (mysql::object_statements< object_type >&, const id_type&); static void load_ (mysql::object_statements< object_type >&, object_type&); static void query_ (database&, const query_type&, mysql::object_statements< object_type >&, details::shared_ptr< mysql::select_statement >&); }; } #include "rdollsgroup-odb.ixx" // Begin epilogue. // // // End epilogue. #include #endif // RDOLLSGROUP_ODB_HXX From dcoffey at netharmonix.com Wed Aug 3 14:02:12 2011 From: dcoffey at netharmonix.com (Dan Coffey) Date: Wed Aug 3 14:02:21 2011 Subject: [odb-users] Building GOF Composite Pattern ODB-1.5.0 In-Reply-To: <4E39817C.4010209@netharmonix.com> References: <4E383449.7070406@netharmonix.com> <4E39742C.4010402@netharmonix.com> <4E39817C.4010209@netharmonix.com> Message-ID: <4E398D24.7000205@netharmonix.com> Hi Boris, By changing the attribute name in the RdollsGroup class from */contains /*to */group /*that last error went away. QMap > *contains*; to QMap > *group*; The base class (Rdolls) has an attribute: QList>*contains_*; With that error gone, now I'm getting this compiler error in Qt Creator: In rdollsgroup-odb.cxx //Ifacompilererrorpointstothelinebelow,then //itmostlikelymeansthatapointerusedinamember //cannotbeinitializedfromanobjectpointer. v = ptr_traits::pointer_type ( db.load< ptr_traits::element_type > (id)); So I changed theabove QMap from QMap > to QMap > and that compiled with no errors. Next I'm going to create the database.hxx and driver.cxx and test it out. Thanks, Dan On 8/3/2011 1:12 PM, Dan Coffey wrote: > Hi Boris, > > I've commented out all of the lines that cause odb processing errors > (attached src on last email) > I then compiled the files (Rdolls ...) using Qt Creator > Then I ran the odb command for each .cpp file without errors and the > *-odb.[ch]xx and *.ixx files were created without errors. > The Qt .pro file was modified to include all of the created > *-odb.[ch]xx files. > When I do a rebuild all in Qt I get the following errors from the > rdollsgroup-odb.hxx file > > /D:\Development\C++\TestCode\ODB\rdolls\rdolls-build-desktop\..\rdolls\rdollsgroup-odb.hxx:118: > error: redefinition of 'struct > odb::access::object_traits::contains_traits' > > D:\Development\C++\TestCode\ODB\rdolls\rdolls-build-desktop\..\rdolls\rdollsgroup-odb.hxx:107: > error: previous definition of 'struct > odb::access::object_traits::contains_traits'/ > > Thanks, > > Dan > > Env: > XP SP3 > minGW > Qt 4.7 > g++ 4.5.2 > > On 8/3/2011 12:15 PM, Dan Coffey wrote: >> Hi Boris, >> >> QMap > >> >> works with the odb commands. I also tried >> QMap contains; but this will cause odb to fail. >> QMap > contains; which works with >> the ODB preprocessor. >> >> In the odb manual example code (pg 58) you have - std::map> short, float> age_weight_map_; >> Is it possible to have a developer defined class as the value? >> >> Attached are the .h files, process.out which has the odb processing >> commands and results. >> All of these compile in Qt Creator without error, I then run the odb >> commands and the output is process.out. >> I also include the Qt files. >> >> Thanks, >> >> Dan >> >> On 8/3/2011 10:20 AM, Boris Kolpackov wrote: >>> Hi Dan, >>> >>> Dan Coffey writes: >>> >>>> QMap contains; >>> Maybe that should be: >>> >>> QMap >>> >>> Or, better yet: >>> >>> QMap > >>> >>> If that doesn't help, please send a minimal but complete header >>> file that fails to compile so that I can take a look. Without >>> seeing the actual C++ declarations I am just guessing. >>> >>> Boris -------------- next part -------------- #ifndef RDOLLSGROUP_H #define RDOLLSGROUP_H #include #include #include #include #include #include "rdolls.h" #pragma db object class RdollsGroup : public Rdolls { public: RdollsGroup(); private: friend class odb::access; QMap > group; //QMap > group; }; #endif // RDOLLSGROUP_H -------------- next part -------------- #------------------------------------------------- # # Project created by QtCreator 2011-07-28T14:19:10 # #------------------------------------------------- QT += network TARGET = rdolls TEMPLATE = lib DEFINES += RDOLLS_LIBRARY SOURCES += rdolls.cpp \ rdollsgroup.cpp \ rdollsleaf.cpp # *-odb.cxx is generated by odb, the odb script must be run #before *-odb.cxx is compiled with rdolls.cpp #comment out the next lines before and uncomment after - dpc 8.1.11 SOURCES += rdolls-odb.cxx \ rdollsgroup-odb.cxx \ rdollsleaf-odb.cxx \ driver.cpp HEADERS += rdolls.h\ rdolls_global.h \ rdollsgroup.h \ rdollsleaf.h # *-odb.hxx is generated by odb, the odb script must be run #before *-odb.hxx is compiled with rdolls.cpp #comment out the next lines before and uncomment after - dpc 8.1.11 HEADERS += rdolls-odb.hxx \ rdollsgroup-odb.hxx \ rdollsleaf-odb.hxx \ driver.h INCLUDEPATH += c:/MinGW/msys/1.0/local/include INCLUDEPATH += c:/MinGW/msys/1.0/local/include/qt4 INCLUDEPATH += c:/MinGW/msys/1.0/local/include/boost LIBS += c:/MinGW/msys/1.0/local/lib/*.a #LIBS += c:/MinGW/msys/1.0/local/lib/odb/* LIBS += c:/MinGW/msys/1.0/local/lib/odb/mysql/*.a LIBS += c:/MinGW/msys/1.0/local/lib/odb/mysql/*.lib LIBS += c:/MinGW/msys/1.0/local/lib/odb/mysql/*.dll #Qt LIBS += c:/MinGW/msys/1.0/local/lib/qt4/*.dll #Not Needed libs the .a causes ld errors #LIBS += c:/MinGW/msys/1.0/local/lib/qt4/*.a #LIBS += c:/MinGW/msys/1.0/local/lib/qt4/*.lib symbian { MMP_RULES += EXPORTUNFROZEN TARGET.UID3 = 0xED6D8BE0 TARGET.CAPABILITY = TARGET.EPOCALLOWDLLDATA = 1 addFiles.sources = rdolls.dll addFiles.path = !:/sys/bin DEPLOYMENT += addFiles } unix:!symbian { maemo5 { target.path = /opt/usr/lib } else { target.path = /usr/lib } INSTALLS += target } From romanovda at gmail.com Fri Aug 5 13:08:17 2011 From: romanovda at gmail.com (Dmitry Romanov) Date: Fri Aug 5 13:08:25 2011 Subject: [odb-users] error with libstdc++.la Message-ID: Dear Developers, We have an error compiling libodb-mysql-1.5.0 on a distributed farm: The real libstdc++.la is located in /apps/gcc/gcc-4.4.4/lib64/libstdc++.la When we do 'make' we've got: libtool: link: warning: library `/u/home/isupov/odb/lib/libodb.la' was moved. libtool: link: warning: library `/apps/gcc/gcc-4.4.4/lib64//libstdc++.la' was moved. libtool: link: g++ -shared -nostdlib /usr/lib/../lib64/crti.o /u/apps/gcc/gcc-4.4.4/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.4.4/crtbeginS.o .libs/connection.o .libs/connection-factory.o .libs/database.o .libs/enum.o .libs/error.o .libs/exceptions.o .libs/object-statements.o .libs/query.o .libs/statement.o .libs/transaction.o .libs/transaction-impl.o .libs/traits.o details/.libs/options.o -Wl,-rpath -Wl,/u/home/isupov/odb/lib -Wl,-rpath -Wl,/apps/gcc/gcc-4.4.4/lib64/ -Wl,-rpath -Wl,/u/home/isupov/odb/lib -Wl,-rpath -Wl,/apps/gcc/gcc-4.4.4/lib64/ -L/u/home/isupov/odb/lib -L/usr/lib64/mysql -lz -lcrypt -lnsl -L/usr/lib64 -lssl -lcrypto -L/apps/gcc/gcc-4.4.4/lib64/ /u/home/isupov/odb/lib/libodb.so -lmysqlclient_r -lpthread -L/u/apps/gcc/gcc-4.4.4/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.4.4 -L/u/apps/gcc/gcc-4.4.4/bin/../lib/gcc -L/u/apps/gcc/gcc-4.4.4/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.4.4/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/u/apps/gcc/gcc-4.4.4/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.4.4/../../.. /apps/gcc/gcc-4.4.4/lib64//libstdc++.so -lm -lc -lgcc_s /u/apps/gcc/gcc-4.4.4/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.4.4/crtendS.o /usr/lib/../lib64/crtn.o -Wl,-soname -Wl,libodb-mysql-1.5.so -o .libs/libodb-mysql-1.5.so libtool: link: (cd ".libs" && rm -f "libodb-mysql.so" && ln -s "libodb-mysql-1.5.so" "libodb-mysql.so") /bin/sed: can't read /apps/gcc-4.4.4/lib/../lib64/libstdc++.la: No such file or directory libtool: link: `/apps/gcc-4.4.4/lib/../lib64/libstdc++.la' is not a valid libtool archive make[2]: *** [libodb-mysql.la] Error 1 make[2]: Leaving directory `/u/home/isupov/odb/libodb-mysql-1.5.0/odb/mysql' make[1]: *** [all] Error 2 make[1]: Leaving directory `/u/home/isupov/odb/libodb-mysql-1.5.0/odb/mysql' make: *** [all-recursive] Error 1 The system is: uname -a Linux *** 2.6.18-128.7.1.el5 #1 SMP Mon Aug 24 08:21:56 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux Before calling make file we do: ./configure --prefix=/u/home/isupov/odb CPPFLAGS="-I/u/home/isupov/odb/include -I/usr/include/mysql" LDFLAGS="-L/u/home/isupov/odb/lib -L/usr/lib64/mysql -lmysqlclient_r -lz -lpthread -lcrypt -lnsl -lm -lpthread -L/usr/lib64 -lssl -lcrypto -L/apps/gcc/gcc-4.4.4/lib64/" Is it a bug? Or are we do something wrong? Thank you very much! Dr. Dmitry A Romanov Thomas Jefferson National Acceleration Facility From boris at codesynthesis.com Fri Aug 5 14:54:03 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Fri Aug 5 14:56:39 2011 Subject: [odb-users] error with libstdc++.la In-Reply-To: References: Message-ID: Hi Dmitry, Dmitry Romanov writes: > The real libstdc++.la is located in /apps/gcc/gcc-4.4.4/lib64/libstdc++.la > > /bin/sed: can't read /apps/gcc-4.4.4/lib/../lib64/libstdc++.la: No > such file or directory > libtool: link: `/apps/gcc-4.4.4/lib/../lib64/libstdc++.la' is not a > valid libtool archive > > Is it a bug? Or are we do something wrong? This seems to be a mis-configuration of your GCC toolchain. Was gcc-4.4.4 perhaps moved to /apps/gcc/ from /apps? Or maybe one of the libraries (libodb or libmysqlclient) were built when gcc-4.4.4 was in still in /apps (or on another machine where it is still in /apps)? I suggest that you inspect the libodb.la and libmysqlclient.la (and any other .la files that they list as dependencies) for the /apps/gcc-4.4.4/lib/../lib64/libstdc++.la path. If you find it, then you need to rebuild that library. Boris From losintikfos at yahoo.co.uk Sun Aug 7 12:10:38 2011 From: losintikfos at yahoo.co.uk (Bright Dadson) Date: Mon Aug 8 08:03:51 2011 Subject: [odb-users] Resolving odb::boost namespace Message-ID: <1312733438.21897.YahooMailClassic@web29304.mail.ird.yahoo.com> I am trying to use the odb::boost::lazy_shared_ptr - I have included the header #include of which when I hold the ctrl key and click on it takes me to the file. My problem is odb::boost is not resolving in my class and therefore when I do odb:: ctrl + space do not find the reference namespace. Do anyone what i am doing wrong??? I have installed the libodb-boost. Thanks. From boris at codesynthesis.com Mon Aug 8 08:02:49 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Mon Aug 8 08:05:24 2011 Subject: [odb-users] Resolving odb::boost namespace In-Reply-To: <1312733438.21897.YahooMailClassic@web29304.mail.ird.yahoo.com> References: <1312733438.21897.YahooMailClassic@web29304.mail.ird.yahoo.com> Message-ID: Hi, Bright Dadson writes: > My problem is odb::boost is not resolving in my class and therefore when > I do odb:: ctrl + space do not find the reference namespace. This can be an IDE issue. Does your code compile with a C++ compiler? Boris From losintikfos at yahoo.co.uk Mon Aug 8 09:47:31 2011 From: losintikfos at yahoo.co.uk (Bright Dadson) Date: Mon Aug 8 10:02:13 2011 Subject: [odb-users] Resolving odb::boost namespace In-Reply-To: References: <1312733438.21897.YahooMailClassic@web29304.mail.ird.yahoo.com> Message-ID: Yes it does compile with C++ compiler. On 8 Aug 2011, at 13:02, Boris Kolpackov wrote: > Hi, > > Bright Dadson writes: > >> My problem is odb::boost is not resolving in my class and therefore when >> I do odb:: ctrl + space do not find the reference namespace. > > This can be an IDE issue. Does your code compile with a C++ compiler? > > Boris From dcoffey at netharmonix.com Mon Aug 8 10:57:48 2011 From: dcoffey at netharmonix.com (Dan Coffey) Date: Mon Aug 8 10:57:55 2011 Subject: [odb-users] Building GOF Composite Pattern ODB-1.5.0 In-Reply-To: <4E398D24.7000205@netharmonix.com> References: <4E383449.7070406@netharmonix.com> <4E39742C.4010402@netharmonix.com> <4E39817C.4010209@netharmonix.com> <4E398D24.7000205@netharmonix.com> Message-ID: <4E3FF96C.5000407@netharmonix.com> Hi Boris, I had both: odb -d mysql --profile *qt *--profile *boost* --generate-query --generate-schema rdolls.h -I/... I removed --profile boost and the pointer error was resolved. Dan On 8/3/2011 2:02 PM, Dan Coffey wrote: > Hi Boris, > > By changing the attribute name in the RdollsGroup class from > */contains /*to */group /*that last error went away. > QMap > *contains*; > to > QMap > *group*; > > The base class (Rdolls) has an attribute: > QList>*contains_*; > > With that error gone, now I'm getting this compiler error in Qt Creator: > In rdollsgroup-odb.cxx > //Ifacompilererrorpointstothelinebelow,then > //itmostlikelymeansthatapointerusedinamember > //cannotbeinitializedfromanobjectpointer. > > v = ptr_traits::pointer_type ( > > db.load< ptr_traits::element_type > (id)); > > So I changed theabove QMap from > QMap > > to > QMap > > > and that compiled with no errors. > Next I'm going to create the database.hxx and driver.cxx and test it out. > > Thanks, > > Dan > > > > On 8/3/2011 1:12 PM, Dan Coffey wrote: >> Hi Boris, >> >> I've commented out all of the lines that cause odb processing errors >> (attached src on last email) >> I then compiled the files (Rdolls ...) using Qt Creator >> Then I ran the odb command for each .cpp file without errors and the >> *-odb.[ch]xx and *.ixx files were created without errors. >> The Qt .pro file was modified to include all of the created >> *-odb.[ch]xx files. >> When I do a rebuild all in Qt I get the following errors from the >> rdollsgroup-odb.hxx file >> >> /D:\Development\C++\TestCode\ODB\rdolls\rdolls-build-desktop\..\rdolls\rdollsgroup-odb.hxx:118: >> error: redefinition of 'struct >> odb::access::object_traits::contains_traits' >> >> D:\Development\C++\TestCode\ODB\rdolls\rdolls-build-desktop\..\rdolls\rdollsgroup-odb.hxx:107: >> error: previous definition of 'struct >> odb::access::object_traits::contains_traits'/ >> >> Thanks, >> >> Dan >> >> Env: >> XP SP3 >> minGW >> Qt 4.7 >> g++ 4.5.2 >> >> On 8/3/2011 12:15 PM, Dan Coffey wrote: >>> Hi Boris, >>> >>> QMap > >>> >>> works with the odb commands. I also tried >>> QMap contains; but this will cause odb to fail. >>> QMap > contains; which works with >>> the ODB preprocessor. >>> >>> In the odb manual example code (pg 58) you have - std::map>> short, float> age_weight_map_; >>> Is it possible to have a developer defined class as the value? >>> >>> Attached are the .h files, process.out which has the odb processing >>> commands and results. >>> All of these compile in Qt Creator without error, I then run the odb >>> commands and the output is process.out. >>> I also include the Qt files. >>> >>> Thanks, >>> >>> Dan >>> >>> On 8/3/2011 10:20 AM, Boris Kolpackov wrote: >>>> Hi Dan, >>>> >>>> Dan Coffey writes: >>>> >>>>> QMap contains; >>>> Maybe that should be: >>>> >>>> QMap >>>> >>>> Or, better yet: >>>> >>>> QMap > >>>> >>>> If that doesn't help, please send a minimal but complete header >>>> file that fails to compile so that I can take a look. Without >>>> seeing the actual C++ declarations I am just guessing. >>>> >>>> Boris From romanovda at gmail.com Mon Aug 8 11:26:54 2011 From: romanovda at gmail.com (Dmitry Romanov) Date: Mon Aug 8 11:27:02 2011 Subject: [odb-users] error with libstdc++.la In-Reply-To: References: Message-ID: Hi Boris, we have solved the problem. Indeed it was an error in our gcc configuration. The problem was: A file libstdc++.la is located at: /apps/gcc/gcc-4.4.4/lib64/libstdc++.la but the file contains record: # Directory that this library needs to be installed in: libdir='/apps/gcc-4.4.4/lib/../lib64' (not /apps/gcc/gcc-4.4.4/... but /apps/gcc-4.4.4/...) Thus libodb.la file had: # Libraries that this one depends upon. dependency_libs=' -lpthread /apps/gcc-4.4.4/lib/../lib64/libstdc++.la' Then a compilation of libodb-mysql fails because of this. We were able to compile everything after modifying libodb.la file (and sending angry letter to our admins). Spasibo! Dmitry On Fri, Aug 5, 2011 at 2:54 PM, Boris Kolpackov wrote: > Hi Dmitry, > > Dmitry Romanov writes: > >> The real libstdc++.la is located in /apps/gcc/gcc-4.4.4/lib64/libstdc++.la >> >> /bin/sed: can't read /apps/gcc-4.4.4/lib/../lib64/libstdc++.la: No >> such file or directory >> libtool: link: `/apps/gcc-4.4.4/lib/../lib64/libstdc++.la' is not a >> valid libtool archive >> >> Is it a bug? Or are we do something wrong? > > This seems to be a mis-configuration of your GCC toolchain. Was gcc-4.4.4 > perhaps moved to /apps/gcc/ from /apps? Or maybe one of the libraries > (libodb or libmysqlclient) were built when gcc-4.4.4 was in still in /apps > (or on another machine where it is still in /apps)? I suggest that you > inspect the libodb.la and libmysqlclient.la (and any other .la files that > they list as dependencies) for the /apps/gcc-4.4.4/lib/../lib64/libstdc++.la > path. If you find it, then you need to rebuild that library. > > Boris > From boris at codesynthesis.com Tue Aug 9 08:14:25 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Tue Aug 9 08:17:00 2011 Subject: [odb-users] Building GOF Composite Pattern ODB-1.5.0 In-Reply-To: <4E3FF96C.5000407@netharmonix.com> References: <4E383449.7070406@netharmonix.com> <4E39742C.4010402@netharmonix.com> <4E39817C.4010209@netharmonix.com> <4E398D24.7000205@netharmonix.com> <4E3FF96C.5000407@netharmonix.com> Message-ID: Hi Dan, Dan Coffey writes: > I had both: odb -d mysql --profile *qt *--profile *boost* > --generate-query --generate-schema rdolls.h -I/... > I removed --profile boost and the pointer error was resolved. The Qt and Boost profiles override the default object pointer to be QSharedPointer and boost::shared_ptr, respectively. The profile that was specified last in the command line (Boost in your case) wins. So if you want to use both, then you can either specify them in the desired order or specify the pointer type explicitly after the profile options: --profile qt --profile boost --default-pointer QSharedPointer As always, this is all covered in the ODB manual. Boris From boris at codesynthesis.com Wed Aug 10 14:06:35 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Wed Aug 10 14:09:10 2011 Subject: [odb-users] Re: Recommended way of persisting objects that contain struct timeval? In-Reply-To: <50FEB91CC4FBAB4881226E0EC04AC340927F6013@HVXMSP9.us.lmco.com> References: <50FEB91CC4FBAB4881226E0EC04AC340927F6013@HVXMSP9.us.lmco.com> Message-ID: Hi Thomas, [CC'ed odb-users to my reply.] Szumowski, Thomas writes: > We have a legacy object I'd like to persist using ODB. One of the fields is > time, in the form of a timeval > structure. (http://www.gnu.org/s/hello/manual/libc/Elapsed-Time.html). The > timeval structure is defined in sys/time.h (linux). > > Is there a recommended way of persisting timeval structures without having > to edit sys/time.h with ODB markings? There are actually two ways a struct like timeval can be stored in the database: as a simple value or as a composite value. Sections 3.1, "Concepts and Terminology" in the ODB manual gives a good overview of the differences between the two, but, essentially, a simple value would be stored in a single column and a composite value will occupy several columns. The desired way normally depends on the application requirements. To store timeval as a simple value (for example, as a number of milliseconds stored in a single 64-bit integer) we would need to map it to a suitable database type using the type pragma. For the SQLite database, we can do something like this: #pragma db value(timeval) type("INTEGER") Then we will need to provide the value_traits specialization for this type that implements the conversion between the struct value and a single integer. The 'mapping' example in the odb-example package shows how to do this. Storing timeval as a composite value is a bit trickier because it is defined in a system header and, as you mentioned, we don't want to modify it by adding a pragma that tells the ODB compiler it is a composite value type. What we can do is add this pragma into the ODB compilation process using the --odb-epilogue option. We will also need to use the --include-regex option (added in ODB 1.5.0) to fix up some of the includes. Here are step-by-step instructions for a test header I created (test.hxx): #include #pragma db object class person { public: #pragma db id unsigned long id_; timeval time_; }; 1. First, I created the "mapping file" for sys/time.h, I called it time-mapping.h, it contains just this line: #pragma db value(timeval) 2. Now if I try to compile /usr/include/sys/time.h, I get empty generated files. As it turns out, timeval is defined in the bits/time.h header which is included by sys/time.h. So the ODB compiler command line I used is this: odb -d sqlite --odb-epilogue-file time-mapping.h \ --include-regex '%time.h%%' -D __need_timeval \ /usr/include/bits/time.h The __need_timeval define is needed in order to make bits/time.h to define struct timeval. This step will product a set of C++ source file (time-odb.?xx) that contain the persistence code for struct timeval. 3. To compile test.hxx, I used this command line: odb -d sqlite --odb-epilogue-file time-mapping.h \ --include-regex '%bits/time-odb.hxx%"time-odb.hxx"%' test.hxx To tidy this up, you may want to place some of the options into an options file, e.g., time.options: --odb-epilogue-file time-mapping.h --include-regex '%bits/time-odb.hxx%"time-odb.hxx"%' Then the command lines become: odb -d sqlite --include-regex '%time.h%%' -D __need_timeval \ --options-file time.options /usr/include/bits/time.h odb -d sqlite --options-file time.options test.hxx Boris From kleber.molica at gmail.com Thu Aug 11 00:01:11 2011 From: kleber.molica at gmail.com (kleber molica) Date: Thu Aug 11 00:01:18 2011 Subject: [odb-users] Error to run odb-examples!!! Message-ID: Hello everybody! I'm new odb user and I had a problem to install and run example app's! I followed all instructions to make right odb, libodb, libodb-sqlite and libodb-qt install. When I tried to run Hello example I got this error: ./driver: error while loading shared libraries: libodb-sqlite-1.5.so: cannot open shared object file: No such file or directory Anyone can help me with this problem? Thank's! -- *Kleber Augusto Molica* Engenharia de Software Core Networks Ltda Rua Coronel Francisco Br?z, n? 185, sala 204 - Centro - ITAJUB?/MG CEP: 37500-052 *Tel.: (35) 3622 3444* *kleber@corenetworks.com.br* From boris at codesynthesis.com Thu Aug 11 09:48:11 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Thu Aug 11 09:50:46 2011 Subject: [odb-users] Error to run odb-examples!!! In-Reply-To: References: Message-ID: Hi Kleber, kleber molica writes: > I followed all instructions to make right odb, libodb, libodb-sqlite and > libodb-qt install. > When I tried to run Hello example I got this error: > > ./driver: error while loading shared libraries: libodb-sqlite-1.5.so: cannot > open shared object file: No such file or directory Depending on where you installed everything (by default /usr/local/), you may need to add the lib/ directory to the LD_LIBRARY_PATH environment variable. Try this from the terminal: $ export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH $ ./driver Boris From eric.b.sum at lmco.com Fri Aug 12 08:43:23 2011 From: eric.b.sum at lmco.com (Sum, Eric B) Date: Fri Aug 12 09:14:54 2011 Subject: [odb-users] How to represent member double* in a persistent class Message-ID: <08372F3F863B0044B6888E7E511186670287024DCF@HVXMSP6.us.lmco.com> Hi, I am declaring a class persistent, and one of the members of the class is a pointer to a double(double*). So far, I have seen two ways to represent this in odb: 1. Declare it as an integer(#pragma db type("INTEGER")) 2. Use a smart pointer to represent it(for example shared_ptr) What is the best way to represent a pointer to a double in odb? Thanks, Eric From eric.b.sum at lmco.com Fri Aug 12 08:58:27 2011 From: eric.b.sum at lmco.com (Sum, Eric B) Date: Fri Aug 12 09:14:54 2011 Subject: [odb-users] Error: "--include-regex: error: unable to open in read mode" Message-ID: <08372F3F863B0044B6888E7E511186670287024E23@HVXMSP6.us.lmco.com> HI, I am trying to follow these instructions for making a timeval struct a composite value member of a persistent class: Storing timeval as a composite value is a bit trickier because it is defined in a system header and, as you mentioned, we don't want to modify it by adding a pragma that tells the ODB compiler it is a composite value type. What we can do is add this pragma into the ODB compilation process using the --odb-epilogue option. We will also need to use the --include-regex option (added in ODB 1.5.0) to fix up some of the includes. Here are step-by-step instructions for a test header I created (test.hxx): #include #pragma db object class person { public: #pragma db id unsigned long id_; timeval time_; }; 1. First, I created the "mapping file" for sys/time.h, I called it time-mapping.h, it contains just this line: #pragma db value(timeval) 2. Now if I try to compile /usr/include/sys/time.h, I get empty generated files. As it turns out, timeval is defined in the bits/time.h header which is included by sys/time.h. So the ODB compiler command line I used is this: odb -d sqlite --odb-epilogue-file time-mapping.h \ --include-regex '%time.h%%' -D __need_timeval \ /usr/include/bits/time.h The __need_timeval define is needed in order to make bits/time.h to define struct timeval. This step will product a set of C++ source file (time-odb.?xx) that contain the persistence code for struct timeval. 3. To compile test.hxx, I used this command line: odb -d sqlite --odb-epilogue-file time-mapping.h \ --include-regex '%bits/time-odb.hxx%"time-odb.hxx"%' test.hxx To tidy this up, you may want to place some of the options into an options file, e.g., time.options: --odb-epilogue-file time-mapping.h --include-regex '%bits/time-odb.hxx%"time-odb.hxx"%' Then the command lines become: odb -d sqlite --include-regex '%time.h%%' -D __need_timeval \ --options-file time.options /usr/include/bits/time.h odb -d sqlite --options-file time.options test.hxx I set these exact files up (test.hxx and time-mapping.h), but when I try the odb compiler command in step 2, I get "-include-regex: error: unable to open in read mode". I am not sure how to go about fixing this. What does this error mean? I am using version 1.5.0 of the odb compiler. Thanks, Eric From boris at codesynthesis.com Fri Aug 12 09:16:16 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Fri Aug 12 09:18:52 2011 Subject: [odb-users] Error: "--include-regex: error: unable to open in read mode" In-Reply-To: <08372F3F863B0044B6888E7E511186670287024E23@HVXMSP6.us.lmco.com> References: <08372F3F863B0044B6888E7E511186670287024E23@HVXMSP6.us.lmco.com> Message-ID: Hi Eric, Sum, Eric B writes: > I set these exact files up (test.hxx and time-mapping.h), but when I > try the odb compiler command in step 2, I get "-include-regex: error: > unable to open in read mode". I think you misspelled the option name. It should be --include-regex, not -include-regex (two leading minus signs). Boris From boris at codesynthesis.com Fri Aug 12 09:33:31 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Fri Aug 12 09:36:11 2011 Subject: [odb-users] How to represent member double* in a persistent class In-Reply-To: <08372F3F863B0044B6888E7E511186670287024DCF@HVXMSP6.us.lmco.com> References: <08372F3F863B0044B6888E7E511186670287024DCF@HVXMSP6.us.lmco.com> Message-ID: Sum, Eric B writes: > What is the best way to represent a pointer to a double in odb? In the upcoming release of ODB we have added the concept of wrappers which would make handling this case quite easy. In the meantime, you will need to map double* to a suitable database type (REAL for SQLite) by, for example, adding something like this into your header: typedef double* double_ptr; #pragma db value(double_ptr) type("REAL") You will also need to create a value_traits specialization for double*. The following example shows how it could look (again for the SQLite database) assuming double* points to a dynamically allocated value: namespace odb { namespace sqlite { template <> struct value_traits { typedef double* value_type; typedef double query_type; typedef double image_type; static void set_value (double*& v, double i, bool is_null) { if (is_null) { delete v; v = 0; } else { if (v == 0) v = new double; *v = i; } } static void set_image (double& i, bool& is_null, double* v) { is_null = (v == 0); if (!is_null) i = *v; } }; } } See the 'mapping' example for information on where to place this traits specialization and how to include it into the generated code. Boris From losintikfos at yahoo.co.uk Sun Aug 14 15:12:16 2011 From: losintikfos at yahoo.co.uk (Bright Dadson) Date: Mon Aug 15 08:40:52 2011 Subject: [odb-users] Mapping abstract Message-ID: <1313349136.47270.YahooMailClassic@web29305.mail.ird.yahoo.com> I have a file called `Account.h` as shown below: ??? #ifndef ACCOUNT_H_ ??? #define ACCOUNT_H_ ?? //forward declaration of address ?? class Address address; ??? ??? #pragma db object abstract ??? class Account ??? { ????? //fields and methods ????? //Inverse bi-directional mapping to Address ??? }; ??? #endif /* ACCOUNT_H_ */ I also have a second file called `Address.h` as shown below: ??? #ifndef ADDRESS_H_ ??? #define ADDRESS_H_ ??? #include "Account.h" ??? ??? typedef Account account_type;//Error her ??? class Address ??? { ???? //Fields and methods ??? }; ??? #endif /* ADDRESS_H_ */ My problem is, when I try to map to Account, I get the error `Account is Abstract`. I want to be able to map to the abstract instead of mappping to each base class - I think doing it this way will remove the verbosity of the mapping code across inherited classes. Is there a simple way of doing this, can I map to the abstract base class, so all children classes will inherit this? Also Is my forward declaration of Address in Account correct? well considering they are different files. Thanks. From losintikfos at yahoo.co.uk Sun Aug 14 18:35:38 2011 From: losintikfos at yahoo.co.uk (Bright Dadson) Date: Mon Aug 15 08:40:52 2011 Subject: [odb-users] Bi-directional mapping to Abstract class Message-ID: <1313361338.37008.YahooMailClassic@web29309.mail.ird.yahoo.com> This thread has been posted already, didn't know how to modify the previous as I had mistakes in it, so I thought I resend it again. I have a file called `Account.h` as shown below: ??? #ifndef ACCOUNT_H_ ??? #define ACCOUNT_H_ ?? //forward declaration of address ?? class Address address; ??? ??? #pragma db object abstract ??? class Account ??? { ????? //fields and methods ????? //Inverse bi-directional mapping to Address ??? }; ??? #endif /* ACCOUNT_H_ */ I also have a second file called `Address.h` as shown below: ??? #ifndef ADDRESS_H_ ??? #define ADDRESS_H_ ??? #include "Account.h" ??? ??? typedef Account account_type; ??? class Address ??? { ???? //Fields and methods ???? ... ???? //Mapping to account_type //..Error here ??? }; ??? #endif /* ADDRESS_H_ */ My problem is, when I try to map to Account, I get the error `Account is Abstract`. I want to be able to map to the abstract instead of mappping to each child inherited class - I think doing it this way will remove the verbosity of the mapping code across inherited classes. Is there a simple way of doing this, can I map to the abstract base class, so all children classes will inherit this? Also Is my forward declaration of Address in Account correct? well considering they are different files. Thanks. From boris at codesynthesis.com Mon Aug 15 08:48:42 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Mon Aug 15 08:51:16 2011 Subject: [odb-users] Bi-directional mapping to Abstract class In-Reply-To: <1313361338.37008.YahooMailClassic@web29309.mail.ird.yahoo.com> References: <1313361338.37008.YahooMailClassic@web29309.mail.ird.yahoo.com> Message-ID: Hi, Bright Dadson writes: > My problem is, when I try to map to Account, I get the error `Account is > Abstract`. I want to be able to map to the abstract instead of mappping > to each child inherited class - I think doing it this way will remove > the verbosity of the mapping code across inherited classes. What you are looking for (I think) is polymorphism inheritance which is not yet supported by ODB. See Chapter 8 in the ODB manual for details. Boris From roland.kloeters at xcom.de Tue Aug 16 11:11:16 2011 From: roland.kloeters at xcom.de (Roland Kloeters) Date: Tue Aug 16 13:59:06 2011 Subject: [odb-users] Executing native selects for no mapped type Message-ID: <1313507476.14503.7.camel@merkur> Hello, I am new to ODB and I am surprised how nice and easy it is to use it. But now I am close to some limitations. I have an entity defined in my db which has a primary key and gets its value from the designated sequence. So far so good. Now I have a second value that is some sort of sequence number declaring an order of how these values have been inserted in the db. But that sequence is not always the same for each row of that entity. As I cannot set the value by default using #pragma db id auto I have to select the value from the sequence directly. I am using postgresql as RDMS so my select would be: "select nextval('sequence')". But how can I get the result of that select? Using odb::database::execute just gives me the number of rows that have been affected. In that case: always 1 So my question is: Is there any chance of executing native select statements and retrieving the results? Kind regards Roland *** XCOM AG Legal Disclaimer *** Diese E-Mail einschliesslich ihrer Anhaenge ist vertraulich und ist allein f?r den Gebrauch durch den vorgesehenen Empfaenger bestimmt. Dritten ist das Lesen, Verteilen oder Weiterleiten dieser E-Mail untersagt. Wir bitten, eine fehlgeleitete E-Mail unverzueglich vollstaendig zu loeschen und uns eine Nachricht zukommen zu lassen. This email may contain material that is confidential and for the sole use of the intended recipient. Any review, distribution by others or forwarding without express permission is strictly prohibited. If you are not the intended recipient, please contact the sender and delete all copies. Hauptsitz: Bahnstrasse 37, D-47877 Willich, USt-IdNr.: DE 812 885 664 Kommunikation: Telefon +49 2154 9209-70, Telefax +49 2154 9209-900, www.xcom.de Handelsregister: Amtsgericht Krefeld, HRB 10340 Vorstand: Matthias Albrecht, Dirk Franzmeyer, Dr. Rainer Fuchs, Marco Marty, Dirk Werner Vorsitzender des Aufsichtsrates: Stefan H. Tarach From roland.kloeters at xcom.de Wed Aug 17 06:07:14 2011 From: roland.kloeters at xcom.de (Roland Kloeters) Date: Wed Aug 17 06:07:53 2011 Subject: [odb-users] Ordering of results Message-ID: <1313575634.3316.0.camel@merkur> Hi folks, is there any chance of getting the results from a query in an order way? Kind regards Roland From boris at codesynthesis.com Wed Aug 17 06:51:34 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Wed Aug 17 06:54:08 2011 Subject: [odb-users] Executing native selects for no mapped type In-Reply-To: <1313507476.14503.7.camel@merkur> References: <1313507476.14503.7.camel@merkur> Message-ID: Hi Roland, Roland Kloeters writes: > As I cannot set the value by default using #pragma db id auto I have to > select the value from the sequence directly. > > I am using postgresql as RDMS so my select would be: "select > nextval('sequence')". > > [...] > > Is there any chance of executing native select statements and retrieving > the results? One way to do it would be to get the native Postgres connection handle from odb::pgsql::connection and execute the query using the low-level C API (libpq). This is not the most convenient way but it is always an option. Also we have been thinking about supporting what we call 'view' objects. A view is a read-only object that can only be loaded using a query. They could be useful for retrieving only a porting of an object, supporting ad-hoc table joins, or performing stored procedure calls. Here is an example: #pragma db view query("SELECT person.name, employer.name FROM person LEFT JOIN employer ON person.employer = employer.id") struct name_and_employer { string name; string employer; }; typedef query query; typedef result result; result r ( db->query ( "WHERE person.age < " + query::_val(30)); Your case would have been handled like this: #pragma db view query("SELECT nextval('sequence')") struct sequence_value { unsigned long long value; }; result r (db->query ()); Or you could specify the actual sequence name at the query execution time: #pragma db view struct sequence_value { unsigned long long value; }; string seq_name = ...; result r ( db->query ( "SELECT nextval('" + query::_val (seq_name) + "')"); Do you think something like this will work well for your use case? In fact, it is possible to kind of emulate views using the existing objects functionality. First we define the object (it must contain the dummy object id): #pragma db object struct sequence_value { #pragma db id unsigned int dummy; unsigned long long value; }; Then the transaction that gets the next value would look like this (PostgreSQL-specific code): #include #include #include namespace pgsql = odb::pgsql; transaction t (db->begin ()); odb::result r; { pgsql::connection& conn (pgsql::transaction::current ().connection ()); odb::query q; odb::details::shared_ptr st ( new (odb::details::shared) pgsql::select_statement ( conn, "sequence_value_query" // Statement name. "select 0, nextval('sequence')", q.parameter_types (), q.parameter_count (), q.parameters_binding (), conn.statement_cache ().find ().out_image_binding ())); st->execute (); st->deallocate (); odb::details::shared_ptr > ri ( new (odb::details::shared) pgsql::result_impl ( q, st, conn.statement_cache ().find ())); r = odb::result (ri); } // Iterate over the query result as usual. For example, r->begin ()->value // is the returned sequence value. t.commit (); This could be a temporary solution until views are supported natively by ODB. Boris From boris at codesynthesis.com Wed Aug 17 06:59:01 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Wed Aug 17 07:01:34 2011 Subject: [odb-users] Ordering of results In-Reply-To: <1313575634.3316.0.camel@merkur> References: <1313575634.3316.0.camel@merkur> Message-ID: Hi Roland, Roland Kloeters writes: > is there any chance of getting the results from a query in an order way? Yes, for now you will need to use something like this: result r (db->query ((query::last == "Doe") + "ORDER BY age")); The native support for order-by (so that you can specify the column as query::age) is still in the works. Boris From roland.kloeters at xcom.de Wed Aug 17 07:34:17 2011 From: roland.kloeters at xcom.de (Roland Kloeters) Date: Wed Aug 17 07:34:57 2011 Subject: [odb-users] Executing native selects for no mapped type In-Reply-To: References: <1313507476.14503.7.camel@merkur> Message-ID: <1313580857.3316.3.camel@merkur> Hi Boris, of course there is a way I could use. I would prefer to use #pragma db view query("SELECT nextval('sequence')") struct sequence_value { unsigned long long value; }; result r (db->query ()); Or you could specify the actual sequence name at the query execution time: #pragma db view struct sequence_value { unsigned long long value; }; string seq_name = ...; result r ( db->query ( "SELECT nextval('" + query::_val (seq_name) + "')"); Unfortunately my ODB Compiler is not willing to know the pragma "view". I get an error like "Sequence.h:16:19: error: unknown db pragma 'view'" What now? Kind regards Roland Am Mittwoch, den 17.08.2011, 12:51 +0200 schrieb Boris Kolpackov: > Hi Roland, > > Roland Kloeters writes: > > > As I cannot set the value by default using #pragma db id auto I have to > > select the value from the sequence directly. > > > > I am using postgresql as RDMS so my select would be: "select > > nextval('sequence')". > > > > [...] > > > > Is there any chance of executing native select statements and retrieving > > the results? > > One way to do it would be to get the native Postgres connection handle > from odb::pgsql::connection and execute the query using the low-level > C API (libpq). This is not the most convenient way but it is always an > option. > > Also we have been thinking about supporting what we call 'view' objects. > A view is a read-only object that can only be loaded using a query. They > could be useful for retrieving only a porting of an object, supporting > ad-hoc table joins, or performing stored procedure calls. Here is an > example: > > #pragma db view query("SELECT person.name, employer.name FROM person LEFT JOIN employer ON person.employer = employer.id") > struct name_and_employer > { > string name; > string employer; > }; > > typedef query query; > typedef result result; > > result r ( > db->query ( > "WHERE person.age < " + query::_val(30)); > > Your case would have been handled like this: > > #pragma db view query("SELECT nextval('sequence')") > struct sequence_value > { > unsigned long long value; > }; > > result r (db->query ()); > > Or you could specify the actual sequence name at the query execution time: > > #pragma db view > struct sequence_value > { > unsigned long long value; > }; > > string seq_name = ...; > > result r ( > db->query ( > "SELECT nextval('" + query::_val (seq_name) + "')"); > > Do you think something like this will work well for your use case? > > In fact, it is possible to kind of emulate views using the existing > objects functionality. First we define the object (it must contain > the dummy object id): > > #pragma db object > struct sequence_value > { > #pragma db id > unsigned int dummy; > > unsigned long long value; > }; > > Then the transaction that gets the next value would look like this > (PostgreSQL-specific code): > > #include > #include > #include > > namespace pgsql = odb::pgsql; > > transaction t (db->begin ()); > > odb::result r; > > { > pgsql::connection& conn (pgsql::transaction::current ().connection ()); > > odb::query q; > > odb::details::shared_ptr st ( > new (odb::details::shared) pgsql::select_statement ( > conn, > "sequence_value_query" // Statement name. > "select 0, nextval('sequence')", > q.parameter_types (), > q.parameter_count (), > q.parameters_binding (), > conn.statement_cache ().find ().out_image_binding ())); > > st->execute (); > st->deallocate (); > > odb::details::shared_ptr > ri ( > new (odb::details::shared) pgsql::result_impl ( > q, st, conn.statement_cache ().find ())); > > r = odb::result (ri); > } > > // Iterate over the query result as usual. For example, r->begin ()->value > // is the returned sequence value. > > t.commit (); > > This could be a temporary solution until views are supported natively by > ODB. > > Boris From boris at codesynthesis.com Wed Aug 17 08:46:25 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Wed Aug 17 08:49:01 2011 Subject: [odb-users] Executing native selects for no mapped type In-Reply-To: <1313580857.3316.3.camel@merkur> References: <1313507476.14503.7.camel@merkur> <1313580857.3316.3.camel@merkur> Message-ID: Hi Roland, Roland Kloeters writes: > Unfortunately my ODB Compiler is not willing to know the pragma "view". Sorry, I must have been unclear in my original email. The view feature is not yet supported. At this stage we are only thinking about possible use-cases and designs. Boris From boris at codesynthesis.com Wed Aug 17 10:03:26 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Wed Aug 17 10:06:01 2011 Subject: [odb-users] Handling pimpl idiom in ODB Message-ID: [Original message sent privately. CC'ing odb-users into the discussion.] Hi Uwe, cetoni GmbH - Uwe Kindler writes: > Our Qt based software is plugin based and uses a lot of shared > libraries. In order to ensure binary compatibility and to lower the > needs to recompile libraries we prefer to use the pimpl idiom like it is > used in the Qt framework. Until now we did not use the idiom for all > classes that are stored into database by ODB because ODB needs access to > the members. Because these persistent classes are used by a lot of our > plugins, adding or removing only a single member variable causes a > recompile of all shared libraries and plugins because binary > compatibility is broken. > > That was the reason for me, to think about ODB and the use of the pimpl > idiom at the same time and I created a small test case that works: > > #pragma db object > class COdbPimplTestPrivate > { > public: > #pragma db id auto > long Id; > double DoubleValue; > int IntValue; > QString Name; > }; > > > #pragma db object > class COdbPimplTest > { > friend class odb::access; > public: > #pragma db id auto > long m_Id; > boost::shared_ptr d; > > public: > COdbPimplTest(); > double doubleValue() const; > }; > > So the real data members are stored in the private class and the public > class has only a pointer to the private class. This results in two > tables - one for the private class with all the data and one for the > public class that consists only of the ID and the foreign key to the > private class. What do you hink about this design? Do you have a better > idea to use ODB and the pimpl idiom at the same time or is there any > best practice for ODB and pimpl classes. The method that you have described works but is not ideal. It is wasteful in the sense that it results in two tables per object as well as requires two SELECT statements to load an object. It is also conceptually incorrect since there is really only one object, not two. After thinking some more about this, I see two ways how a pimpl idiom can be handled. With the first approach we make the 'impl' class an ODB object and store that in the database. Because the 'impl' class is the implementation detail of the 'interface' class, with this approach we would also have to hide (or wrap) the database loading/storing logic. In other words, the persistence of the class becomes its implementation details. Here is how this can look: #pragma db object class COdbPimplTestPrivate { public: #pragma db id auto long Id; double DoubleValue; int IntValue; QString Name; }; class COdbPimplTest { boost::shared_ptr d; public: // Database operations. // COdbPimplTest(odb::database& db, long id) { d = db.load (id); } void persist (odb::database& db) { db->persist (d); } void update (odb::database& db) { db->update (d); } }; The major limitation of this approach is the fact that you have to wrap the odb::database operations that are normally available to the persistent objects. This can be easy for operations like persist() and load() and more complicated for query() (because COdbPimplTest is not a persistent object, we cannot use odb::query or odb::result). Handling inheritance with this approach can also be tricky. Though inheritance is generally tricky with pimpl. This approach is supported by ODB now. The alternative approach is to make the 'interface' class the ODB persistent object and treat the 'impl' class as just details of how the data is stored. While both approaches have their merits and which one to use will ultimately depend on the application requirements, IMO, the second approach better reflects the purpose of why we use the pimpl idiom in the first place. Now, there is no way to support the second approach in the current state of ODB (as of version 1.5.0) because, as you have pointed out, ODB needs direct access to the object's data members. However, for some time now, we have been thinking about a feature that would relax this requirement and which would allow us to handle the second pimpl approach as well as some other use-cases, such as objects with private data members that cannot be modified by adding the friend declaration. In a nutshell, the idea is to have what we call "virtual data members" which are not really data members but rather a pair of accessor and modifier expressions. Here is an example (the exact syntax is not yet finalized): class COdbPimplTestPrivate { public: long Id; double DoubleValue; int IntValue; QString Name; }; #pragma db object class COdbPimplTest { #pragma db transient boost::shared_ptr d; public: double doubleValue() const; void doubleValue(double) const; #pragma db member(Id) virtual(long) get(this->d->Id) id auto #pragma db member(DoubleValue) virtual(double) \ get(this->doubleValue ()) set(this->doubleValue (?)) ... }; Which approach do you think will work best for your case? If it is the second, do you see any issues with the virtual member-based implementation? Boris From jan.kuentzer at roche.com Wed Aug 17 12:06:40 2011 From: jan.kuentzer at roche.com (Kuentzer, Jan) Date: Wed Aug 17 12:06:46 2011 Subject: [odb-users] Inheritance In-Reply-To: References: <38307BF0D71C2644BDA445BF0AFED3654DC197AA4F@mx1> <24FA8A6483D7144F8D95F61A94417815049CCAA896@RKAMSEM705.emea.roche.com> Message-ID: <24FA8A6483D7144F8D95F61A9441781504A08CD5EC@RKAMSEM705.emea.roche.com> Hi Boris, Thanks again for the workaround for the polymorphic inheritance which works fine with the current release. I use as you suggested id fields with transient pointer. I implemented a callback method for post_load and pre_persist. The persist works fine and the ids are correctly written in the database. But I found a strange behavior with the post_load which I cannot explain. I have a derived class (e.g. node_set) having a polymorphic variable with the type of the super class (e.g. node). This means the variable could actually be of the same type as the class itself (e.g. the node could be a node_set). If this is the case, the load method is not working. If the attribute is of another type everything is loaded perfectly fine. Is this a problem of the callback method since I load an object of the same type? If I load the attribute alone by id outside the callback method everything works fine. Best Jan > > The idea behind emulation is to encode the object type into the id. This > way, when you load the object, you can first figure out its actual type > and then load it from the database. In this approach you cannot use the > automatically-assigned ids for the hierarchy, and all objects in the > hierarchy must share the same id space. > > As an example, let's use a 64-bit integer as an id for our employee > hierarchy. To encode the object type, we will reserve the top byte > and will use 1 for permanent_employee and 2 for temporary_employee > (employee class is abstract and doesn't need a type code). > > #pragma db object abstract > class employee > { > public: > ... > > unsigned long long > id () const > { > return id_; > } > > protected: > friend class odb::access; > employee () {} // Default c-tor for ODB. > > // C-tor for derived types. > // > employee (unsigned char type_code, unsigned long long id) > { > id = (type_code << 56) | (id & 0x00FFFFFFFFFFFFFFUL); > } > > #pragma db id > unsigned long long id_; > }; > > #pragma db object > class permanent_employee > { > public: > permanent_employee (unsigned long long id) > : employee (1 /* type code for permanent_employee */, id) > { > } > > ... > > }; > > #pragma db object > class temporary_employee > { > public: > temporary_employee (unsigned long long id) > : employee (2 /* type code for temporary_employee */, id) > { > } > > ... > > }; > > Next we need to wrap the database operation with some extra logic. > Here is polymorphic persist: > > unsigned long long > persist_employee (odb::database& db, employee* e) > { > switch (d->id () >> 56) // Get the type code. > { > case 1: > return db->persist (static_cast (e)); > case 2: > return db->persist (static_cast (e)); > default: > assert (false); > } > }; > > And here is polymorphic load() (note that id should be what's returned > by the persist() call or what's stored in employee::id_, not what we > pass to *_employee constructors). > > employee* > load_employee (odb::database& db, unsigned long long id) > { > switch (id >> 56) // Get the type code. > { > case 1: > return db->load (id); > case 2: > return db->load (id); > default: > assert (false); > } > } > > Finally, in order to have a polymorphic object relationship, you will > need to emulate it by having a persistent member that is the object > id and a transient member which is the actual pointer: > > #pragma db object > class employer > { > ... > > unsigned long long ceo_id_; > > #pragma db transient > employee* ceo_; > }; > > You will then need to use the load_employee() function to load the ceo_ > pointer. For the next release of ODB we have added support for user > callbacks. This feature will allow you to handle such loading > transparently. > > Boris From uwe_kindler at web.de Wed Aug 17 13:28:16 2011 From: uwe_kindler at web.de (Uwe Kindler) Date: Wed Aug 17 14:30:02 2011 Subject: [odb-users] Re: Handling pimpl idiom in ODB In-Reply-To: References: Message-ID: <4E4BFA30.4000303@web.de> Hi Boris, I think your first approach, making only the 'impl' class an ODB object will not work. Because then I cannot use the public interface class in a relation because ODB does not know anything about the interface class. That means I cannot have another persistent class that has a one to many or one to one relation to my COdbPimplTest interface class. Exactly this was the reason I made the private impl class as well as the public interface class ODB objects. When I first thought about this problem, I tried to solve it with a composite value type. That means I thought of the private impl class as a composite value type. But it was not possible to use a pointer to a composite value type so I decided to go the persistent object way. Regarding the second approach I have a question. The keyword virtual does not mean, that it will be a virtual method, or does it? If it would be a virtual method then it would not work because virtual methods also break binary compatibility. So I assume the keyword virtual simply identifies virtual ODB members. As long as the accessor and modifier expressions are non virtual private or protected C++ methods, I don't see any issues at the moment. The problem with the second approach is, that it would cause a lot of pragmas for the accessors and modifiers. At the moment one big plus for ODB is that I can make a class persistent with a minimum number of changes: Often #pragma db object #pragma db id auto friend class odb::access; are the only thing you need to make a class persistent. An then I would need to write a pragma for each member. This won't make the more beautiful ;O). But if it works, I think it would be o.k. What do you think about the composite value approach. Would it be possible to implement pointers to composite values? Kind Regards, Uwe From eric.b.sum at lmco.com Wed Aug 17 14:02:22 2011 From: eric.b.sum at lmco.com (Sum, Eric B) Date: Wed Aug 17 14:30:02 2011 Subject: [odb-users] Recommendations for Mass-Deleting from SQLite Database table Message-ID: <08372F3F863B0044B6888E7E5111866702876D9C88@HVXMSP6.us.lmco.com> I am trying to delete a group of objects(previously persisted in odb) from a table in a SQLite database that match a certain condition. I can think of two ways to do this: 1. Use the query API from ODB to get all objects that match that condition and store them in an ODB result. Then, call the ODB erase function to delete the persistent object from the database. 2. Call the execute function in ODB, and execute a native SQL statement such as "DELETE FROM WHERE " such that the condition expression matches the same query in the first option . There will be MANY entries in the table, and there are going to be MANY objects to delete based on the condition, so I am going to be performing a massive delete in the database. Which of these options would you recommend for speed/efficiency/performance since I am going to be performing such a massive delete? Any other suggestions for performing such an operation? Thanks, Eric From kleber.molica at gmail.com Wed Aug 17 20:21:13 2011 From: kleber.molica at gmail.com (kleber molica) Date: Wed Aug 17 20:21:22 2011 Subject: [odb-users] Error to run odb-examples!!! In-Reply-To: References: Message-ID: Thanks! On Thu, Aug 11, 2011 at 10:48 AM, Boris Kolpackov wrote: > Hi Kleber, > > kleber molica writes: > > > I followed all instructions to make right odb, libodb, libodb-sqlite and > > libodb-qt install. > > When I tried to run Hello example I got this error: > > > > ./driver: error while loading shared libraries: libodb-sqlite-1.5.so: > cannot > > open shared object file: No such file or directory > > Depending on where you installed everything (by default /usr/local/), you > may need to add the lib/ directory to the LD_LIBRARY_PATH environment > variable. Try this from the terminal: > > $ export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH > $ ./driver > > Boris > -- *Kleber Augusto Molica* Engenharia de Software Core Networks Ltda Rua Coronel Francisco Br?z, n? 185, sala 204 - Centro - ITAJUB?/MG CEP: 37500-052 *Tel.: (35) 3622 3444* *kleber@corenetworks.com.br* From boris at codesynthesis.com Thu Aug 18 05:42:11 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Thu Aug 18 05:44:45 2011 Subject: [odb-users] Inheritance In-Reply-To: <24FA8A6483D7144F8D95F61A9441781504A08CD5EC@RKAMSEM705.emea.roche.com> References: <38307BF0D71C2644BDA445BF0AFED3654DC197AA4F@mx1> <24FA8A6483D7144F8D95F61A94417815049CCAA896@RKAMSEM705.emea.roche.com> <24FA8A6483D7144F8D95F61A9441781504A08CD5EC@RKAMSEM705.emea.roche.com> Message-ID: Hi Jan, Kuentzer, Jan writes: > I have a derived class (e.g. node_set) having a polymorphic variable with > the type of the super class (e.g. node). This means the variable could > actually be of the same type as the class itself (e.g. the node could > be a node_set). If this is the case, the load method is not working. > If the attribute is of another type everything is loaded perfectly > fine. Is this a problem of the callback method since I load an object > of the same type? If I load the attribute alone by id outside the > callback method everything works fine. I looked into this and apparently we had a bug there. Here is the message for the fix I just committed: " Fix custom recursive load in post_load callback Before we called the callback while holding the statements locked. As a result, if the callback tried to load another object of this type, it failed. Now we unlock the statements (since we have completely loaded the object from ODB's point of view) and then call the callback. The callback test has been updated to test this situation. " I can build you a pre-release snapshot of ODB with this fix if you would like. Just let me know for which platform you need the ODB binary, if any. Boris From jan.kuentzer at roche.com Thu Aug 18 06:37:10 2011 From: jan.kuentzer at roche.com (Kuentzer, Jan) Date: Thu Aug 18 06:37:16 2011 Subject: [odb-users] Inheritance In-Reply-To: References: <38307BF0D71C2644BDA445BF0AFED3654DC197AA4F@mx1> <24FA8A6483D7144F8D95F61A94417815049CCAA896@RKAMSEM705.emea.roche.com> <24FA8A6483D7144F8D95F61A9441781504A08CD5EC@RKAMSEM705.emea.roche.com> Message-ID: <24FA8A6483D7144F8D95F61A9441781504A08CD738@RKAMSEM705.emea.roche.com> Hi Boris, Thanks for the quick reply ! > -----Original Message----- > From: Boris Kolpackov [mailto:boris@codesynthesis.com] > > I can build you a pre-release snapshot of ODB with this fix if you would like. Just > let me know for which platform you need the ODB binary, if any. I use the odb-1.5.0-i686-linux-gnu version with mysql. If you could send me the snapshot it would be perfect. I will then regenerate the -odb files for the classes. Do I also need to download and rebuild libodb and libodb-mysql? Jan From boris at codesynthesis.com Thu Aug 18 07:12:57 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Thu Aug 18 07:15:30 2011 Subject: [odb-users] Re: Handling pimpl idiom in ODB In-Reply-To: <4E4BFA30.4000303@web.de> References: <4E4BFA30.4000303@web.de> Message-ID: Hi Uwe, Uwe Kindler writes: > I think your first approach, making only the 'impl' class an ODB object > will not work. Because then I cannot use the public interface class in a > relation because ODB does not know anything about the interface class. > That means I cannot have another persistent class that has a one to many > or one to one relation to my COdbPimplTest interface class. Yes, I missed that. This is another pretty big limitation of the first approach. > When I first thought about this problem, I tried to solve it with a > composite value type. That means I thought of the private impl class as > a composite value type. But it was not possible to use a pointer to a > composite value type so I decided to go the persistent object way. That's actually a pretty good idea. See more on that below. > Regarding the second approach I have a question. The keyword virtual > does not mean, that it will be a virtual method, or does it? No, virtual in this context simply means that there is no actual C++ data member. > The problem with the second approach is, that it would cause a lot of > pragmas for the accessors and modifiers. At the moment one big plus for > ODB is that I can make a class persistent with a minimum number of > changes: > > Often > > #pragma db object > #pragma db id auto > friend class odb::access; > > are the only thing you need to make a class persistent. An then I would > need to write a pragma for each member. This won't make the more > beautiful ;O). But if it works, I think it would be o.k. Yes, that's the drawback. However, it kind of parallels the extra work you have to do when you use the pimpl idiom, such as forwarding the calls to the 'impl' class. In essence, the virtual member pragma is 'forwarding' of the data member to the one in 'impl' class. Note also that the pragmas can always be moved out of the class or even into a separate file. Plus, as I will discuss in more detail below, this approach is the most flexible. > What do you think about the composite value approach. Would it be > possible to implement pointers to composite values? Yes, I think it would. For the upcoming release of ODB, we have implemented the concept of wrappers. In ODB, wrapper is essentially a type that wraps a value type. The primary purpose of wrappers is to add the NULL semantics to types that otherwise don't have it. However, wrappers don't have to handle NULL (such wrappers are called transparent). Some examples of wrappers include smart pointers and optional value containers, such as boost::optional. Now, currently, wrappers are only supported for simple values because at the moment we only support the NULL semantics for simple values. However, there are plans to extend the NULL support to composite values and maybe even containers. So the idea is that wrappers should work equally well for both simple and composite values. I can now see how a transparent wrapper for a composite value can be very useful when implementing the pimpl idiom. There are a couple of limitations to this approach, however: 1. The id member will have to be defined in the 'interface' class instead of the 'impl' class. This is probably not a big issue since presumably this member doesn't get added/deleted/changed very often. Note that the virtual member approach doesn't have this limitation. 2. Organizationally, you will need to have a separate header that contains the 'impl' value definition. Normally, the 'impl' class is defined in the source file. Again, the virtual member approach doesn't have this limitation. 3. Whenever you need to perform a database operation, the definition of the 'impl' value type will have to be visible. In other words, whenever you #include the -odb.hxx file corresponding to the object, the definition of the value type will be included as well. I am not sure if this is an issue in your case. Again, the virtual member approach doesn't have this limitation. Would you like to give the value type approach a try? If so, I can add support for transparent wrappers for composite values and build you a pre-release binary. Just let me know for which platform you need the ODB compiler binary, if any. Boris From boris at codesynthesis.com Thu Aug 18 09:41:41 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Thu Aug 18 09:44:16 2011 Subject: [odb-users] Recommendations for Mass-Deleting from SQLite Database table In-Reply-To: <08372F3F863B0044B6888E7E5111866702876D9C88@HVXMSP6.us.lmco.com> References: <08372F3F863B0044B6888E7E5111866702876D9C88@HVXMSP6.us.lmco.com> Message-ID: Hi Eric, Sum, Eric B writes: > I am trying to delete a group of objects(previously persisted in odb) > from a table in a SQLite database that match a certain condition. > > I can think of two ways to do this: > > 1. Use the query API from ODB to get all objects that match that condition > and store them in an ODB result. Then, call the ODB erase function to > delete the persistent object from the database. > > 2. Call the execute function in ODB, and execute a native SQL statement such > as "DELETE FROM WHERE " such that the > condition expression matches the same query in the first option . > > There will be MANY entries in the table, and there are going to be MANY > objects to delete based on the condition, so I am going to be performing > a massive delete in the database. > > Which of these options would you recommend for speed/efficiency/performance > since I am going to be performing such a massive delete? Any other > suggestions for performing such an operation? The second approach will definitely be faster. In fact, for some time now I have been planning to add the query_erase() function, which would be similar to query() except that it will delete the objects instead of returning them. If you can wait, I should have it ready some time tomorrow and can build you a pre-release binary. Boris From n.albeza at gmail.com Thu Aug 18 09:51:07 2011 From: n.albeza at gmail.com (Nicolas ALBEZA) Date: Thu Aug 18 09:51:15 2011 Subject: [odb-users] ODB and aggregate functions Message-ID: Hello odb-users ! I'm looking for a way to use aggregate (group-by) functions with ODB, to use in simple queries, such as "SELECT AVG(field) from table where ...". It seems that ODB doesnt allow such things, so i guess i'll have to use the low-level and db specific functions to reach my goal. Is there any examples or documentation about that ? (I'm using a mysql DB). Thanks ! Regards, -- ALBEZA "Pause" Nicolas From uwe_kindler at web.de Thu Aug 18 11:05:16 2011 From: uwe_kindler at web.de (Uwe Kindler) Date: Fri Aug 19 04:19:07 2011 Subject: [odb-users] Re: Handling pimpl idiom in ODB In-Reply-To: References: <4E4BFA30.4000303@web.de> Message-ID: <4E4D2A2C.3070607@web.de> Hi Boris, that sounds great. I'm on vacation till september the 6th - so no need to hurry. But if I'm back from vacation I would like to give the value type approach a try. I would need the ODB compiler binary for Windows 7. Uwe From eric.b.sum at lmco.com Thu Aug 18 18:16:50 2011 From: eric.b.sum at lmco.com (Sum, Eric B) Date: Fri Aug 19 04:19:07 2011 Subject: [odb-users] Completing Transactions in the callback function of a persistent class Message-ID: <08372F3F863B0044B6888E7E51118667028777C87D@HVXMSP6.us.lmco.com> Hi, I am trying to make odb an transaction for querying and then deleting the result of that query on the post-persist event of the callback function of a persistent class. To do this, I need to include the proper header files such as odb/database.hxx and odb/transaction.hxx. However, when I include these files in the header file of the persistent class(where the callback function is) or in a different header file included by that persistent class's header file, I get lots of errors when I run the odb compiler on the persistent class's header file. The errors are about not being able to find object traits and other fields for the class that I am trying to make persistent. I am assuming that this is because I am trying to make a transaction in a persistent class. My ultimate goal is to make this such that every time an object of this type is persisted in the database, something gets triggered to perform a query and a delete in the database. Is there a way to declare odb transactions in the callback function of a persistent class? Thanks, Eric From boris at codesynthesis.com Fri Aug 19 04:22:25 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Fri Aug 19 04:24:57 2011 Subject: [odb-users] ODB and aggregate functions In-Reply-To: References: Message-ID: Hi Nicolas, Nicolas ALBEZA writes: > I'm looking for a way to use aggregate (group-by) functions with ODB, to use > in simple queries, such as "SELECT AVG(field) from table where ...". > > It seems that ODB doesnt allow such things, so i guess i'll have to use the > low-level and db specific functions to reach my goal. > Is there any examples or documentation about that ? (I'm using a mysql DB). I think the 'view' feature that is still in development will allow you to achieve this pretty easily. I have described it a couple of days ago in this post: http://www.codesynthesis.com/pipermail/odb-users/2011-August/000239.html Do you think it will work for your use case? Boris From n.albeza at gmail.com Fri Aug 19 05:17:05 2011 From: n.albeza at gmail.com (Nicolas ALBEZA) Date: Fri Aug 19 05:17:13 2011 Subject: [odb-users] ODB and aggregate functions In-Reply-To: References: Message-ID: It would fit perfectly. Regards, 2011/8/19 Boris Kolpackov > Hi Nicolas, > > Nicolas ALBEZA writes: > > > I'm looking for a way to use aggregate (group-by) functions with ODB, to > use > > in simple queries, such as "SELECT AVG(field) from table where ...". > > > > It seems that ODB doesnt allow such things, so i guess i'll have to use > the > > low-level and db specific functions to reach my goal. > > Is there any examples or documentation about that ? (I'm using a mysql > DB). > > I think the 'view' feature that is still in development will allow you > to achieve this pretty easily. I have described it a couple of days ago > in this post: > > http://www.codesynthesis.com/pipermail/odb-users/2011-August/000239.html > > Do you think it will work for your use case? > > Boris > -- ALBEZA "Pause" Nicolas From boris at codesynthesis.com Fri Aug 19 10:07:00 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Fri Aug 19 10:09:34 2011 Subject: [odb-users] Completing Transactions in the callback function of a persistent class In-Reply-To: <08372F3F863B0044B6888E7E51118667028777C87D@HVXMSP6.us.lmco.com> References: <08372F3F863B0044B6888E7E51118667028777C87D@HVXMSP6.us.lmco.com> Message-ID: Hi Eric, Sum, Eric B writes: > I am trying to make odb an transaction for querying and then deleting the > result of that query on the post-persist event of the callback function of a > persistent class. To do this, I need to include the proper header files > such as odb/database.hxx and odb/transaction.hxx. However, when I include > these files in the header file of the persistent class(where the callback > function is) or in a different header file included by that persistent > class's header file, I get lots of errors when I run the odb compiler on the > persistent class's header file. You need to move the body of the callback function to the source file instead of definiting it inline in the header. Generally, you cannot use database operations in the header file because for them you need to include the -odb.hxx file. But that file has not yet been created when the ODB compiler is compiling the header. Boris From n.albeza at gmail.com Fri Aug 19 12:52:40 2011 From: n.albeza at gmail.com (Nicolas ALBEZA) Date: Fri Aug 19 12:52:48 2011 Subject: [odb-users] Many to many relationships - Insertion and deletion Message-ID: Hello odb-users, I'm currently using ODB's many-to-many relationships in my projects, and i was wondering how to insert and delete entires efficiently. My classes look like (most of it omitted for clarity): class Project { #pragma db value_not_null unordered list > members; } class Account { #pragma db value_not_null inverse(members) list > projects; } Currently, to add an Account to a Project, i'm doing something along the lines of : shared_ptr account = db->find(...); shared_ptr project = db->find(...); project->members.push_back(account); db->update(project); Unfortunately, when looking at MySQL's query log, i can see the following queries being executed : - A full update of the project entry - Deletion of entries in the junction table - And finally, insertion of an entry in the junction table The two first steps seem unnecessary, so i was wondering if there was a better approach to do this. Thanks ! Regards, -- ALBEZA "Pause" Nicolas From boris at codesynthesis.com Mon Aug 22 10:43:45 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Mon Aug 22 10:46:41 2011 Subject: [odb-users] Many to many relationships - Insertion and deletion In-Reply-To: References: Message-ID: Hi Nicolas, Nicolas ALBEZA writes: > I'm currently using ODB's many-to-many relationships in my projects, and i > was wondering how to insert and delete entires efficiently. > > My classes look like (most of it omitted for clarity): > > class Project > { > #pragma db value_not_null unordered > list > members; > } > > class Account > { > #pragma db value_not_null inverse(members) > list > projects; > } > > Currently, to add an Account to a Project, i'm doing something along the > lines of : > > shared_ptr account = db->find(...); > shared_ptr project = db->find(...); You don't really need to load the Account object (unless you need it later). Instead, you can create an "unloaded" lazy pointer: lazy_shared_ptr account (*db, account_id); The 'inverse' example uses this technique. > project->members.push_back(account); > db->update(project); > > Unfortunately, when looking at MySQL's query log, i can see the following > queries being executed : > > - A full update of the project entry > - Deletion of entries in the junction table > - And finally, insertion of an entry in the junction table > > The two first steps seem unnecessary, so i was wondering if there was a > better approach to do this. Unfortunately, I am afraid this is as efficient as it can get right now. We still need to work on the state change detection and more optimal container handling. If you had a one-to-many relationship, then making the 'many' side inverse (and thus getting rid of the container table) would have been a viable optimization. Boris From boris at codesynthesis.com Mon Aug 22 10:46:05 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Mon Aug 22 10:48:36 2011 Subject: [odb-users] ODB 1.6.0.a1 available Message-ID: Hi, The first alpha version for the upcoming ODB 1.6.0 is now available. The NEWS file entries so far are: * SQLite ODB runtime now enabled foreign key constraints checking by default. While this should not affect correct applications, due to bugs in SQLite DDL foreign keys support, you may need to temporarily disable foreign key constraints checking when re-creating the database schema (the sign that you may need to do so is the "foreign key constraint failed" exception thrown by the commit() function after the call to schema_catalog::create_schema()). For more information, refer to Section 12.5.3, "Foreign Key Constraints" in the ODB manual. * New function, database::erase_query(), allows the deletion of the database state of multiple objects matching certain criteria. It uses the same query expression as the database::query() function. For more information, refer to Section 3.10, "Deleting Persistent Objects" in the ODB manual. * Support for value wrappers. An ODB value wrapper is a class template that wraps a value type. Common examples of wrappers are smart pointers, holders, and "optional value" containers such as boost::optional. A wrapper can be transparent or it can handle the NULL semantics. To allow the easy conversion of value types that do not support the NULL semantics into the ones that do, the odb::nullable class template has been added. ODB also now includes built-in support for std::auto_ptr and std::tr1::shared_ptr smart pointers as value wrappers as well as for boost::shared_ptr and QSharedPointer via the Boost and Qt profiles. For more information, refer to Section 7.3, "NULL Value Semantics" in the ODB manual. * Support for the boost::optional container in the Boost profile. A data member of the boost::optional type is mapped to a column that can have a NULL value. For more information, refer to Section 15.3 "Optional Library" in the ODB manual. * Support for mapping std::vector to the BLOB (or equivalent) types. For more information, refer to chapters 11 (for MySQL), 12 (for SQLite) and 13 (for PostgreSQL) in the ODB manual. * New option, --table-prefix, allows the specification of a prefix that is added to table and index names. For more information, refer to the ODB compiler command line interface documentation (man pages). * New ODB runtime interface, odb::connection, represents a connection to the database. The primary use case for a connection is to execute native statements outside of a transaction. For more information, refer to Section 3.5, "Connections" in the ODB manual. This pre-release (as well as all the future pre-releases) is available from: http://www.codesynthesis.com/download/odb/pre-release/ The ODB compiler binaries are only available for Windows and GNU/Linux (x86 and x86_64). Testing and feedback are appreciated. Enjoys, Boris From n.albeza at gmail.com Mon Aug 22 12:11:49 2011 From: n.albeza at gmail.com (Nicolas ALBEZA) Date: Mon Aug 22 12:11:59 2011 Subject: [odb-users] Many to many relationships - Insertion and deletion In-Reply-To: References: Message-ID: Thanks a lot for your answer ! Regards, 2011/8/22 Boris Kolpackov > Hi Nicolas, > > Nicolas ALBEZA writes: > > > I'm currently using ODB's many-to-many relationships in my projects, and > i > > was wondering how to insert and delete entires efficiently. > > > > My classes look like (most of it omitted for clarity): > > > > class Project > > { > > #pragma db value_not_null unordered > > list > members; > > } > > > > class Account > > { > > #pragma db value_not_null inverse(members) > > list > projects; > > } > > > > Currently, to add an Account to a Project, i'm doing something along the > > lines of : > > > > shared_ptr account = db->find(...); > > shared_ptr project = db->find(...); > > You don't really need to load the Account object (unless you need it > later). Instead, you can create an "unloaded" lazy pointer: > > lazy_shared_ptr account (*db, account_id); > > The 'inverse' example uses this technique. > > > > project->members.push_back(account); > > db->update(project); > > > > Unfortunately, when looking at MySQL's query log, i can see the following > > queries being executed : > > > > - A full update of the project entry > > - Deletion of entries in the junction table > > - And finally, insertion of an entry in the junction table > > > > The two first steps seem unnecessary, so i was wondering if there was a > > better approach to do this. > > Unfortunately, I am afraid this is as efficient as it can get right > now. We still need to work on the state change detection and more > optimal container handling. > > If you had a one-to-many relationship, then making the 'many' side > inverse (and thus getting rid of the container table) would have > been a viable optimization. > > Boris > -- ALBEZA "Pause" Nicolas From n.albeza at gmail.com Tue Aug 23 10:48:32 2011 From: n.albeza at gmail.com (Nicolas ALBEZA) Date: Tue Aug 23 10:48:40 2011 Subject: [odb-users] Simultaneous transactions with two databases Message-ID: Hello odb-users ! In the application i'm currently writing, i need to access two databases at the same time, in such a way that DB2 is accessed while DB1's transaction is still "active". Is there a way to do that without triggering the "transaction_already_in_progress" exception ? I think that spawning a thread would do the trick, but i'd like to know if there is less expensive solutions available. Thanks ! Regards, -- ALBEZA "Pause" Nicolas From boris at codesynthesis.com Wed Aug 24 03:59:57 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Wed Aug 24 04:02:30 2011 Subject: [odb-users] Simultaneous transactions with two databases In-Reply-To: References: Message-ID: Hi Nicolas, Nicolas ALBEZA writes: > In the application i'm currently writing, i need to access two databases at > the same time, in such a way that DB2 is accessed while DB1's transaction is > still "active". > > Is there a way to do that without triggering the > "transaction_already_in_progress" exception ? > > I think that spawning a thread would do the trick, but i'd like to know if > there is less expensive solutions available. Yes, creating a separate thread is the only option right now, and I agree, it is not a very good one. The other day I actually thought that sooner or later someone will want to multiplex several transactions in the same thread and that we should probably think about a way to support this. It happened sooner than I expected ;-). Here how I see this could work: transaction t1 (db1->begin (), false); // false for "don't make it current" transaction t2 (db2->begin (), false); transaction::current (t1); db1->load (...); transaction::current (t2); db2->load (...); transaction::current (t1); db1->update (...); t1.commit (); transaction::current (t2); db2->update (...); t2.commit (); Would something like this help in your case? Boris From n.albeza at gmail.com Wed Aug 24 04:43:16 2011 From: n.albeza at gmail.com (Nicolas ALBEZA) Date: Wed Aug 24 04:43:25 2011 Subject: [odb-users] Simultaneous transactions with two databases In-Reply-To: References: Message-ID: This would solve my problem, and a lot better than spawning a thread. Will this be implemented soon ? Thanks ! Regards, 2011/8/24 Boris Kolpackov > Hi Nicolas, > > Nicolas ALBEZA writes: > > > In the application i'm currently writing, i need to access two databases > at > > the same time, in such a way that DB2 is accessed while DB1's transaction > is > > still "active". > > > > Is there a way to do that without triggering the > > "transaction_already_in_progress" exception ? > > > > I think that spawning a thread would do the trick, but i'd like to know > if > > there is less expensive solutions available. > > Yes, creating a separate thread is the only option right now, and I > agree, it is not a very good one. > > The other day I actually thought that sooner or later someone will want > to multiplex several transactions in the same thread and that we should > probably think about a way to support this. It happened sooner than I > expected ;-). > > Here how I see this could work: > > transaction t1 (db1->begin (), false); // false for "don't make it current" > transaction t2 (db2->begin (), false); > > transaction::current (t1); > > db1->load (...); > > transaction::current (t2); > > db2->load (...); > > transaction::current (t1); > > db1->update (...); > t1.commit (); > > transaction::current (t2); > > db2->update (...); > t2.commit (); > > Would something like this help in your case? > > Boris > -- ALBEZA "Pause" Nicolas From boris at codesynthesis.com Wed Aug 24 07:47:39 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Wed Aug 24 07:50:11 2011 Subject: [odb-users] Simultaneous transactions with two databases In-Reply-To: References: Message-ID: Hi Nicolas, Nicolas ALBEZA writes: > Will this be implemented soon ? It is in the master. Patching 1.5.0 might require some effort, but the changes should apply cleanly to 1.6.0.a1. You will need to patch libodb: http://scm.codesynthesis.com/?p=odb/libodb.git;a=commit;h=f5d79a0cd5dc12a430d17bbdca7ec5aacb45996c And libodb-mysql: http://scm.codesynthesis.com/?p=odb/libodb-mysql.git;a=commit;h=ce69b47672cab339994828e0ff5e28b058a517f0 The ODB compiler is unchanged. Let me know if you run into any problems. Boris From thomas.szumowski at lmco.com Wed Aug 24 12:22:43 2011 From: thomas.szumowski at lmco.com (Szumowski, Thomas) Date: Wed Aug 24 16:22:14 2011 Subject: [odb-users] Deleting members from child tables in a one-one relationship Message-ID: <50FEB91CC4FBAB4881226E0EC04AC340941742F2@HVXMSP9.us.lmco.com> I had a question about the erase feature in ODB. Using the "relationships" example to start, I added a few lines after the first commit that erases the employer "Simple Tech Ltd". See the attached file (remove .allow and unpack). I understand the relationship with John/Jane and Simple Tech as a one-to-one with employee referencing employer. In terms described at http://www.sqlite.org/foreignkeys.html, this makes the employee the "child table" and the employer the "parent table". So I am essentially deleting a member of the parent table. In the above link, there is much discussion on the various behaviors one can define upon an attempt to delete a member of the parent table (see section 4.3). I have a few questions about ODB's expected behavior when deleting a member of a parent table (e.g. "employer"). 1. The SQL equivalent of the one-to-one relationship defined in the manual seems to match the relationship between tables TRACK and ARTIST in section 1 of the above link. In that section, a call of "DELETE FROM artist WHERE artistname = 'Frank Sinatra'" results in the error "SQL error: foreign key constraint failed". When I run the attached code, it runs without error. Does ODB do handling in the background to manage potential errors like the one listed? 2. The resulting database after running the attached code has John and Jane remaining, but Simple Tech Ltd deleted. In the employee table, Simple Tech is still listed as the employer. What would happen employer were to have more fields, and we later wished to load John. Here we now have an invalid foreign key since the employer was deleted. The link above has means of managing those events in section 4.3. For example, "REFERENCES XYZ ON DELETE SET NULL" Would set the employer field in John and Jane to NULL. Is there a way to define this type of behavior in ODB? -Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: driver.zip.allow Type: application/octet-stream Size: 1388 bytes Desc: driver.zip.allow Url : http://codesynthesis.com/pipermail/odb-users/attachments/20110824/94a866a0/driver.zip.obj From boris at codesynthesis.com Wed Aug 24 16:44:43 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Wed Aug 24 16:47:17 2011 Subject: [odb-users] Deleting members from child tables in a one-one relationship In-Reply-To: <50FEB91CC4FBAB4881226E0EC04AC340941742F2@HVXMSP9.us.lmco.com> References: <50FEB91CC4FBAB4881226E0EC04AC340941742F2@HVXMSP9.us.lmco.com> Message-ID: Hi Thomas, Szumowski, Thomas writes: > 1. The SQL equivalent of the one-to-one relationship defined in the manual > seems to match the relationship between tables TRACK and ARTIST in > section 1 of the above link. In that section, a call of "DELETE FROM > artist WHERE artistname = 'Frank Sinatra'" results in the error "SQL > error: foreign key constraint failed". > > When I run the attached code, it runs without error. Does ODB do > handling in the background to manage potential errors like the one > listed? Up to and including version 1.5.0, ODB did not enable foreign key constraint checking in SQLite (SQLite keeps it disabled by default). So in these versions such constraint violations were simply ignored. For the upcoming 1.6.0 release (and in the 1.6.0.a1 pre-release that I mentioned to Eric), we now by default enable foreign keys in SQLite. We also make foreign keys corresponding to object relationships deferred (INITIALLY DEFERRED; see Section 4.2 in the SQLite foreign keys page) which means they are checked at the end of the transaction. So with version 1.6.0.a1 and later, in this situation you would get a "foreign key constraint failed" error on commit. > 2. The resulting database after running the attached code has John and Jane > remaining, but Simple Tech Ltd deleted. In the employee table, Simple > Tech is still listed as the employer. What would happen employer were to > have more fields, and we later wished to load John. Here we now have an > invalid foreign key since the employer was deleted. The link above has > means of managing those events in section 4.3. For example, "REFERENCES > XYZ ON DELETE SET NULL" Would set the employer field in John and Jane to > NULL. > > Is there a way to define this type of behavior in ODB? I see how ON DELETE SET NULL or ON DELETE CASCADE can be useful. However, there is currently no way to specify this in the ODB pragma language. The only way would be to either modify the generated schema or use something like ALTER TABLE to add the ON DELETE clause. There are also potential issues with using ON DELETE. If you had one of the employers corresponding to the deleted Simple Tech Ltd loaded into the application's memory, there would be no way to synchronize its state with the ON DELETE mechanism. If you were to later call update() with such an object, you would effectively restore an invalid key. So, in this light, perhaps making sure that object references are consistent (e.g., first deleting all the employees before deleting the employer) and getting an error if they aren't is the best approach. Boris From spiritonly at gmail.com Fri Aug 26 03:39:55 2011 From: spiritonly at gmail.com (=?UTF-8?B?5p2o5rGf6aqF?=) Date: Fri Aug 26 07:43:06 2011 Subject: [odb-users] how to persist utf8 string to database? Message-ID: Hi: I have a mysql with utf-8 charset, and when i persist an object i have convert my string to std::string with utf8 encoding. But the string in database are illegible characters. So i think odb has do something during serialization. ---------------------------------------------------------------------- gtalk: spiritonly@gmail.com msn: spiritonly@live.cn blog: http://blog.csdn.net/spirit_only From boris at codesynthesis.com Fri Aug 26 07:48:44 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Fri Aug 26 07:51:16 2011 Subject: [odb-users] how to persist utf8 string to database? In-Reply-To: References: Message-ID: Hi, spiritonly@gmail.com writes: > I have a mysql with utf-8 charset, and when i persist an object i have > convert my string to std::string with utf8 encoding. But the string in > database are illegible characters. This is probably because the default client character set for a MySQL connection is latin1. There is no easy way to change that in ODB 1.5.0 but I have added the charset argument to the odb::mysql::database class constructors for the next release. I also checked and the patch applies cleanly to libodb-mysql-1.5.0: http://scm.codesynthesis.com/?p=odb/libodb-mysql.git;a=commit;h=4ea19dd03241a940a4194ac3bdea89bf7cca8f42 So you can give it a try. Here is the corresponding paragraph from the updated ODB manual: "The charset argument allows us to specify the client character set, that is, the character set in which the application will encode its text data. Note that this can be different from the MySQL server character set. If this argument is not specified or is empty, then the default MySQL client character set is used, normally latin1. Commonly used values for this argument are latin1 (equivalent to Windows cp1252 and similar to ISO-8859-1) and utf8. For other possible values as well as more information on character set support in MySQL, refer to the MySQL documentation." Boris From spiritonly at gmail.com Fri Aug 26 03:42:13 2011 From: spiritonly at gmail.com (=?UTF-8?B?5p2o5rGf6aqF?=) Date: Fri Aug 26 13:58:38 2011 Subject: [odb-users] how to see the sql executing? Message-ID: Hi: I want to see the sql executing like hibernate, how can I set configuration ? ?? ?? ---------------------------------------------------------------------- gtalk: spiritonly@gmail.com msn: spiritonly@live.cn blog: http://blog.csdn.net/spirit_only From boris at codesynthesis.com Fri Aug 26 14:07:13 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Fri Aug 26 14:09:44 2011 Subject: [odb-users] how to see the sql executing? In-Reply-To: References: Message-ID: Hi, spiritonly@gmail.com writes: > I want to see the sql executing like hibernate ODB doesn't support this. For performance reasons we use prepared statements throughout and pass data in binary form. As a result, it will be very difficult to print anything meaningful. The best we could do is to print a statement without the data, so you would see something like INSERT INTO Foo VALUES(?, ?, ?) -- not very useful. The better way to achieve this would be to use the database server logs. Most (all?) database servers provide the ability to see the SQL statements as they are being executed. Check your database server documentation for more information on how to do this. Boris From spiritonly at gmail.com Sat Aug 27 20:31:11 2011 From: spiritonly at gmail.com (=?UTF-8?B?5p2o5rGf6aqF?=) Date: Sat Aug 27 20:31:19 2011 Subject: [odb-users] how to see the sql executing? In-Reply-To: References: Message-ID: Hi, Thank you so much! I will try to check my database log for help. ?? ?? ---------------------------------------------------------------------- gtalk: spiritonly@gmail.com msn: spiritonly@live.cn blog: http://blog.csdn.net/spirit_only On Sat, Aug 27, 2011 at 2:07 AM, Boris Kolpackov wrote: > Hi, > > spiritonly@gmail.com writes: > > > I want to see the sql executing like hibernate > > ODB doesn't support this. For performance reasons we use prepared > statements throughout and pass data in binary form. As a result, > it will be very difficult to print anything meaningful. The best > we could do is to print a statement without the data, so you > would see something like INSERT INTO Foo VALUES(?, ?, ?) -- not > very useful. > > The better way to achieve this would be to use the database server > logs. Most (all?) database servers provide the ability to see the > SQL statements as they are being executed. Check your database > server documentation for more information on how to do this. > > Boris > From boris at codesynthesis.com Sun Aug 28 08:29:10 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Sun Aug 28 08:31:43 2011 Subject: [odb-users] Re: Handling pimpl idiom in ODB In-Reply-To: <4E4D2A2C.3070607@web.de> References: <4E4BFA30.4000303@web.de> <4E4D2A2C.3070607@web.de> Message-ID: Hi Uwe, The support for composite value (and container) wrappers is in the master. I also create an example that shows how to use this feature to handle the C++ pimpl idiom: http://www.codesynthesis.com/~boris/tmp/odb/pimpl-value.tar.gz While at it, I discovered yet another limitation of this approach: if you are using queries, you will have to specify the 'impl' value type name before the data members, e.g., query::impl::age < 30 instead of query::age < 30. This is quite ugly if you are using queries and is the reason (along with other limitations I listed in my previous email) why the above example is no in the odb-examples package. I think the "recommended" way to handle the pimpl idiom in ODB will be the "virtual data members" approach. However, other than the mentioned limitations, the value type approach works fine. I am planning to create another alpha release for 1.6.0 some time soon, so you should have something packaged and ready to try by the time you are back. Boris From thomas.szumowski at lmco.com Mon Aug 29 10:36:31 2011 From: thomas.szumowski at lmco.com (Szumowski, Thomas) Date: Mon Aug 29 11:09:57 2011 Subject: [odb-users] Configure error in building ODB 1.6 prelease compiler Message-ID: <50FEB91CC4FBAB4881226E0EC04AC34094224C6B@HVXMSP9.us.lmco.com> When building the ODB v1.6 pre-release on a Linux (CentOS) machine, I get the following error when running configure: ... checking whether g++ supports plugins... no configure: error: g++ does not support plugins; reconfigure GCC with --enable-plugin Any recommendations? -Tom From thomas.szumowski at lmco.com Mon Aug 29 11:03:12 2011 From: thomas.szumowski at lmco.com (Szumowski, Thomas) Date: Mon Aug 29 11:10:20 2011 Subject: [odb-users] RE: Configure error in building ODB 1.6 prelease compiler Message-ID: <50FEB91CC4FBAB4881226E0EC04AC34094224D41@HVXMSP9.us.lmco.com> Please disregard this last post. I noticed there is a precompiled binary for odb compiler "odb-1.6.0.a1-i686-linux-gnu.tar.bz2". That worked perfectly. From: Szumowski, Thomas Sent: Monday, August 29, 2011 10:37 AM To: 'odb-users@codesynthesis.com' Subject: Configure error in building ODB 1.6 prelease compiler When building the ODB v1.6 pre-release on a Linux (CentOS) machine, I get the following error when running configure: ... checking whether g++ supports plugins... no configure: error: g++ does not support plugins; reconfigure GCC with --enable-plugin Any recommendations? -Tom From thomas.szumowski at lmco.com Mon Aug 29 11:45:16 2011 From: thomas.szumowski at lmco.com (Szumowski, Thomas) Date: Mon Aug 29 11:45:31 2011 Subject: [odb-users] Building "hello" example on linux Message-ID: <50FEB91CC4FBAB4881226E0EC04AC34094224E77@HVXMSP9.us.lmco.com> This is my first attempt at using ODB in linux vs windows. I was able to build all the examples (with sqlite as the selected database) from the top examples directory using 'make'. No errors occurred. But if I go into the "hello" directory and type make, I get the following errors. Any idea why this is occurring? I ask because I get the same error when I try to manually go through the walkthrough in the user guide. ----------------------------------------------------- make all-am make[1]: Entering directory `/home/bladeuser/temp/odb-examples-1.6.0.a1/hello' depbase=`echo driver.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\ g++ -DHAVE_CONFIG_H -I'.' -I'.' -DDATABASE_SQLITE -g -O2 -MT driver.o -MD -MP -MF $depbase.Tpo -c -o driver.o driver.cxx &&\ mv -f $depbase.Tpo $depbase.Po depbase=`echo person-odb.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\ g++ -DHAVE_CONFIG_H -I'.' -I'.' -DDATABASE_SQLITE -g -O2 -MT person-odb.o -MD -MP -MF $depbase.Tpo -c -o person-odb.o person-odb.cxx &&\ mv -f $depbase.Tpo $depbase.Po /bin/sh ../libtool --tag=CXX --mode=link g++ -g -O2 -o driver driver.o person-odb.o -lodb-sqlite -lodb -lpthread libtool: link: g++ -g -O2 -o driver driver.o person-odb.o -lodb-sqlite -lodb -lpthread /usr/local/lib/libodb-sqlite.so: undefined reference to `sqlite3_open_v2' /usr/local/lib/libodb-sqlite.so: undefined reference to `sqlite3_extended_errcode' /usr/local/lib/libodb-sqlite.so: undefined reference to `sqlite3_prepare_v2' collect2: ld returned 1 exit status make[1]: *** [driver] Error 1 ----------------------------------------------------- -Tom From thomas.szumowski at lmco.com Mon Aug 29 11:52:10 2011 From: thomas.szumowski at lmco.com (Szumowski, Thomas) Date: Mon Aug 29 11:52:23 2011 Subject: [odb-users] RE: Building "hello" example on linux Message-ID: <50FEB91CC4FBAB4881226E0EC04AC34094224EAC@HVXMSP9.us.lmco.com> Please disregard again. I asked too soon and figured it out right after. :) As a reference for others: I was running the make in the examples directory in a different console window than the one in the hello directory. The one in the hello directory didn't have the right library path. I fixed with: LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib And I made it permanent by putting the line in /home/user/.bash_profile. From: Szumowski, Thomas Sent: Monday, August 29, 2011 11:45 AM To: 'odb-users@codesynthesis.com' Subject: Building "hello" example on linux This is my first attempt at using ODB in linux vs windows. I was able to build all the examples (with sqlite as the selected database) from the top examples directory using 'make'. No errors occurred. But if I go into the "hello" directory and type make, I get the following errors. Any idea why this is occurring? I ask because I get the same error when I try to manually go through the walkthrough in the user guide. ----------------------------------------------------- make all-am make[1]: Entering directory `/home/bladeuser/temp/odb-examples-1.6.0.a1/hello' depbase=`echo driver.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\ g++ -DHAVE_CONFIG_H -I'.' -I'.' -DDATABASE_SQLITE -g -O2 -MT driver.o -MD -MP -MF $depbase.Tpo -c -o driver.o driver.cxx &&\ mv -f $depbase.Tpo $depbase.Po depbase=`echo person-odb.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\ g++ -DHAVE_CONFIG_H -I'.' -I'.' -DDATABASE_SQLITE -g -O2 -MT person-odb.o -MD -MP -MF $depbase.Tpo -c -o person-odb.o person-odb.cxx &&\ mv -f $depbase.Tpo $depbase.Po /bin/sh ../libtool --tag=CXX --mode=link g++ -g -O2 -o driver driver.o person-odb.o -lodb-sqlite -lodb -lpthread libtool: link: g++ -g -O2 -o driver driver.o person-odb.o -lodb-sqlite -lodb -lpthread /usr/local/lib/libodb-sqlite.so: undefined reference to `sqlite3_open_v2' /usr/local/lib/libodb-sqlite.so: undefined reference to `sqlite3_extended_errcode' /usr/local/lib/libodb-sqlite.so: undefined reference to `sqlite3_prepare_v2' collect2: ld returned 1 exit status make[1]: *** [driver] Error 1 ----------------------------------------------------- -Tom From thomas.szumowski at lmco.com Mon Aug 29 12:24:19 2011 From: thomas.szumowski at lmco.com (Szumowski, Thomas) Date: Mon Aug 29 12:32:07 2011 Subject: [odb-users] Linux Linking ODB - libtool vs g++ Message-ID: <50FEB91CC4FBAB4881226E0EC04AC34094224F89@HVXMSP9.us.lmco.com> I was following the example in the ODB user manual section 2.3 "Compiling and Running". I am on a linux machine. I noticed when I get to the point of running the equivalent command "c++ -o driver driver.o person-odb.o -lodb-mysql -lodb", I get an error. But when I run the make in the examples (hello), it runs libtool and I get no errors. See below for my results. First I link using libtool, as done in the makefile. That works fine and I can execute the program. But then I try the line in the user manual and it fails. Any recommendations? And should I just always use libtool to build? ----------------------------------- OUTPUT ----------------------------------- [user@localhost tmp]$ ../../libtool --tag=CXX --mode=link g++ -g -O2 -o driver driver.o person-odb.o -lodb-sqlite -lodb -lpthread libtool: link: g++ -g -O2 -o driver driver.o person-odb.o /usr/local/lib/libodb-sqlite.so /usr/local/lib/libodb.so -lpthread -Wl,-rpath -Wl,/usr/local/lib -Wl,-rpath -Wl,/usr/local/lib [user@localhost tmp]$ ls database.hxx driver driver.cxx driver.o person.hxx person-odb.cxx person-odb.hxx person-odb.ixx person-odb.o [user@localhost tmp]$ ./driver Hello, John Doe! Hello, Jane Doe! [user@localhost tmp]$ g++ -o driver driver.o person-odb.o -lodb-sqlite -lodb /usr/local/lib/libodb-sqlite.so: undefined reference to `sqlite3_open_v2' /usr/local/lib/libodb-sqlite.so: undefined reference to `sqlite3_extended_errcode' /usr/local/lib/libodb-sqlite.so: undefined reference to `sqlite3_prepare_v2' collect2: ld returned 1 exit status ----------------------------------- -Tom From thomas.szumowski at lmco.com Mon Aug 29 12:47:05 2011 From: thomas.szumowski at lmco.com (Szumowski, Thomas) Date: Mon Aug 29 12:47:18 2011 Subject: [odb-users] RE: Linux Linking ODB - libtool vs g++ In-Reply-To: <50FEB91CC4FBAB4881226E0EC04AC34094224F89@HVXMSP9.us.lmco.com> References: <50FEB91CC4FBAB4881226E0EC04AC34094224F89@HVXMSP9.us.lmco.com> Message-ID: <50FEB91CC4FBAB4881226E0EC04AC3409422502C@HVXMSP9.us.lmco.com> Looks like my third strike today. :) I noticed the main difference between the libtool and g++ calls were libtools inclusion of "-Wl,-rpath,/usr/local/lib". Adding that to g++ and naturally it works fine. So perhaps I just need to ensure I have that added in as needed? -Tom -----Original Message----- From: odb-users-bounces@codesynthesis.com [mailto:odb-users-bounces@codesynthesis.com] On Behalf Of Szumowski, Thomas Sent: Monday, August 29, 2011 12:24 PM To: odb-users@codesynthesis.com Subject: EXTERNAL: [odb-users] Linux Linking ODB - libtool vs g++ I was following the example in the ODB user manual section 2.3 "Compiling and Running". I am on a linux machine. I noticed when I get to the point of running the equivalent command "c++ -o driver driver.o person-odb.o -lodb-mysql -lodb", I get an error. But when I run the make in the examples (hello), it runs libtool and I get no errors. See below for my results. First I link using libtool, as done in the makefile. That works fine and I can execute the program. But then I try the line in the user manual and it fails. Any recommendations? And should I just always use libtool to build? ----------------------------------- OUTPUT ----------------------------------- [user@localhost tmp]$ ../../libtool --tag=CXX --mode=link g++ -g -O2 -o driver driver.o person-odb.o -lodb-sqlite -lodb -lpthread libtool: link: g++ -g -O2 -o driver driver.o person-odb.o /usr/local/lib/libodb-sqlite.so /usr/local/lib/libodb.so -lpthread -Wl,-rpath -Wl,/usr/local/lib -Wl,-rpath -Wl,/usr/local/lib [user@localhost tmp]$ ls database.hxx driver driver.cxx driver.o person.hxx person-odb.cxx person-odb.hxx person-odb.ixx person-odb.o [user@localhost tmp]$ ./driver Hello, John Doe! Hello, Jane Doe! [user@localhost tmp]$ g++ -o driver driver.o person-odb.o -lodb-sqlite -lodb /usr/local/lib/libodb-sqlite.so: undefined reference to `sqlite3_open_v2' /usr/local/lib/libodb-sqlite.so: undefined reference to `sqlite3_extended_errcode' /usr/local/lib/libodb-sqlite.so: undefined reference to `sqlite3_prepare_v2' collect2: ld returned 1 exit status ----------------------------------- -Tom From boris at codesynthesis.com Mon Aug 29 12:50:18 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Mon Aug 29 12:52:52 2011 Subject: [odb-users] Linux Linking ODB - libtool vs g++ In-Reply-To: <50FEB91CC4FBAB4881226E0EC04AC34094224F89@HVXMSP9.us.lmco.com> References: <50FEB91CC4FBAB4881226E0EC04AC34094224F89@HVXMSP9.us.lmco.com> Message-ID: Hi Thomas, Szumowski, Thomas writes: > I was following the example in the ODB user manual section 2.3 "Compiling > and Running". I am on a linux machine. I noticed when I get to the point of > running the equivalent command "c++ -o driver driver.o person-odb.o > -lodb-mysql -lodb", I get an error. But when I run the make in the examples > (hello), it runs libtool and I get no errors. See below for my > results. First I link using libtool, as done in the makefile. That works > fine and I can execute the program. But then I try the line in the user > manual and it fails. Any recommendations? Hm, this is strange. I don't get this error. It looks like libodb-sqlite.so is not linked to libsqlite3.so. Can you try this command line and see if there is an entry for libsqlite3.so in the output: ldd /usr/local/lib/libodb-sqlite.so One explanation for this behavior would be if you didn't have a shared version (.so) of libsqlite3, only static (libsqlite3.a). The output from the above command line should shed some light on this as well. Also, I assume that you have built and installed libodb-sqlite (and libodb) using something like this: $ ./configure $ make $ sudo make install Another thing that could be helpful is if you could send me your /usr/local/lib/libodb-sqlite.la so that I could compare it mine. > And should I just always use libtool to build? You can, but you definitely shouldn't have to. I can build the hello example using just the g++ command line without any problems. Boris From boris at codesynthesis.com Mon Aug 29 13:01:51 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Mon Aug 29 13:04:23 2011 Subject: [odb-users] RE: Linux Linking ODB - libtool vs g++ In-Reply-To: <50FEB91CC4FBAB4881226E0EC04AC3409422502C@HVXMSP9.us.lmco.com> References: <50FEB91CC4FBAB4881226E0EC04AC34094224F89@HVXMSP9.us.lmco.com> <50FEB91CC4FBAB4881226E0EC04AC3409422502C@HVXMSP9.us.lmco.com> Message-ID: Hi Thomas, Szumowski, Thomas writes: > I noticed the main difference between the libtool and g++ calls were > libtools inclusion of "-Wl,-rpath,/usr/local/lib". Adding that to g++ > and naturally it works fine. So perhaps I just need to ensure I have > that added in as needed? Hm, this gets stranger. Here is a quote from the GNU ld man pages that may explain why this helps: "The -rpath option is also used when locating shared objects which are needed by shared objects explicitly included in the link" So it seems like for some reason ld cannot locate libsqlite3.so (which I assume is in /usr/local/lib) even though it can resolve -lodb-sqlite and -lodb without any problems. Very strange. Can you try this: $ export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH And then run the vanilla g++ command? As well as this (without the LD_LIBRARY_PATH): $ g++ -L/usr/local/lib ... Boris From dcoffey at netharmonix.com Mon Aug 29 13:45:33 2011 From: dcoffey at netharmonix.com (Dan Coffey) Date: Mon Aug 29 13:45:40 2011 Subject: [odb-users] RE: Linux Linking ODB - libtool vs g++ In-Reply-To: References: <50FEB91CC4FBAB4881226E0EC04AC34094224F89@HVXMSP9.us.lmco.com> <50FEB91CC4FBAB4881226E0EC04AC3409422502C@HVXMSP9.us.lmco.com> Message-ID: <4E5BD03D.5010207@netharmonix.com> Here is a link that shows you how to setup Ubuntu files in /etc/ld.so.conf.d so that the libs will be found. Dan On 08/29/2011 01:01 PM, Boris Kolpackov wrote: > Hi Thomas, > > Szumowski, Thomas writes: > >> I noticed the main difference between the libtool and g++ calls were >> libtools inclusion of "-Wl,-rpath,/usr/local/lib". Adding that to g++ >> and naturally it works fine. So perhaps I just need to ensure I have >> that added in as needed? > Hm, this gets stranger. Here is a quote from the GNU ld man pages that > may explain why this helps: > > "The -rpath option is also used when locating shared objects which are > needed by shared objects explicitly included in the link" > > So it seems like for some reason ld cannot locate libsqlite3.so (which > I assume is in /usr/local/lib) even though it can resolve -lodb-sqlite > and -lodb without any problems. Very strange. > > Can you try this: > > $ export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH > > And then run the vanilla g++ command? > > As well as this (without the LD_LIBRARY_PATH): > > $ g++ -L/usr/local/lib ... > > Boris > From boris at codesynthesis.com Tue Aug 30 11:30:07 2011 From: boris at codesynthesis.com (Boris Kolpackov) Date: Tue Aug 30 11:32:43 2011 Subject: [odb-users] Linux Linking ODB - libtool vs g++ In-Reply-To: <50FEB91CC4FBAB4881226E0EC04AC34094225157@HVXMSP9.us.lmco.com> References: <50FEB91CC4FBAB4881226E0EC04AC34094224F89@HVXMSP9.us.lmco.com> <50FEB91CC4FBAB4881226E0EC04AC34094225157@HVXMSP9.us.lmco.com> Message-ID: Hi Thomas, [CC'ed odb-users in case others run into a similar issue.] Szumowski, Thomas writes: > ldd /usr/local/lib/libodb-sqlite.so > libsqlite3.so.0 => /usr/lib/libsqlite3.so.0 (0x00b83000) Ok, I think I know what's going on here. You have two versions of libsqlite3.so, one in /usr/lib and the other in /usr/local/lib. /usr/local/lib doesn't appear to be in your LD_LIBRARY_PATH and when you use the g++ command line to link the example, it resolves libsqlite3.so to /usr/lib/libsqlite3.so (just like in the ldd output above). libsqlite3.so in /usr/lib is probably quite old and that's the reason why sqlite3_open_v2 is reported unresolved. When you added -rpath /usr/local/lib to the g++ command line, that added this directory to the library search list and the correct libsqlite3.so was used. Similarly, adding /usr/local/lib to LD_LIBRARY_PATH fixes the problem. So, I would say, the recommended solution it to add /usr/local/lib to LD_LIBRARY_PATH or, better yet, as Dan suggested, add it to /etc/ld.so.conf (and don't forget to run ldconfig). Boris