first commit
This commit is contained in:
15
test/CMakeLists.txt
Normal file
15
test/CMakeLists.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
project(QxOrmAllTests LANGUAGES CXX)
|
||||
|
||||
add_subdirectory(../ ./QxOrm)
|
||||
|
||||
add_subdirectory(qxBlog)
|
||||
add_subdirectory(qxBlogCompositeKey)
|
||||
add_subdirectory(qxBlogCpp11)
|
||||
add_subdirectory(qxBlogModelView)
|
||||
add_subdirectory(qxDllSample)
|
||||
add_subdirectory(qxClientServer)
|
||||
add_subdirectory(qxBlogMongoDB)
|
||||
add_subdirectory(qxBlogPImpl)
|
||||
add_subdirectory(qxBlogRestApi)
|
||||
7
test/_bin/.gitignore
vendored
Normal file
7
test/_bin/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# git does not allow empty directories.
|
||||
# Yet, we need to add this empty directory on git.
|
||||
# To achieve that, we created this .gitignore file, so that the directory will not be empty thus enabling us to commit it.
|
||||
# Since we want all generated files/folders in this directory to be ignored by git, we add a rule for this.
|
||||
*
|
||||
# And then add an exception for this specifc file (so that we can commit it).
|
||||
!.gitignore
|
||||
56
test/qxBlog/CMakeLists.txt
Normal file
56
test/qxBlog/CMakeLists.txt
Normal file
@@ -0,0 +1,56 @@
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
project(qxBlog LANGUAGES CXX)
|
||||
|
||||
include(../../QxOrm.cmake)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
set(CMAKE_DEBUG_POSTFIX "d")
|
||||
|
||||
set(HEADERS
|
||||
./include/precompiled.h
|
||||
./include/export.h
|
||||
./include/author.h
|
||||
./include/blog.h
|
||||
./include/category.h
|
||||
./include/comment.h
|
||||
)
|
||||
|
||||
set(SRCS
|
||||
./src/author.cpp
|
||||
./src/blog.cpp
|
||||
./src/category.cpp
|
||||
./src/comment.cpp
|
||||
./src/main.cpp
|
||||
)
|
||||
|
||||
add_executable(qxBlog ${SRCS} ${HEADERS})
|
||||
|
||||
target_compile_definitions(qxBlog PRIVATE -D_BUILDING_QX_BLOG)
|
||||
|
||||
if(COMMAND target_precompile_headers)
|
||||
target_precompile_headers(qxBlog PRIVATE ./include/precompiled.h)
|
||||
endif() # (COMMAND target_precompile_headers)
|
||||
|
||||
target_link_libraries(qxBlog ${QX_LIBRARIES} QxOrm)
|
||||
|
||||
set_target_properties(qxBlog PROPERTIES
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
ARCHIVE_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
)
|
||||
|
||||
set_target_properties(qxBlog PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
|
||||
7
test/qxBlog/debug/.gitignore
vendored
Normal file
7
test/qxBlog/debug/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# git does not allow empty directories.
|
||||
# Yet, we need to add this empty directory on git.
|
||||
# To achieve that, we created this .gitignore file, so that the directory will not be empty thus enabling us to commit it.
|
||||
# Since we want all generated files/folders in this directory to be ignored by git, we add a rule for this.
|
||||
*
|
||||
# And then add an exception for this specifc file (so that we can commit it).
|
||||
!.gitignore
|
||||
33
test/qxBlog/include/author.h
Normal file
33
test/qxBlog/include/author.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef _QX_BLOG_AUTHOR_H_
|
||||
#define _QX_BLOG_AUTHOR_H_
|
||||
|
||||
class blog;
|
||||
|
||||
class QX_BLOG_DLL_EXPORT author
|
||||
{
|
||||
public:
|
||||
// -- typedef
|
||||
typedef std::shared_ptr<blog> blog_ptr;
|
||||
typedef std::vector<blog_ptr> list_blog;
|
||||
// -- enum
|
||||
enum enum_sex { male, female, unknown };
|
||||
// -- properties
|
||||
QString m_id;
|
||||
QString m_name;
|
||||
QDate m_birthdate;
|
||||
enum_sex m_sex;
|
||||
list_blog m_blogX;
|
||||
// -- contructor, virtual destructor
|
||||
author() : m_id("0"), m_sex(unknown) { ; }
|
||||
virtual ~author() { ; }
|
||||
// -- methods
|
||||
int age() const;
|
||||
};
|
||||
|
||||
QX_REGISTER_PRIMARY_KEY(author, QString)
|
||||
QX_REGISTER_HPP_QX_BLOG(author, qx::trait::no_base_class_defined, 0)
|
||||
|
||||
typedef std::shared_ptr<author> author_ptr;
|
||||
typedef qx::QxCollection<QString, author_ptr> list_author;
|
||||
|
||||
#endif // _QX_BLOG_AUTHOR_H_
|
||||
28
test/qxBlog/include/blog.h
Normal file
28
test/qxBlog/include/blog.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef _QX_BLOG_BLOG_H_
|
||||
#define _QX_BLOG_BLOG_H_
|
||||
|
||||
#include "author.h"
|
||||
#include "comment.h"
|
||||
#include "category.h"
|
||||
|
||||
class QX_BLOG_DLL_EXPORT blog
|
||||
{
|
||||
public:
|
||||
// -- properties
|
||||
long m_id;
|
||||
QString m_text;
|
||||
QDateTime m_dt_creation;
|
||||
author_ptr m_author;
|
||||
list_comment m_commentX;
|
||||
list_category m_categoryX;
|
||||
// -- contructor, virtual destructor
|
||||
blog() : m_id(0) { ; }
|
||||
virtual ~blog() { ; }
|
||||
};
|
||||
|
||||
QX_REGISTER_HPP_QX_BLOG(blog, qx::trait::no_base_class_defined, 0)
|
||||
|
||||
typedef std::shared_ptr<blog> blog_ptr;
|
||||
typedef std::vector<blog_ptr> list_blog;
|
||||
|
||||
#endif // _QX_BLOG_BLOG_H_
|
||||
27
test/qxBlog/include/category.h
Normal file
27
test/qxBlog/include/category.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef _QX_BLOG_CATEGORY_H_
|
||||
#define _QX_BLOG_CATEGORY_H_
|
||||
|
||||
class blog;
|
||||
|
||||
class QX_BLOG_DLL_EXPORT category
|
||||
{
|
||||
public:
|
||||
// -- typedef
|
||||
typedef std::shared_ptr<blog> blog_ptr;
|
||||
typedef qx::QxCollection<long, blog_ptr> list_blog;
|
||||
// -- properties
|
||||
long m_id;
|
||||
QString m_name;
|
||||
QString m_desc;
|
||||
list_blog m_blogX;
|
||||
// -- contructor, virtual destructor
|
||||
category() : m_id(0) { ; }
|
||||
virtual ~category() { ; }
|
||||
};
|
||||
|
||||
QX_REGISTER_HPP_QX_BLOG(category, qx::trait::no_base_class_defined, 0)
|
||||
|
||||
typedef QSharedPointer<category> category_ptr;
|
||||
typedef qx::QxCollection<long, category_ptr> list_category;
|
||||
|
||||
#endif // _QX_BLOG_CATEGORY_H_
|
||||
26
test/qxBlog/include/comment.h
Normal file
26
test/qxBlog/include/comment.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef _QX_BLOG_COMMENT_H_
|
||||
#define _QX_BLOG_COMMENT_H_
|
||||
|
||||
class blog;
|
||||
|
||||
class QX_BLOG_DLL_EXPORT comment
|
||||
{
|
||||
public:
|
||||
// -- typedef
|
||||
typedef std::shared_ptr<blog> blog_ptr;
|
||||
// -- properties
|
||||
long m_id;
|
||||
QString m_text;
|
||||
QDateTime m_dt_create;
|
||||
blog_ptr m_blog;
|
||||
// -- contructor, virtual destructor
|
||||
comment() : m_id(0) { ; }
|
||||
virtual ~comment() { ; }
|
||||
};
|
||||
|
||||
QX_REGISTER_HPP_QX_BLOG(comment, qx::trait::no_base_class_defined, 0)
|
||||
|
||||
typedef std::shared_ptr<comment> comment_ptr;
|
||||
typedef QList<comment_ptr> list_comment;
|
||||
|
||||
#endif // _QX_BLOG_COMMENT_H_
|
||||
18
test/qxBlog/include/export.h
Normal file
18
test/qxBlog/include/export.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef _QX_BLOG_EXPORT_H_
|
||||
#define _QX_BLOG_EXPORT_H_
|
||||
|
||||
#ifdef _BUILDING_QX_BLOG
|
||||
#define QX_BLOG_DLL_EXPORT QX_DLL_EXPORT_HELPER
|
||||
#else // _BUILDING_QX_BLOG
|
||||
#define QX_BLOG_DLL_EXPORT QX_DLL_IMPORT_HELPER
|
||||
#endif // _BUILDING_QX_BLOG
|
||||
|
||||
#ifdef _BUILDING_QX_BLOG
|
||||
#define QX_REGISTER_HPP_QX_BLOG QX_REGISTER_HPP_EXPORT_DLL
|
||||
#define QX_REGISTER_CPP_QX_BLOG QX_REGISTER_CPP_EXPORT_DLL
|
||||
#else // _BUILDING_QX_BLOG
|
||||
#define QX_REGISTER_HPP_QX_BLOG QX_REGISTER_HPP_IMPORT_DLL
|
||||
#define QX_REGISTER_CPP_QX_BLOG QX_REGISTER_CPP_IMPORT_DLL
|
||||
#endif // _BUILDING_QX_BLOG
|
||||
|
||||
#endif // _QX_BLOG_EXPORT_H_
|
||||
8
test/qxBlog/include/precompiled.h
Normal file
8
test/qxBlog/include/precompiled.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef _QX_BLOG_PRECOMPILED_HEADER_H_
|
||||
#define _QX_BLOG_PRECOMPILED_HEADER_H_
|
||||
|
||||
#include <QxOrm.h>
|
||||
|
||||
#include "export.h"
|
||||
|
||||
#endif // _QX_BLOG_PRECOMPILED_HEADER_H_
|
||||
7
test/qxBlog/qt/moc/.gitignore
vendored
Normal file
7
test/qxBlog/qt/moc/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# git does not allow empty directories.
|
||||
# Yet, we need to add this empty directory on git.
|
||||
# To achieve that, we created this .gitignore file, so that the directory will not be empty thus enabling us to commit it.
|
||||
# Since we want all generated files/folders in this directory to be ignored by git, we add a rule for this.
|
||||
*
|
||||
# And then add an exception for this specifc file (so that we can commit it).
|
||||
!.gitignore
|
||||
34
test/qxBlog/qxBlog.pro
Normal file
34
test/qxBlog/qxBlog.pro
Normal file
@@ -0,0 +1,34 @@
|
||||
include(../../QxOrm.pri)
|
||||
|
||||
TEMPLATE = app
|
||||
DEFINES += _BUILDING_QX_BLOG
|
||||
INCLUDEPATH += ../../../QxOrm/include/
|
||||
DESTDIR = ../../../QxOrm/test/_bin/
|
||||
LIBS += -L"../../../QxOrm/lib"
|
||||
|
||||
!contains(DEFINES, _QX_NO_PRECOMPILED_HEADER) {
|
||||
PRECOMPILED_HEADER = ./include/precompiled.h
|
||||
} # !contains(DEFINES, _QX_NO_PRECOMPILED_HEADER)
|
||||
|
||||
macx:CONFIG-=app_bundle
|
||||
|
||||
CONFIG(debug, debug|release) {
|
||||
TARGET = qxBlogd
|
||||
LIBS += -l"QxOrmd"
|
||||
} else {
|
||||
TARGET = qxBlog
|
||||
LIBS += -l"QxOrm"
|
||||
} # CONFIG(debug, debug|release)
|
||||
|
||||
HEADERS += ./include/precompiled.h
|
||||
HEADERS += ./include/export.h
|
||||
HEADERS += ./include/author.h
|
||||
HEADERS += ./include/blog.h
|
||||
HEADERS += ./include/category.h
|
||||
HEADERS += ./include/comment.h
|
||||
|
||||
SOURCES += ./src/author.cpp
|
||||
SOURCES += ./src/blog.cpp
|
||||
SOURCES += ./src/category.cpp
|
||||
SOURCES += ./src/comment.cpp
|
||||
SOURCES += ./src/main.cpp
|
||||
7
test/qxBlog/release/.gitignore
vendored
Normal file
7
test/qxBlog/release/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# git does not allow empty directories.
|
||||
# Yet, we need to add this empty directory on git.
|
||||
# To achieve that, we created this .gitignore file, so that the directory will not be empty thus enabling us to commit it.
|
||||
# Since we want all generated files/folders in this directory to be ignored by git, we add a rule for this.
|
||||
*
|
||||
# And then add an exception for this specifc file (so that we can commit it).
|
||||
!.gitignore
|
||||
28
test/qxBlog/src/author.cpp
Normal file
28
test/qxBlog/src/author.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#include "../include/precompiled.h"
|
||||
|
||||
#include "../include/author.h"
|
||||
#include "../include/blog.h"
|
||||
|
||||
#include <QxOrm_Impl.h>
|
||||
|
||||
QX_REGISTER_CPP_QX_BLOG(author)
|
||||
|
||||
namespace qx {
|
||||
template <> void register_class(QxClass<author> & t)
|
||||
{
|
||||
t.id(& author::m_id, "author_id");
|
||||
|
||||
t.data(& author::m_name, "name");
|
||||
t.data(& author::m_birthdate, "birthdate");
|
||||
t.data(& author::m_sex, "sex");
|
||||
|
||||
t.relationOneToMany(& author::m_blogX, "list_blog", "author_id");
|
||||
|
||||
t.fct_0<int>(std::mem_fn(& author::age), "age"); // using std::mem_fn() here is just a workaround for an issue with some versions of MSVC, it is not required with a full compliant C++11 compiler (http://stackoverflow.com/questions/23778883/vs2013-stdfunction-with-member-function)
|
||||
}}
|
||||
|
||||
int author::age() const
|
||||
{
|
||||
if (! m_birthdate.isValid()) { return -1; }
|
||||
return (QDate::currentDate().year() - m_birthdate.year());
|
||||
}
|
||||
20
test/qxBlog/src/blog.cpp
Normal file
20
test/qxBlog/src/blog.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "../include/precompiled.h"
|
||||
|
||||
#include "../include/blog.h"
|
||||
|
||||
#include <QxOrm_Impl.h>
|
||||
|
||||
QX_REGISTER_CPP_QX_BLOG(blog)
|
||||
|
||||
namespace qx {
|
||||
template <> void register_class(QxClass<blog> & t)
|
||||
{
|
||||
t.id(& blog::m_id, "blog_id");
|
||||
|
||||
t.data(& blog::m_text, "blog_text");
|
||||
t.data(& blog::m_dt_creation, "date_creation");
|
||||
|
||||
t.relationManyToOne(& blog::m_author, "author_id");
|
||||
t.relationOneToMany(& blog::m_commentX, "list_comment", "blog_id");
|
||||
t.relationManyToMany(& blog::m_categoryX, "list_category", "category_blog", "blog_id", "category_id");
|
||||
}}
|
||||
19
test/qxBlog/src/category.cpp
Normal file
19
test/qxBlog/src/category.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "../include/precompiled.h"
|
||||
|
||||
#include "../include/category.h"
|
||||
#include "../include/blog.h"
|
||||
|
||||
#include <QxOrm_Impl.h>
|
||||
|
||||
QX_REGISTER_CPP_QX_BLOG(category)
|
||||
|
||||
namespace qx {
|
||||
template <> void register_class(QxClass<category> & t)
|
||||
{
|
||||
t.id(& category::m_id, "category_id");
|
||||
|
||||
t.data(& category::m_name, "name");
|
||||
t.data(& category::m_desc, "description");
|
||||
|
||||
t.relationManyToMany(& category::m_blogX, "list_blog", "category_blog", "category_id", "blog_id");
|
||||
}}
|
||||
19
test/qxBlog/src/comment.cpp
Normal file
19
test/qxBlog/src/comment.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "../include/precompiled.h"
|
||||
|
||||
#include "../include/comment.h"
|
||||
#include "../include/blog.h"
|
||||
|
||||
#include <QxOrm_Impl.h>
|
||||
|
||||
QX_REGISTER_CPP_QX_BLOG(comment)
|
||||
|
||||
namespace qx {
|
||||
template <> void register_class(QxClass<comment> & t)
|
||||
{
|
||||
t.id(& comment::m_id, "comment_id");
|
||||
|
||||
t.data(& comment::m_text, "comment_text");
|
||||
t.data(& comment::m_dt_create, "date_creation");
|
||||
|
||||
t.relationManyToOne(& comment::m_blog, "blog_id");
|
||||
}}
|
||||
425
test/qxBlog/src/main.cpp
Normal file
425
test/qxBlog/src/main.cpp
Normal file
@@ -0,0 +1,425 @@
|
||||
#include "../include/precompiled.h"
|
||||
|
||||
#include <QtCore/qcoreapplication.h>
|
||||
|
||||
#include "../include/blog.h"
|
||||
#include "../include/author.h"
|
||||
#include "../include/comment.h"
|
||||
#include "../include/category.h"
|
||||
|
||||
#include <QxOrm_Impl.h>
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
// Qt application
|
||||
QCoreApplication app(argc, argv);
|
||||
QFile::remove("./qxBlog.sqlite");
|
||||
|
||||
// Parameters to connect to database
|
||||
qx::QxSqlDatabase::getSingleton()->setDriverName("QSQLITE");
|
||||
qx::QxSqlDatabase::getSingleton()->setDatabaseName("./qxBlog.sqlite");
|
||||
qx::QxSqlDatabase::getSingleton()->setHostName("localhost");
|
||||
qx::QxSqlDatabase::getSingleton()->setUserName("root");
|
||||
qx::QxSqlDatabase::getSingleton()->setPassword("");
|
||||
qx::QxSqlDatabase::getSingleton()->setFormatSqlQueryBeforeLogging(true);
|
||||
qx::QxSqlDatabase::getSingleton()->setDisplayTimerDetails(true);
|
||||
|
||||
// Only for debug purpose : assert if invalid offset detected fetching a relation
|
||||
qx::QxSqlDatabase::getSingleton()->setVerifyOffsetRelation(true);
|
||||
|
||||
// Create all tables in database
|
||||
QSqlError daoError = qx::dao::create_table<author>();
|
||||
daoError = qx::dao::create_table<comment>();
|
||||
daoError = qx::dao::create_table<category>();
|
||||
daoError = qx::dao::create_table<blog>();
|
||||
|
||||
// Create a list of 3 author
|
||||
author_ptr author_1; author_1.reset(new author());
|
||||
author_ptr author_2; author_2.reset(new author());
|
||||
author_ptr author_3; author_3.reset(new author());
|
||||
|
||||
author_1->m_id = "author_id_1"; author_1->m_name = "author_1";
|
||||
author_1->m_sex = author::male; author_1->m_birthdate = QDate::currentDate();
|
||||
author_2->m_id = "author_id_2"; author_2->m_name = "author_2";
|
||||
author_2->m_sex = author::female; author_2->m_birthdate = QDate::currentDate();
|
||||
author_3->m_id = "author_id_3"; author_3->m_name = "author_3";
|
||||
author_3->m_sex = author::female; author_3->m_birthdate = QDate::currentDate();
|
||||
|
||||
list_author authorX;
|
||||
authorX.insert(author_1->m_id, author_1);
|
||||
authorX.insert(author_2->m_id, author_2);
|
||||
authorX.insert(author_3->m_id, author_3);
|
||||
|
||||
// Insert list of 3 author into database
|
||||
daoError = qx::dao::insert(authorX);
|
||||
qAssert(qx::dao::count<author>() == 3);
|
||||
|
||||
// Delete all authors in database and try to insert them using exec batch method
|
||||
daoError = qx::dao::delete_all<author>(); qAssert(! daoError.isValid());
|
||||
qAssert(qx::dao::count<author>() == 0);
|
||||
daoError = qx::dao::insert(authorX, NULL, true); qAssert(! daoError.isValid());
|
||||
qAssert(qx::dao::count<author>() == 3);
|
||||
|
||||
// Clone author 2 : 'author_id_2'
|
||||
author_ptr author_clone = qx::clone(* author_2);
|
||||
qAssert(author_clone->m_id == "author_id_2");
|
||||
qAssert(author_clone->m_sex == author::female);
|
||||
|
||||
// Create a query to fetch only female author : 'author_id_2' and 'author_id_3'
|
||||
qx::QxSqlQuery query("WHERE author.sex = :sex");
|
||||
query.bind(":sex", author::female);
|
||||
|
||||
list_author list_of_female_author;
|
||||
daoError = qx::dao::fetch_by_query(query, list_of_female_author);
|
||||
qAssert(list_of_female_author.count() == 2);
|
||||
|
||||
// Dump list of female author (xml serialization)
|
||||
qx::dump(list_of_female_author, false);
|
||||
qx::dump(list_of_female_author, true);
|
||||
|
||||
// Test qx::QxSqlQuery::freeText() with/without placeholders
|
||||
query = qx_query(); query.freeText("WHERE author.sex = " + QString::number(static_cast<int>(author::female)));
|
||||
daoError = qx::dao::fetch_by_query(query, list_of_female_author);
|
||||
qAssert(list_of_female_author.count() == 2);
|
||||
query = qx_query(); query.freeText("WHERE author.sex = :sex", QVariantList() << author::female);
|
||||
daoError = qx::dao::fetch_by_query(query, list_of_female_author);
|
||||
qAssert(list_of_female_author.count() == 2);
|
||||
query = qx_query(); query.freeText("WHERE author.sex=:sex AND author.author_id=:author_id", QVariantList() << author::female << "author_id_2");
|
||||
daoError = qx::dao::fetch_by_query(query, list_of_female_author);
|
||||
qAssert(list_of_female_author.count() == 1);
|
||||
query = qx_query(); query.freeText("WHERE (author.sex = :sex) AND (author.author_id = :author_id)", QVariantList() << author::female << "author_id_2");
|
||||
daoError = qx::dao::fetch_by_query(query, list_of_female_author);
|
||||
qAssert(list_of_female_author.count() == 1);
|
||||
|
||||
// Create 3 categories
|
||||
category_ptr category_1 = category_ptr(new category());
|
||||
category_ptr category_2 = category_ptr(new category());
|
||||
category_ptr category_3 = category_ptr(new category());
|
||||
|
||||
category_1->m_name = "category_1"; category_1->m_desc = "desc_1";
|
||||
category_2->m_name = "category_2"; category_2->m_desc = "desc_2";
|
||||
category_3->m_name = "category_3"; category_3->m_desc = "desc_3";
|
||||
|
||||
{ // Create a scope to destroy temporary connexion to database
|
||||
|
||||
// Open a transaction to database
|
||||
QSqlDatabase db = qx::QxSqlDatabase::getDatabase();
|
||||
bool bCommit = db.transaction();
|
||||
|
||||
// Insert 3 categories into database, use 'db' parameter for the transaction
|
||||
daoError = qx::dao::insert(category_1, (& db)); bCommit = (bCommit && ! daoError.isValid());
|
||||
daoError = qx::dao::insert(category_2, (& db)); bCommit = (bCommit && ! daoError.isValid());
|
||||
daoError = qx::dao::insert(category_3, (& db)); bCommit = (bCommit && ! daoError.isValid());
|
||||
|
||||
qAssert(bCommit);
|
||||
qAssert(category_1->m_id != 0);
|
||||
qAssert(category_2->m_id != 0);
|
||||
qAssert(category_3->m_id != 0);
|
||||
|
||||
// Terminate transaction => commit or rollback if there is error
|
||||
if (bCommit) { db.commit(); }
|
||||
else { db.rollback(); }
|
||||
|
||||
} // End of scope : 'db' is destroyed
|
||||
|
||||
// Create a blog with the class name (factory)
|
||||
qx::any blog_any = qx::create("blog");
|
||||
blog_ptr blog_1;
|
||||
try { blog_1 = qx::any_cast<blog_ptr>(blog_any); }
|
||||
catch (...) { blog_1.reset(new blog()); }
|
||||
blog_1->m_text = "blog_text_1";
|
||||
blog_1->m_dt_creation = QDateTime::currentDateTime();
|
||||
blog_1->m_author = author_1;
|
||||
|
||||
// Insert 'blog_1' into database with 'save()' method
|
||||
daoError = qx::dao::save(blog_1);
|
||||
|
||||
// Modify 'blog_1' properties and save into database
|
||||
blog_1->m_text = "update blog_text_1";
|
||||
blog_1->m_author = author_2;
|
||||
daoError = qx::dao::save(blog_1);
|
||||
|
||||
// Add 2 comments to 'blog_1'
|
||||
comment_ptr comment_1; comment_1.reset(new comment());
|
||||
comment_ptr comment_2; comment_2.reset(new comment());
|
||||
|
||||
comment_1->m_text = "comment_1 text";
|
||||
comment_1->m_dt_create = QDateTime::currentDateTime();
|
||||
comment_1->m_blog = blog_1;
|
||||
comment_2->m_text = "comment_2 text";
|
||||
comment_2->m_dt_create = QDateTime::currentDateTime();
|
||||
comment_2->m_blog = blog_1;
|
||||
|
||||
daoError = qx::dao::insert(comment_1);
|
||||
daoError = qx::dao::insert(comment_2);
|
||||
qAssert(qx::dao::count<comment>() == 2);
|
||||
|
||||
// Add 2 categories to 'blog_1' => must insert into extra-table 'category_blog'
|
||||
blog_1->m_categoryX.insert(category_1->m_id, category_1);
|
||||
blog_1->m_categoryX.insert(category_3->m_id, category_3);
|
||||
daoError = qx::dao::save_with_relation("list_category", blog_1);
|
||||
|
||||
// Fetch blog into a new variable with all relation : 'author', 'comment' and 'category'
|
||||
blog_ptr blog_tmp; blog_tmp.reset(new blog());
|
||||
blog_tmp->m_id = blog_1->m_id;
|
||||
daoError = qx::dao::fetch_by_id_with_all_relation(blog_tmp);
|
||||
|
||||
qAssert(blog_tmp->m_commentX.count() == 2);
|
||||
qAssert(blog_tmp->m_categoryX.count() == 2);
|
||||
qAssert(blog_tmp->m_text == "update blog_text_1");
|
||||
qAssert(blog_tmp->m_author && blog_tmp->m_author->m_id == "author_id_2");
|
||||
|
||||
// Fetch blog into a new variable with many relations using "*->*->*->*" (4 levels of relationships)
|
||||
blog_tmp.reset(new blog());
|
||||
blog_tmp->m_id = blog_1->m_id;
|
||||
daoError = qx::dao::fetch_by_id_with_relation("*->*->*->*", blog_tmp);
|
||||
|
||||
qAssert(blog_tmp->m_commentX.count() == 2);
|
||||
qAssert(blog_tmp->m_categoryX.count() == 2);
|
||||
qAssert(blog_tmp->m_text == "update blog_text_1");
|
||||
qAssert(blog_tmp->m_author && blog_tmp->m_author->m_id == "author_id_2");
|
||||
|
||||
// Dump 'blog_tmp' result from database (xml serialization)
|
||||
qx::dump(blog_tmp, false);
|
||||
qx::dump(blog_tmp, true);
|
||||
|
||||
// Fetch relations defining columns to fetch with syntax { col_1, col_2, etc... }
|
||||
list_blog lstBlogComplexRelation;
|
||||
daoError = qx::dao::fetch_all_with_relation(QStringList() << "{ blog_text }" << "author_id { name, birthdate }" << "list_comment { comment_text } -> blog_id -> *", lstBlogComplexRelation);
|
||||
qx::dump(lstBlogComplexRelation);
|
||||
qAssert(lstBlogComplexRelation.size() > 0);
|
||||
qAssert(lstBlogComplexRelation[0]->m_text != ""); // Fetched
|
||||
qAssert(lstBlogComplexRelation[0]->m_dt_creation.isNull()); // Not fetched
|
||||
qAssert(lstBlogComplexRelation[0]->m_author->m_sex == author::unknown); // Not fetched
|
||||
qAssert(lstBlogComplexRelation[0]->m_author->m_name != ""); // Fetched
|
||||
qAssert(lstBlogComplexRelation[0]->m_commentX.size() > 0);
|
||||
qAssert(lstBlogComplexRelation[0]->m_commentX[0]->m_dt_create.isNull()); // Not fetched
|
||||
qAssert(lstBlogComplexRelation[0]->m_commentX[0]->m_text != ""); // Fetched
|
||||
qAssert(lstBlogComplexRelation[0]->m_commentX[0]->m_blog);
|
||||
|
||||
// Fetch relations defining columns to remove before fetching with syntax -{ col_1, col_2, etc... }
|
||||
list_blog lstBlogComplexRelation2;
|
||||
daoError = qx::dao::fetch_all_with_relation(QStringList() << "-{ blog_text }" << "author_id -{ name, birthdate }" << "list_comment -{ comment_text } -> blog_id -> *", lstBlogComplexRelation2);
|
||||
qx::dump(lstBlogComplexRelation2);
|
||||
qAssert(lstBlogComplexRelation2.size() > 0);
|
||||
qAssert(lstBlogComplexRelation2[0]->m_text == ""); // Not fetched
|
||||
qAssert(! lstBlogComplexRelation2[0]->m_dt_creation.isNull()); // Fetched
|
||||
qAssert(lstBlogComplexRelation2[0]->m_author->m_sex != author::unknown); // Fetched
|
||||
qAssert(lstBlogComplexRelation2[0]->m_author->m_name == ""); // Not fetched
|
||||
qAssert(lstBlogComplexRelation2[0]->m_commentX.size() > 0);
|
||||
qAssert(! lstBlogComplexRelation2[0]->m_commentX[0]->m_dt_create.isNull()); // Fetched
|
||||
qAssert(lstBlogComplexRelation2[0]->m_commentX[0]->m_text == ""); // Not fetched
|
||||
qAssert(lstBlogComplexRelation2[0]->m_commentX[0]->m_blog);
|
||||
|
||||
#ifndef _QX_NO_JSON
|
||||
// Custom JSON serialization process
|
||||
QString customJsonFull = qx::serialization::json::to_string(blog_tmp, 1);
|
||||
QString customJsonFiltered = qx::serialization::json::to_string(blog_tmp, 1, "filter: { blog_text } | author_id { name, birthdate } | list_comment { comment_text } -> blog_id -> *");
|
||||
qDebug("[QxOrm] custom JSON serialization process (full) : \n%s", qPrintable(customJsonFull));
|
||||
qDebug("[QxOrm] custom JSON serialization process (filtered) : \n%s", qPrintable(customJsonFiltered));
|
||||
|
||||
blog_ptr blogFromJsonFull; blogFromJsonFull.reset(new blog());
|
||||
blog_ptr blogFromJsonFiltered; blogFromJsonFiltered.reset(new blog());
|
||||
qx::serialization::json::from_string(blogFromJsonFull, customJsonFull, 1);
|
||||
qx::serialization::json::from_string(blogFromJsonFiltered, customJsonFull, 1, "filter: { blog_text } | author_id { name, birthdate } | list_comment { comment_text } -> blog_id -> *");
|
||||
|
||||
qx::dump(blogFromJsonFull);
|
||||
qAssert(blogFromJsonFull->m_commentX.count() == 2);
|
||||
qAssert(blogFromJsonFull->m_categoryX.count() == 2);
|
||||
qAssert(blogFromJsonFull->m_text == "update blog_text_1");
|
||||
qAssert(blogFromJsonFull->m_author && blogFromJsonFull->m_author->m_id == "author_id_2");
|
||||
|
||||
qx::dump(blogFromJsonFiltered);
|
||||
qAssert(blogFromJsonFiltered->m_text != ""); // Fetched
|
||||
qAssert(blogFromJsonFiltered->m_dt_creation.isNull()); // Not fetched
|
||||
qAssert(blogFromJsonFiltered->m_author->m_sex == author::unknown); // Not fetched
|
||||
qAssert(blogFromJsonFiltered->m_author->m_name != ""); // Fetched
|
||||
qAssert(blogFromJsonFiltered->m_commentX.size() > 0);
|
||||
qAssert(blogFromJsonFiltered->m_commentX[0]->m_dt_create.isNull()); // Not fetched
|
||||
qAssert(blogFromJsonFiltered->m_commentX[0]->m_text != ""); // Fetched
|
||||
qAssert(blogFromJsonFiltered->m_commentX[0]->m_blog);
|
||||
#endif // _QX_NO_JSON
|
||||
|
||||
// Fetch relations defining columns to fetch with syntax { col_1, col_2, etc... } + custom table alias using syntax <my_table_alias> + custom table alias suffix using syntax <..._my_alias_suffix>
|
||||
list_blog lstBlogComplexRelation3;
|
||||
daoError = qx::dao::fetch_all_with_relation(QStringList() << "<blog_alias> { blog_text }" << "author_id <author_alias> { name, birthdate }" << "list_comment <list_comment_alias> { comment_text } -> blog_id <blog_alias_2> -> * <..._my_alias_suffix>", lstBlogComplexRelation3);
|
||||
qx::dump(lstBlogComplexRelation3);
|
||||
qAssert(lstBlogComplexRelation3.size() > 0);
|
||||
qAssert(lstBlogComplexRelation3[0]->m_text != ""); // Fetched
|
||||
qAssert(lstBlogComplexRelation3[0]->m_dt_creation.isNull()); // Not fetched
|
||||
qAssert(lstBlogComplexRelation3[0]->m_author->m_sex == author::unknown); // Not fetched
|
||||
qAssert(lstBlogComplexRelation3[0]->m_author->m_name != ""); // Fetched
|
||||
qAssert(lstBlogComplexRelation3[0]->m_commentX.size() > 0);
|
||||
qAssert(lstBlogComplexRelation3[0]->m_commentX[0]->m_dt_create.isNull()); // Not fetched
|
||||
qAssert(lstBlogComplexRelation3[0]->m_commentX[0]->m_text != ""); // Fetched
|
||||
qAssert(lstBlogComplexRelation3[0]->m_commentX[0]->m_blog);
|
||||
|
||||
// Test to add join SQL sub-queries (inside LEFT OUTER JOIN or INNER JOIN)
|
||||
list_blog lstBlogWithJoinQueries;
|
||||
query = qx_query().where("blog_alias.blog_text").isEqualTo("update blog_text_1");
|
||||
query.addJoinQuery("list_comment_alias", "AND list_comment_alias.comment_text IS NOT NULL");
|
||||
query.addJoinQuery("author_alias", qx_query().freeText("AND author_alias.sex = :sex", QVariantList() << author::female));
|
||||
daoError = qx::dao::fetch_by_query_with_relation(QStringList() << "<blog_alias> { blog_text }" << "author_id <author_alias> { name, birthdate, sex }" << "list_comment <list_comment_alias> { comment_text }", query, lstBlogWithJoinQueries);
|
||||
qx::dump(lstBlogWithJoinQueries);
|
||||
qAssert(lstBlogWithJoinQueries.size() > 0);
|
||||
qAssert(lstBlogWithJoinQueries[0]->m_text == "update blog_text_1");
|
||||
qAssert(lstBlogWithJoinQueries[0]->m_author->m_sex == author::female);
|
||||
|
||||
// When join SQL sub-queries are used, then relationships should keep user defined order (in this example : 'list_comment' before 'author')
|
||||
lstBlogWithJoinQueries.clear();
|
||||
query = qx_query().where("blog_alias.blog_text").isEqualTo("update blog_text_1");
|
||||
query.addJoinQuery("list_comment_alias", "AND list_comment_alias.comment_text IS NOT NULL");
|
||||
query.addJoinQuery("author_alias", qx_query("AND author_alias.sex = :sex", QVariantList() << author::female));
|
||||
daoError = qx::dao::fetch_by_query_with_relation(QStringList() << "<blog_alias> { blog_text }" << "list_comment <list_comment_alias> { comment_text }" << "author_id <author_alias> { name, birthdate, sex }", query, lstBlogWithJoinQueries);
|
||||
qx::dump(lstBlogWithJoinQueries);
|
||||
qAssert(lstBlogWithJoinQueries.size() > 0);
|
||||
qAssert(lstBlogWithJoinQueries[0]->m_text == "update blog_text_1");
|
||||
qAssert(lstBlogWithJoinQueries[0]->m_author->m_sex == author::female);
|
||||
|
||||
// Check qx::dao::save_with_relation_recursive() function
|
||||
daoError = qx::dao::save_with_relation_recursive(blog_tmp);
|
||||
qAssert(! daoError.isValid());
|
||||
daoError = qx::dao::save_with_relation_recursive(blog_tmp, qx::dao::save_mode::e_update_only);
|
||||
qAssert(! daoError.isValid());
|
||||
|
||||
// Call 'age()' method with class name and method name (reflexion)
|
||||
qx_bool bInvokeOk = qx::QxClassX::invoke("author", "age", author_1);
|
||||
qAssert(bInvokeOk);
|
||||
|
||||
// Check count with relations and filter
|
||||
long lBlogCountWithRelation = 0; qx_query queryBlogCountWithRelation;
|
||||
daoError = qx::dao::count_with_relation<blog>(lBlogCountWithRelation, QStringList() << "author_id" << "list_comment -> blog_id -> *", queryBlogCountWithRelation);
|
||||
qAssert(! daoError.isValid() && (lBlogCountWithRelation > 0));
|
||||
|
||||
// Test 'isDirty()' method
|
||||
qx::dao::ptr<blog> blog_isdirty = qx::dao::ptr<blog>(new blog());
|
||||
blog_isdirty->m_id = blog_1->m_id;
|
||||
daoError = qx::dao::fetch_by_id(blog_isdirty);
|
||||
qAssert(! daoError.isValid() && ! blog_isdirty.isDirty());
|
||||
|
||||
blog_isdirty->m_text = "blog property 'text' modified => blog is dirty !!!";
|
||||
QStringList lstDiff; bool bDirty = blog_isdirty.isDirty(lstDiff);
|
||||
qAssert(bDirty && (lstDiff.count() == 1) && (lstDiff.at(0) == "blog_text"));
|
||||
if (bDirty) { qDebug("[QxOrm] test dirty 1 : blog is dirty => '%s'", qPrintable(lstDiff.join("|"))); }
|
||||
|
||||
// Update only property 'm_text' of 'blog_isdirty'
|
||||
daoError = qx::dao::update_optimized(blog_isdirty);
|
||||
qAssert(! daoError.isValid() && ! blog_isdirty.isDirty());
|
||||
qx::dump(blog_isdirty, false);
|
||||
qx::dump(blog_isdirty, true);
|
||||
|
||||
// Test 'isDirty()' method with a container
|
||||
typedef qx::dao::ptr< QList<author_ptr> > type_lst_author_test_is_dirty;
|
||||
type_lst_author_test_is_dirty container_isdirty = type_lst_author_test_is_dirty(new QList<author_ptr>());
|
||||
daoError = qx::dao::fetch_all(container_isdirty);
|
||||
qAssert(! daoError.isValid() && ! container_isdirty.isDirty() && (container_isdirty->count() == 3));
|
||||
|
||||
author_ptr author_ptr_dirty = container_isdirty->at(1);
|
||||
author_ptr_dirty->m_name = "author name modified at index 1 => container is dirty !!!";
|
||||
bDirty = container_isdirty.isDirty(lstDiff);
|
||||
qAssert(bDirty && (lstDiff.count() == 1));
|
||||
if (bDirty) { qDebug("[QxOrm] test dirty 2 : container is dirty => '%s'", qPrintable(lstDiff.join("|"))); }
|
||||
|
||||
author_ptr_dirty = container_isdirty->at(2);
|
||||
author_ptr_dirty->m_birthdate = QDate(1998, 03, 06);
|
||||
bDirty = container_isdirty.isDirty(lstDiff);
|
||||
qAssert(bDirty && (lstDiff.count() == 2));
|
||||
if (bDirty) { qDebug("[QxOrm] test dirty 3 : container is dirty => '%s'", qPrintable(lstDiff.join("|"))); }
|
||||
|
||||
// Update only property 'm_name' at position 1, only property 'm_birthdate' at position 2 and nothing at position 0
|
||||
daoError = qx::dao::update_optimized(container_isdirty);
|
||||
qAssert(! daoError.isValid() && ! container_isdirty.isDirty());
|
||||
qx::dump(container_isdirty, false);
|
||||
qx::dump(container_isdirty, true);
|
||||
|
||||
// Fetch only property 'm_dt_creation' of blog
|
||||
QStringList lstColumns = QStringList() << "date_creation";
|
||||
list_blog lst_blog_with_only_date_creation;
|
||||
daoError = qx::dao::fetch_all(lst_blog_with_only_date_creation, NULL, lstColumns);
|
||||
qAssert(! daoError.isValid() && (lst_blog_with_only_date_creation.size() > 0));
|
||||
if ((lst_blog_with_only_date_creation.size() > 0) && (lst_blog_with_only_date_creation[0].get() != NULL))
|
||||
{ qAssert(lst_blog_with_only_date_creation[0]->m_text.isEmpty()); }
|
||||
qx::dump(lst_blog_with_only_date_creation, false);
|
||||
qx::dump(lst_blog_with_only_date_creation, true);
|
||||
|
||||
// Dump all registered classes into QxOrm context (introspection engine)
|
||||
qx::QxClassX::dumpAllClasses();
|
||||
|
||||
// Call a custom SQL query or a stored procedure
|
||||
qx_query testStoredProc("SELECT * FROM author");
|
||||
daoError = qx::dao::call_query(testStoredProc);
|
||||
qAssert(! daoError.isValid());
|
||||
testStoredProc.dumpSqlResult();
|
||||
QVariant valFromSqlResult = testStoredProc.getSqlResultAt(0, "birthdate"); qAssert(! valFromSqlResult.isNull());
|
||||
valFromSqlResult = testStoredProc.getSqlResultAt(0, "BIRTHDATE", false); qAssert(! valFromSqlResult.isNull());
|
||||
valFromSqlResult = testStoredProc.getSqlResultAt(0, "BIRTHDATE", true); qAssert(valFromSqlResult.isNull());
|
||||
|
||||
// Call a custom SQL query or a stored procedure and fetch automatically properties (with a collection of items)
|
||||
qx_query testStoredProcBis("SELECT * FROM author");
|
||||
authorX.clear();
|
||||
daoError = qx::dao::execute_query(testStoredProcBis, authorX);
|
||||
qAssert(! daoError.isValid()); qAssert(authorX.count() > 0);
|
||||
qx::dump(authorX, false);
|
||||
qx::dump(authorX, true);
|
||||
|
||||
// Call a custom SQL query or a stored procedure and fetch automatically properties
|
||||
qx_query testStoredProcThird("SELECT name, category_id FROM category");
|
||||
category_ptr category_tmp = category_ptr(new category());
|
||||
daoError = qx::dao::execute_query(testStoredProcThird, category_tmp);
|
||||
qAssert(! daoError.isValid()); qAssert(category_tmp->m_id != 0);
|
||||
qx::dump(category_tmp, false);
|
||||
qx::dump(category_tmp, true);
|
||||
|
||||
// Test SQL DISTINCT keyword
|
||||
QList<blog> listOfBlogDistinct;
|
||||
qx_query queryDistinct; queryDistinct.distinct().limit(10);
|
||||
daoError = qx::dao::fetch_by_query(queryDistinct, listOfBlogDistinct, NULL, QStringList() << "blog_text");
|
||||
qAssert(! daoError.isValid());
|
||||
qx::dump(listOfBlogDistinct);
|
||||
qAssert(listOfBlogDistinct.count() > 0);
|
||||
qAssert(listOfBlogDistinct.at(0).m_id == 0);
|
||||
qAssert(! listOfBlogDistinct.at(0).m_text.isEmpty());
|
||||
|
||||
// Test SQL DISTINCT keyword with relationships
|
||||
listOfBlogDistinct.clear();
|
||||
qx_query queryDistinctWithRelations; queryDistinctWithRelations.distinct().limit(10);
|
||||
daoError = qx::dao::fetch_by_query_with_relation(QStringList() << "<blog_alias> { blog_text }" << "list_comment <list_comment_alias> { comment_text }" << "author_id <author_alias> { name, birthdate }", queryDistinctWithRelations, listOfBlogDistinct);
|
||||
qAssert(! daoError.isValid());
|
||||
qx::dump(listOfBlogDistinct);
|
||||
qAssert(listOfBlogDistinct.count() > 0);
|
||||
qAssert(listOfBlogDistinct.at(0).m_id == 0);
|
||||
qAssert(! listOfBlogDistinct.at(0).m_text.isEmpty());
|
||||
qAssert(listOfBlogDistinct.at(0).m_author.get() != NULL);
|
||||
qAssert(listOfBlogDistinct.at(0).m_author->m_id == "0"); // Not fetched
|
||||
qAssert(! listOfBlogDistinct.at(0).m_author->m_name.isEmpty());
|
||||
qAssert(listOfBlogDistinct.at(0).m_commentX.size() > 1);
|
||||
qAssert(listOfBlogDistinct.at(0).m_commentX.at(0)->m_id == 0); // Not fetched
|
||||
qAssert(! listOfBlogDistinct.at(0).m_commentX.at(0)->m_text.isEmpty());
|
||||
|
||||
// Test SQL DISTINCT keyword with relationships forcing ID in root level
|
||||
listOfBlogDistinct.clear();
|
||||
qx_query queryDistinctWithRelationsAndId; queryDistinctWithRelationsAndId.distinct().limit(10);
|
||||
daoError = qx::dao::fetch_by_query_with_relation(QStringList() << "<blog_alias> { blog_id, blog_text }" << "list_comment <list_comment_alias> { comment_text }" << "author_id <author_alias> { name, birthdate }", queryDistinctWithRelationsAndId, listOfBlogDistinct);
|
||||
qAssert(! daoError.isValid());
|
||||
qx::dump(listOfBlogDistinct);
|
||||
qAssert(listOfBlogDistinct.count() > 0);
|
||||
qAssert(listOfBlogDistinct.at(0).m_id != 0); // Force fetched even if DISTINCT keyword is used
|
||||
qAssert(! listOfBlogDistinct.at(0).m_text.isEmpty());
|
||||
qAssert(listOfBlogDistinct.at(0).m_author.get() != NULL);
|
||||
qAssert(listOfBlogDistinct.at(0).m_author->m_id == "0"); // Not fetched
|
||||
qAssert(! listOfBlogDistinct.at(0).m_author->m_name.isEmpty());
|
||||
qAssert(listOfBlogDistinct.at(0).m_commentX.size() > 1);
|
||||
qAssert(listOfBlogDistinct.at(0).m_commentX.at(0)->m_id == 0); // Not fetched
|
||||
qAssert(! listOfBlogDistinct.at(0).m_commentX.at(0)->m_text.isEmpty());
|
||||
|
||||
// Test fetch relationships (with alias) only in LEFT OUTER/INNER JOIN and WHERE clauses (so no columns in SELECT part) : use {NULL} syntax to define no relation columns in SELECT part
|
||||
list_blog lstBlogComplexRelation4;
|
||||
daoError = qx::dao::fetch_all_with_relation(QStringList() << "<blog_alias> { blog_text }" << "author_id <author_alias> { NULL }" << "list_comment <list_comment_alias> { NULL }", lstBlogComplexRelation4);
|
||||
qAssert(! daoError.isValid());
|
||||
qx::dump(lstBlogComplexRelation4);
|
||||
qAssert((lstBlogComplexRelation4.size() > 0) && (lstBlogComplexRelation4[0].get() != NULL));
|
||||
qAssert(lstBlogComplexRelation4[0]->m_author.get() == NULL); // Not fetched
|
||||
qAssert(lstBlogComplexRelation4[0]->m_commentX.size() == 0); // Not fetched
|
||||
|
||||
return 0;
|
||||
}
|
||||
56
test/qxBlogCompositeKey/CMakeLists.txt
Normal file
56
test/qxBlogCompositeKey/CMakeLists.txt
Normal file
@@ -0,0 +1,56 @@
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
project(qxBlogCompositeKey LANGUAGES CXX)
|
||||
|
||||
include(../../QxOrm.cmake)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
set(CMAKE_DEBUG_POSTFIX "d")
|
||||
|
||||
set(HEADERS
|
||||
./include/precompiled.h
|
||||
./include/export.h
|
||||
./include/author.h
|
||||
./include/blog.h
|
||||
./include/category.h
|
||||
./include/comment.h
|
||||
)
|
||||
|
||||
set(SRCS
|
||||
./src/author.cpp
|
||||
./src/blog.cpp
|
||||
./src/category.cpp
|
||||
./src/comment.cpp
|
||||
./src/main.cpp
|
||||
)
|
||||
|
||||
add_executable(qxBlogCompositeKey ${SRCS} ${HEADERS})
|
||||
|
||||
target_compile_definitions(qxBlogCompositeKey PRIVATE -D_BUILDING_QX_BLOG)
|
||||
|
||||
if(COMMAND target_precompile_headers)
|
||||
target_precompile_headers(qxBlogCompositeKey PRIVATE ./include/precompiled.h)
|
||||
endif() # (COMMAND target_precompile_headers)
|
||||
|
||||
target_link_libraries(qxBlogCompositeKey ${QX_LIBRARIES} QxOrm)
|
||||
|
||||
set_target_properties(qxBlogCompositeKey PROPERTIES
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
ARCHIVE_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
)
|
||||
|
||||
set_target_properties(qxBlogCompositeKey PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
|
||||
7
test/qxBlogCompositeKey/debug/.gitignore
vendored
Normal file
7
test/qxBlogCompositeKey/debug/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# git does not allow empty directories.
|
||||
# Yet, we need to add this empty directory on git.
|
||||
# To achieve that, we created this .gitignore file, so that the directory will not be empty thus enabling us to commit it.
|
||||
# Since we want all generated files/folders in this directory to be ignored by git, we add a rule for this.
|
||||
*
|
||||
# And then add an exception for this specifc file (so that we can commit it).
|
||||
!.gitignore
|
||||
57
test/qxBlogCompositeKey/include/author.h
Normal file
57
test/qxBlogCompositeKey/include/author.h
Normal file
@@ -0,0 +1,57 @@
|
||||
#ifndef _QX_BLOG_AUTHOR_H_
|
||||
#define _QX_BLOG_AUTHOR_H_
|
||||
|
||||
class blog;
|
||||
|
||||
class QX_BLOG_DLL_EXPORT author
|
||||
{
|
||||
|
||||
QX_REGISTER_FRIEND_CLASS(author)
|
||||
|
||||
public:
|
||||
|
||||
// -- composite key (multi-column primary key in database)
|
||||
typedef std::tuple<QString, long, QString> type_composite_key;
|
||||
static QString str_composite_key() { return "author_id_0|author_id_1|author_id_2"; }
|
||||
|
||||
// -- typedef
|
||||
typedef std::shared_ptr<blog> blog_ptr;
|
||||
typedef std::vector<blog_ptr> list_blog;
|
||||
|
||||
// -- enum
|
||||
enum enum_sex { male, female, unknown };
|
||||
|
||||
// -- properties
|
||||
type_composite_key m_id;
|
||||
QString m_name;
|
||||
QDate m_birthdate;
|
||||
enum_sex m_sex;
|
||||
list_blog m_blogX;
|
||||
|
||||
// -- contructor, virtual destructor
|
||||
author() : m_id("", 0, ""), m_sex(unknown) { ; }
|
||||
virtual ~author() { ; }
|
||||
|
||||
// -- methods
|
||||
int age() const;
|
||||
|
||||
// -- methods "get" to composite key
|
||||
type_composite_key getId() const { return m_id; }
|
||||
QString getId_0() const { return std::get<0>(m_id); }
|
||||
long getId_1() const { return std::get<1>(m_id); }
|
||||
QString getId_2() const { return std::get<2>(m_id); }
|
||||
|
||||
// -- methods "set" to composite key
|
||||
void setId_0(const QString & s) { std::get<0>(m_id) = s; }
|
||||
void setId_1(long l) { std::get<1>(m_id) = l; }
|
||||
void setId_2(const QString & s) { std::get<2>(m_id) = s; }
|
||||
|
||||
};
|
||||
|
||||
QX_REGISTER_PRIMARY_KEY(author, author::type_composite_key)
|
||||
QX_REGISTER_HPP_QX_BLOG(author, qx::trait::no_base_class_defined, 0)
|
||||
|
||||
typedef std::shared_ptr<author> author_ptr;
|
||||
typedef qx::QxCollection<author::type_composite_key, author_ptr> list_author;
|
||||
|
||||
#endif // _QX_BLOG_AUTHOR_H_
|
||||
48
test/qxBlogCompositeKey/include/blog.h
Normal file
48
test/qxBlogCompositeKey/include/blog.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef _QX_BLOG_BLOG_H_
|
||||
#define _QX_BLOG_BLOG_H_
|
||||
|
||||
#include "author.h"
|
||||
#include "comment.h"
|
||||
#include "category.h"
|
||||
|
||||
class QX_BLOG_DLL_EXPORT blog
|
||||
{
|
||||
|
||||
QX_REGISTER_FRIEND_CLASS(blog)
|
||||
|
||||
public:
|
||||
|
||||
// -- composite key (multi-column primary key in database)
|
||||
typedef QPair<long, QString> type_composite_key;
|
||||
static QString str_composite_key() { return "blog_id_0|blog_id_1"; }
|
||||
|
||||
// -- properties
|
||||
type_composite_key m_id;
|
||||
QString m_text;
|
||||
QDateTime m_dt_creation;
|
||||
author_ptr m_author;
|
||||
list_comment m_commentX;
|
||||
list_category m_categoryX;
|
||||
|
||||
// -- contructor, virtual destructor
|
||||
blog() : m_id(0, "") { ; }
|
||||
virtual ~blog() { ; }
|
||||
|
||||
// -- methods "get" to composite key
|
||||
type_composite_key getId() const { return m_id; }
|
||||
long getId_0() const { return m_id.first; }
|
||||
QString getId_1() const { return m_id.second; }
|
||||
|
||||
// -- methods "set" to composite key
|
||||
void setId_0(long l) { m_id.first = l; }
|
||||
void setId_1(const QString & s) { m_id.second = s; }
|
||||
|
||||
};
|
||||
|
||||
QX_REGISTER_PRIMARY_KEY(blog, blog::type_composite_key)
|
||||
QX_REGISTER_HPP_QX_BLOG(blog, qx::trait::no_base_class_defined, 0)
|
||||
|
||||
typedef std::shared_ptr<blog> blog_ptr;
|
||||
typedef std::vector<blog_ptr> list_blog;
|
||||
|
||||
#endif // _QX_BLOG_BLOG_H_
|
||||
52
test/qxBlogCompositeKey/include/category.h
Normal file
52
test/qxBlogCompositeKey/include/category.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#ifndef _QX_BLOG_CATEGORY_H_
|
||||
#define _QX_BLOG_CATEGORY_H_
|
||||
|
||||
class blog;
|
||||
|
||||
class QX_BLOG_DLL_EXPORT category
|
||||
{
|
||||
|
||||
QX_REGISTER_FRIEND_CLASS(category)
|
||||
|
||||
public:
|
||||
|
||||
// -- composite key (multi-column primary key in database)
|
||||
typedef std::tuple<QString, long, QString, long> type_composite_key;
|
||||
static QString str_composite_key() { return "category_id_0|category_id_1|category_id_2|category_id_3"; }
|
||||
|
||||
// -- typedef
|
||||
typedef std::shared_ptr<blog> blog_ptr;
|
||||
typedef qx::QxCollection<long, blog_ptr> list_blog;
|
||||
|
||||
// -- properties
|
||||
type_composite_key m_id;
|
||||
QString m_name;
|
||||
QString m_desc;
|
||||
list_blog m_blogX;
|
||||
|
||||
// -- contructor, virtual destructor
|
||||
category() : m_id("", 0, "", 0) { ; }
|
||||
virtual ~category() { ; }
|
||||
|
||||
// -- methods "get" to composite key
|
||||
type_composite_key getId() const { return m_id; }
|
||||
QString getId_0() const { return std::get<0>(m_id); }
|
||||
long getId_1() const { return std::get<1>(m_id); }
|
||||
QString getId_2() const { return std::get<2>(m_id); }
|
||||
long getId_3() const { return std::get<3>(m_id); }
|
||||
|
||||
// -- methods "set" to composite key
|
||||
void setId_0(const QString & s) { std::get<0>(m_id) = s; }
|
||||
void setId_1(long l) { std::get<1>(m_id) = l; }
|
||||
void setId_2(const QString & s) { std::get<2>(m_id) = s; }
|
||||
void setId_3(long l) { std::get<3>(m_id) = l; }
|
||||
|
||||
};
|
||||
|
||||
QX_REGISTER_PRIMARY_KEY(category, category::type_composite_key)
|
||||
QX_REGISTER_HPP_QX_BLOG(category, qx::trait::no_base_class_defined, 0)
|
||||
|
||||
typedef QSharedPointer<category> category_ptr;
|
||||
typedef qx::QxCollection<category::type_composite_key, category_ptr> list_category;
|
||||
|
||||
#endif // _QX_BLOG_CATEGORY_H_
|
||||
47
test/qxBlogCompositeKey/include/comment.h
Normal file
47
test/qxBlogCompositeKey/include/comment.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#ifndef _QX_BLOG_COMMENT_H_
|
||||
#define _QX_BLOG_COMMENT_H_
|
||||
|
||||
class blog;
|
||||
|
||||
class QX_BLOG_DLL_EXPORT comment
|
||||
{
|
||||
|
||||
QX_REGISTER_FRIEND_CLASS(comment)
|
||||
|
||||
public:
|
||||
|
||||
// -- composite key (multi-column primary key in database)
|
||||
typedef std::tuple<long, QString> type_composite_key;
|
||||
static QString str_composite_key() { return "comment_id_0|comment_id_1"; }
|
||||
|
||||
// -- typedef
|
||||
typedef std::shared_ptr<blog> blog_ptr;
|
||||
|
||||
// -- properties
|
||||
type_composite_key m_id;
|
||||
QString m_text;
|
||||
QDateTime m_dt_create;
|
||||
blog_ptr m_blog;
|
||||
|
||||
// -- contructor, virtual destructor
|
||||
comment() : m_id(0, "") { ; }
|
||||
virtual ~comment() { ; }
|
||||
|
||||
// -- methods "get" to composite key
|
||||
type_composite_key getId() const { return m_id; }
|
||||
long getId_0() const { return std::get<0>(m_id); }
|
||||
QString getId_1() const { return std::get<1>(m_id); }
|
||||
|
||||
// -- methods "set" to composite key
|
||||
void setId_0(long l) { std::get<0>(m_id) = l; }
|
||||
void setId_1(const QString & s) { std::get<1>(m_id) = s; }
|
||||
|
||||
};
|
||||
|
||||
QX_REGISTER_PRIMARY_KEY(comment, comment::type_composite_key)
|
||||
QX_REGISTER_HPP_QX_BLOG(comment, qx::trait::no_base_class_defined, 0)
|
||||
|
||||
typedef std::shared_ptr<comment> comment_ptr;
|
||||
typedef QList<comment_ptr> list_comment;
|
||||
|
||||
#endif // _QX_BLOG_COMMENT_H_
|
||||
18
test/qxBlogCompositeKey/include/export.h
Normal file
18
test/qxBlogCompositeKey/include/export.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef _QX_BLOG_EXPORT_H_
|
||||
#define _QX_BLOG_EXPORT_H_
|
||||
|
||||
#ifdef _BUILDING_QX_BLOG
|
||||
#define QX_BLOG_DLL_EXPORT QX_DLL_EXPORT_HELPER
|
||||
#else // _BUILDING_QX_BLOG
|
||||
#define QX_BLOG_DLL_EXPORT QX_DLL_IMPORT_HELPER
|
||||
#endif // _BUILDING_QX_BLOG
|
||||
|
||||
#ifdef _BUILDING_QX_BLOG
|
||||
#define QX_REGISTER_HPP_QX_BLOG QX_REGISTER_HPP_EXPORT_DLL
|
||||
#define QX_REGISTER_CPP_QX_BLOG QX_REGISTER_CPP_EXPORT_DLL
|
||||
#else // _BUILDING_QX_BLOG
|
||||
#define QX_REGISTER_HPP_QX_BLOG QX_REGISTER_HPP_IMPORT_DLL
|
||||
#define QX_REGISTER_CPP_QX_BLOG QX_REGISTER_CPP_IMPORT_DLL
|
||||
#endif // _BUILDING_QX_BLOG
|
||||
|
||||
#endif // _QX_BLOG_EXPORT_H_
|
||||
8
test/qxBlogCompositeKey/include/precompiled.h
Normal file
8
test/qxBlogCompositeKey/include/precompiled.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef _QX_BLOG_PRECOMPILED_HEADER_H_
|
||||
#define _QX_BLOG_PRECOMPILED_HEADER_H_
|
||||
|
||||
#include <QxOrm.h>
|
||||
|
||||
#include "export.h"
|
||||
|
||||
#endif // _QX_BLOG_PRECOMPILED_HEADER_H_
|
||||
7
test/qxBlogCompositeKey/qt/moc/.gitignore
vendored
Normal file
7
test/qxBlogCompositeKey/qt/moc/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# git does not allow empty directories.
|
||||
# Yet, we need to add this empty directory on git.
|
||||
# To achieve that, we created this .gitignore file, so that the directory will not be empty thus enabling us to commit it.
|
||||
# Since we want all generated files/folders in this directory to be ignored by git, we add a rule for this.
|
||||
*
|
||||
# And then add an exception for this specifc file (so that we can commit it).
|
||||
!.gitignore
|
||||
34
test/qxBlogCompositeKey/qxBlog.pro
Normal file
34
test/qxBlogCompositeKey/qxBlog.pro
Normal file
@@ -0,0 +1,34 @@
|
||||
include(../../QxOrm.pri)
|
||||
|
||||
TEMPLATE = app
|
||||
DEFINES += _BUILDING_QX_BLOG
|
||||
INCLUDEPATH += ../../../QxOrm/include/
|
||||
DESTDIR = ../../../QxOrm/test/_bin/
|
||||
LIBS += -L"../../../QxOrm/lib"
|
||||
|
||||
!contains(DEFINES, _QX_NO_PRECOMPILED_HEADER) {
|
||||
PRECOMPILED_HEADER = ./include/precompiled.h
|
||||
} # !contains(DEFINES, _QX_NO_PRECOMPILED_HEADER)
|
||||
|
||||
macx:CONFIG-=app_bundle
|
||||
|
||||
CONFIG(debug, debug|release) {
|
||||
TARGET = qxBlogCompositeKeyd
|
||||
LIBS += -l"QxOrmd"
|
||||
} else {
|
||||
TARGET = qxBlogCompositeKey
|
||||
LIBS += -l"QxOrm"
|
||||
} # CONFIG(debug, debug|release)
|
||||
|
||||
HEADERS += ./include/precompiled.h
|
||||
HEADERS += ./include/export.h
|
||||
HEADERS += ./include/author.h
|
||||
HEADERS += ./include/blog.h
|
||||
HEADERS += ./include/category.h
|
||||
HEADERS += ./include/comment.h
|
||||
|
||||
SOURCES += ./src/author.cpp
|
||||
SOURCES += ./src/blog.cpp
|
||||
SOURCES += ./src/category.cpp
|
||||
SOURCES += ./src/comment.cpp
|
||||
SOURCES += ./src/main.cpp
|
||||
7
test/qxBlogCompositeKey/release/.gitignore
vendored
Normal file
7
test/qxBlogCompositeKey/release/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# git does not allow empty directories.
|
||||
# Yet, we need to add this empty directory on git.
|
||||
# To achieve that, we created this .gitignore file, so that the directory will not be empty thus enabling us to commit it.
|
||||
# Since we want all generated files/folders in this directory to be ignored by git, we add a rule for this.
|
||||
*
|
||||
# And then add an exception for this specifc file (so that we can commit it).
|
||||
!.gitignore
|
||||
28
test/qxBlogCompositeKey/src/author.cpp
Normal file
28
test/qxBlogCompositeKey/src/author.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#include "../include/precompiled.h"
|
||||
|
||||
#include "../include/author.h"
|
||||
#include "../include/blog.h"
|
||||
|
||||
#include <QxOrm_Impl.h>
|
||||
|
||||
QX_REGISTER_CPP_QX_BLOG(author)
|
||||
|
||||
namespace qx {
|
||||
template <> void register_class(QxClass<author> & t)
|
||||
{
|
||||
t.id(& author::m_id, author::str_composite_key());
|
||||
|
||||
t.data(& author::m_name, "name");
|
||||
t.data(& author::m_birthdate, "birthdate");
|
||||
t.data(& author::m_sex, "sex");
|
||||
|
||||
t.relationOneToMany(& author::m_blogX, blog::str_composite_key(), author::str_composite_key());
|
||||
|
||||
t.fct_0<int>(std::mem_fn(& author::age), "age"); // using std::mem_fn() here is just a workaround for an issue with some versions of MSVC, it is not required with a full compliant C++11 compiler (http://stackoverflow.com/questions/23778883/vs2013-stdfunction-with-member-function)
|
||||
}}
|
||||
|
||||
int author::age() const
|
||||
{
|
||||
if (! m_birthdate.isValid()) { return -1; }
|
||||
return (QDate::currentDate().year() - m_birthdate.year());
|
||||
}
|
||||
60
test/qxBlogCompositeKey/src/blog.cpp
Normal file
60
test/qxBlogCompositeKey/src/blog.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#include "../include/precompiled.h"
|
||||
|
||||
#include "../include/blog.h"
|
||||
|
||||
#include <QxOrm_Impl.h>
|
||||
|
||||
QX_REGISTER_CPP_QX_BLOG(blog)
|
||||
|
||||
void logCustomSqlCallback(qx::IxDataMemberSqlCallbackParams & params, const QString & fctName)
|
||||
{
|
||||
QString msg = "-- " + fctName + " : " + params.pDataMember->getNameParent() + "::" + params.pDataMember->getName() + " --";
|
||||
msg += "\nSQL query generated by QxOrm library for this data member : " + params.sSQL;
|
||||
if (params.pSqlQueryBuilder) { msg += "\nCurrent building full SQL query (not finished yet) : " + params.pSqlQueryBuilder->getCurrentBuildingSql(); }
|
||||
msg += "\n";
|
||||
qDebug(qPrintable(msg));
|
||||
}
|
||||
|
||||
void myCustomGetSqlName(qx::IxDataMemberSqlCallbackParams & params)
|
||||
{
|
||||
logCustomSqlCallback(params, "myCustomGetSqlName");
|
||||
}
|
||||
|
||||
void myCustomGetSqlTablePointNameAsAlias(qx::IxDataMemberSqlCallbackParams & params)
|
||||
{
|
||||
logCustomSqlCallback(params, "myCustomGetSqlTablePointNameAsAlias");
|
||||
}
|
||||
|
||||
void myCustomGetSqlNameEqualToPlaceHolder(qx::IxDataMemberSqlCallbackParams & params)
|
||||
{
|
||||
logCustomSqlCallback(params, "myCustomGetSqlNameEqualToPlaceHolder");
|
||||
}
|
||||
|
||||
void myCustomGetSqlAliasEqualToPlaceHolder(qx::IxDataMemberSqlCallbackParams & params)
|
||||
{
|
||||
logCustomSqlCallback(params, "myCustomGetSqlAliasEqualToPlaceHolder");
|
||||
}
|
||||
|
||||
void myCustomGetSqlAlias(qx::IxDataMemberSqlCallbackParams & params)
|
||||
{
|
||||
logCustomSqlCallback(params, "myCustomGetSqlAlias");
|
||||
}
|
||||
|
||||
namespace qx {
|
||||
template <> void register_class(QxClass<blog> & t)
|
||||
{
|
||||
t.id(& blog::m_id, blog::str_composite_key());
|
||||
|
||||
t.data(& blog::m_text, "blog_text");
|
||||
qx::IxDataMember * pData = t.data(& blog::m_dt_creation, "date_creation");
|
||||
|
||||
pData->customGetSqlName(myCustomGetSqlName);
|
||||
pData->customGetSqlTablePointNameAsAlias(myCustomGetSqlTablePointNameAsAlias);
|
||||
pData->customGetSqlNameEqualToPlaceHolder(myCustomGetSqlNameEqualToPlaceHolder);
|
||||
pData->customGetSqlAliasEqualToPlaceHolder(myCustomGetSqlAliasEqualToPlaceHolder);
|
||||
pData->customGetSqlAlias(myCustomGetSqlAlias);
|
||||
|
||||
t.relationManyToOne(& blog::m_author, author::str_composite_key());
|
||||
t.relationOneToMany(& blog::m_commentX, comment::str_composite_key(), blog::str_composite_key());
|
||||
t.relationManyToMany(& blog::m_categoryX, "list_category", "category_blog", blog::str_composite_key(), category::str_composite_key());
|
||||
}}
|
||||
19
test/qxBlogCompositeKey/src/category.cpp
Normal file
19
test/qxBlogCompositeKey/src/category.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "../include/precompiled.h"
|
||||
|
||||
#include "../include/category.h"
|
||||
#include "../include/blog.h"
|
||||
|
||||
#include <QxOrm_Impl.h>
|
||||
|
||||
QX_REGISTER_CPP_QX_BLOG(category)
|
||||
|
||||
namespace qx {
|
||||
template <> void register_class(QxClass<category> & t)
|
||||
{
|
||||
t.id(& category::m_id, category::str_composite_key());
|
||||
|
||||
t.data(& category::m_name, "name");
|
||||
t.data(& category::m_desc, "description");
|
||||
|
||||
t.relationManyToMany(& category::m_blogX, "list_blog", "category_blog", category::str_composite_key(), blog::str_composite_key());
|
||||
}}
|
||||
19
test/qxBlogCompositeKey/src/comment.cpp
Normal file
19
test/qxBlogCompositeKey/src/comment.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "../include/precompiled.h"
|
||||
|
||||
#include "../include/comment.h"
|
||||
#include "../include/blog.h"
|
||||
|
||||
#include <QxOrm_Impl.h>
|
||||
|
||||
QX_REGISTER_CPP_QX_BLOG(comment)
|
||||
|
||||
namespace qx {
|
||||
template <> void register_class(QxClass<comment> & t)
|
||||
{
|
||||
t.id(& comment::m_id, comment::str_composite_key());
|
||||
|
||||
t.data(& comment::m_text, "comment_text");
|
||||
t.data(& comment::m_dt_create, "date_creation");
|
||||
|
||||
t.relationManyToOne(& comment::m_blog, blog::str_composite_key());
|
||||
}}
|
||||
225
test/qxBlogCompositeKey/src/main.cpp
Normal file
225
test/qxBlogCompositeKey/src/main.cpp
Normal file
@@ -0,0 +1,225 @@
|
||||
#include "../include/precompiled.h"
|
||||
|
||||
#include <QtCore/qcoreapplication.h>
|
||||
|
||||
#include "../include/blog.h"
|
||||
#include "../include/author.h"
|
||||
#include "../include/comment.h"
|
||||
#include "../include/category.h"
|
||||
|
||||
#include <QxOrm_Impl.h>
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
// Qt application
|
||||
QCoreApplication app(argc, argv);
|
||||
QFile::remove("./qxBlogCompositeKey.sqlite");
|
||||
|
||||
// Parameters to connect to database
|
||||
qx::QxSqlDatabase::getSingleton()->setDriverName("QSQLITE");
|
||||
qx::QxSqlDatabase::getSingleton()->setDatabaseName("./qxBlogCompositeKey.sqlite");
|
||||
qx::QxSqlDatabase::getSingleton()->setHostName("localhost");
|
||||
qx::QxSqlDatabase::getSingleton()->setUserName("root");
|
||||
qx::QxSqlDatabase::getSingleton()->setPassword("");
|
||||
qx::QxSqlDatabase::getSingleton()->setAddSqlSquareBracketsForTableName(true);
|
||||
qx::QxSqlDatabase::getSingleton()->setAddSqlSquareBracketsForColumnName(true);
|
||||
|
||||
// Only for debug purpose : assert if invalid offset detected fetching a relation
|
||||
qx::QxSqlDatabase::getSingleton()->setVerifyOffsetRelation(true);
|
||||
qx::IxSqlRelation::setTraceRelationInit(true);
|
||||
qx::QxClassX::registerAllClasses();
|
||||
|
||||
// Create all tables in database
|
||||
QSqlError daoError = qx::dao::create_table<author>();
|
||||
daoError = qx::dao::create_table<comment>();
|
||||
daoError = qx::dao::create_table<category>();
|
||||
daoError = qx::dao::create_table<blog>();
|
||||
|
||||
// Create a list of 3 author
|
||||
author_ptr author_1; author_1.reset(new author());
|
||||
author_ptr author_2; author_2.reset(new author());
|
||||
author_ptr author_3; author_3.reset(new author());
|
||||
|
||||
author_1->setId_0("_111_"); author_1->setId_1(100); author_1->setId_2("1_1");
|
||||
author_1->m_name = "author_1"; author_1->m_sex = author::male; author_1->m_birthdate = QDate::currentDate();
|
||||
author_2->setId_0("_222_"); author_2->setId_1(200); author_2->setId_2("2_2");
|
||||
author_2->m_name = "author_2"; author_2->m_sex = author::female; author_2->m_birthdate = QDate::currentDate();
|
||||
author_3->setId_0("_333_"); author_3->setId_1(300); author_3->setId_2("3_3");
|
||||
author_3->m_name = "author_3"; author_3->m_sex = author::female; author_3->m_birthdate = QDate::currentDate();
|
||||
|
||||
list_author authorX;
|
||||
authorX.insert(author_1->getId(), author_1);
|
||||
authorX.insert(author_2->getId(), author_2);
|
||||
authorX.insert(author_3->getId(), author_3);
|
||||
|
||||
// Insert list of 3 author into database
|
||||
daoError = qx::dao::insert(authorX);
|
||||
qAssert(qx::dao::count<author>() == 3);
|
||||
|
||||
// Clone author 2 : 'author_id_2'
|
||||
author_ptr author_clone = qx::clone(* author_2);
|
||||
qAssert(author_clone->getId() == author::type_composite_key("_222_", 200, "2_2"));
|
||||
qAssert(author_clone->m_sex == author::female);
|
||||
|
||||
// Create a query to fetch only female author : 'author_id_2' and 'author_id_3'
|
||||
qx::QxSqlQuery query("WHERE author.sex = :sex");
|
||||
query.bind(":sex", author::female);
|
||||
|
||||
list_author list_of_female_author;
|
||||
daoError = qx::dao::fetch_by_query(query, list_of_female_author);
|
||||
qAssert(list_of_female_author.count() == 2);
|
||||
|
||||
// Dump list of female author (xml serialization)
|
||||
qx::dump(list_of_female_author);
|
||||
|
||||
// Create 3 categories
|
||||
category_ptr category_1 = category_ptr(new category());
|
||||
category_ptr category_2 = category_ptr(new category());
|
||||
category_ptr category_3 = category_ptr(new category());
|
||||
|
||||
category_1->setId_0("101"); category_1->setId_1(10);
|
||||
category_1->setId_2("__11_XX"); category_1->setId_3(10010);
|
||||
category_1->m_name = "category_1"; category_1->m_desc = "desc_1";
|
||||
category_2->setId_0("202"); category_2->setId_1(20);
|
||||
category_2->setId_2("__22_XX"); category_2->setId_3(20020);
|
||||
category_2->m_name = "category_2"; category_2->m_desc = "desc_2";
|
||||
category_3->setId_0("303"); category_3->setId_1(30);
|
||||
category_3->setId_2("__33_XX"); category_3->setId_3(30030);
|
||||
category_3->m_name = "category_3"; category_3->m_desc = "desc_3";
|
||||
|
||||
{ // Create a scope to destroy temporary connexion to database
|
||||
|
||||
// Open a transaction to database
|
||||
QSqlDatabase db = qx::QxSqlDatabase::getDatabase();
|
||||
bool bCommit = db.transaction();
|
||||
|
||||
// Insert 3 categories into database, use 'db' parameter for the transaction
|
||||
daoError = qx::dao::insert(category_1, (& db)); bCommit = (bCommit && ! daoError.isValid());
|
||||
daoError = qx::dao::insert(category_2, (& db)); bCommit = (bCommit && ! daoError.isValid());
|
||||
daoError = qx::dao::insert(category_3, (& db)); bCommit = (bCommit && ! daoError.isValid());
|
||||
|
||||
qAssert(bCommit);
|
||||
qAssert(category_1->getId() == category::type_composite_key("101", 10, "__11_XX", 10010));
|
||||
qAssert(category_2->getId() == category::type_composite_key("202", 20, "__22_XX", 20020));
|
||||
qAssert(category_3->getId() == category::type_composite_key("303", 30, "__33_XX", 30030));
|
||||
|
||||
// Terminate transaction => commit or rollback if there is error
|
||||
if (bCommit) { db.commit(); }
|
||||
else { db.rollback(); }
|
||||
|
||||
} // End of scope : 'db' is destroyed
|
||||
|
||||
// Create a blog with the class name (factory)
|
||||
qx::any blog_any = qx::create("blog");
|
||||
blog_ptr blog_1;
|
||||
try { blog_1 = qx::any_cast<blog_ptr>(blog_any); }
|
||||
catch (...) { blog_1.reset(new blog()); }
|
||||
blog_1->setId_0(1);
|
||||
blog_1->setId_1("blog 1");
|
||||
blog_1->m_text = "blog_text_1";
|
||||
blog_1->m_dt_creation = QDateTime::currentDateTime();
|
||||
blog_1->m_author = author_1;
|
||||
|
||||
// Insert 'blog_1' into database with 'save()' method
|
||||
daoError = qx::dao::save(blog_1);
|
||||
|
||||
// Modify 'blog_1' properties and save into database
|
||||
blog_1->m_text = "update blog_text_1";
|
||||
blog_1->m_author = author_2;
|
||||
daoError = qx::dao::save(blog_1);
|
||||
|
||||
// Add 2 comments to 'blog_1'
|
||||
comment_ptr comment_1; comment_1.reset(new comment());
|
||||
comment_ptr comment_2; comment_2.reset(new comment());
|
||||
|
||||
comment_1->setId_0(1);
|
||||
comment_1->setId_1("comment 1");
|
||||
comment_1->m_text = "comment_1 text";
|
||||
comment_1->m_dt_create = QDateTime::currentDateTime();
|
||||
comment_1->m_blog = blog_1;
|
||||
comment_2->setId_0(2);
|
||||
comment_2->setId_1("comment 2");
|
||||
comment_2->m_text = "comment_2 text";
|
||||
comment_2->m_dt_create = QDateTime::currentDateTime();
|
||||
comment_2->m_blog = blog_1;
|
||||
|
||||
daoError = qx::dao::insert(comment_1);
|
||||
daoError = qx::dao::insert(comment_2);
|
||||
qAssert(! daoError.isValid() && (qx::dao::count<comment>() == 2));
|
||||
|
||||
// Add 2 categories to 'blog_1' => must insert into extra-table 'category_blog'
|
||||
blog_1->m_categoryX.insert(category_1->getId(), category_1);
|
||||
blog_1->m_categoryX.insert(category_3->getId(), category_3);
|
||||
daoError = qx::dao::save_with_relation("list_category", blog_1);
|
||||
|
||||
// Fetch blog into a new variable with all relation : 'author', 'comment' and 'category'
|
||||
blog_ptr blog_tmp; blog_tmp.reset(new blog());
|
||||
blog_tmp->setId_0(blog_1->getId_0());
|
||||
blog_tmp->setId_1(blog_1->getId_1());
|
||||
daoError = qx::dao::fetch_by_id_with_all_relation(blog_tmp);
|
||||
|
||||
qAssert(! daoError.isValid());
|
||||
qAssert(blog_tmp->m_commentX.count() == 2);
|
||||
qAssert(blog_tmp->m_categoryX.count() == 2);
|
||||
qAssert(blog_tmp->m_text == "update blog_text_1");
|
||||
qAssert(blog_tmp->m_author && blog_tmp->m_author->getId() == author::type_composite_key("_222_", 200, "2_2"));
|
||||
|
||||
// Dump 'blog_tmp' result from database (xml serialization)
|
||||
qx::dump(blog_tmp);
|
||||
|
||||
// Fetch relations defining columns to fetch with syntax { col_1, col_2, etc... }
|
||||
list_blog lstBlogComplexRelation;
|
||||
daoError = qx::dao::fetch_all_with_relation(QStringList() << author::str_composite_key() + " { name, birthdate }" << comment::str_composite_key() + " { comment_text } -> " + blog::str_composite_key() + " -> *", lstBlogComplexRelation);
|
||||
qx::dump(lstBlogComplexRelation);
|
||||
qAssert(lstBlogComplexRelation.size() > 0);
|
||||
qAssert(lstBlogComplexRelation[0]->m_author->m_sex == author::unknown); // Not fetched
|
||||
qAssert(lstBlogComplexRelation[0]->m_author->m_name != ""); // Fetched
|
||||
qAssert(lstBlogComplexRelation[0]->m_commentX.size() > 0);
|
||||
qAssert(lstBlogComplexRelation[0]->m_commentX[0]->m_dt_create.isNull()); // Not fetched
|
||||
qAssert(lstBlogComplexRelation[0]->m_commentX[0]->m_text != ""); // Fetched
|
||||
qAssert(lstBlogComplexRelation[0]->m_commentX[0]->m_blog);
|
||||
|
||||
// Call 'age()' method with class name and method name (reflexion)
|
||||
qx_bool bInvokeOk = qx::QxClassX::invoke("author", "age", author_1);
|
||||
qAssert(bInvokeOk);
|
||||
|
||||
// Test 'isDirty()' method
|
||||
qx::dao::ptr<blog> blog_isdirty = qx::dao::ptr<blog>(new blog());
|
||||
blog_isdirty->setId_0(blog_1->getId_0());
|
||||
blog_isdirty->setId_1(blog_1->getId_1());
|
||||
daoError = qx::dao::fetch_by_id(blog_isdirty);
|
||||
qAssert(! daoError.isValid() && ! blog_isdirty.isDirty());
|
||||
|
||||
blog_isdirty->m_text = "blog property 'text' modified => blog is dirty !!!";
|
||||
QStringList lstDiff; bool bDirty = blog_isdirty.isDirty(lstDiff);
|
||||
qAssert(bDirty && (lstDiff.count() == 1) && (lstDiff.at(0) == "blog_text"));
|
||||
if (bDirty) { qDebug("[QxOrm] test dirty 1 : blog is dirty => '%s'", qPrintable(lstDiff.join("|"))); }
|
||||
|
||||
daoError = qx::dao::update(blog_isdirty);
|
||||
qAssert(! daoError.isValid() && ! blog_isdirty.isDirty());
|
||||
qx::dump(blog_isdirty);
|
||||
|
||||
// Test 'isDirty()' method with a container
|
||||
typedef qx::dao::ptr< QList<author_ptr> > type_lst_author_test_is_dirty;
|
||||
type_lst_author_test_is_dirty container_isdirty = type_lst_author_test_is_dirty(new QList<author_ptr>());
|
||||
daoError = qx::dao::fetch_all(container_isdirty);
|
||||
qAssert(! daoError.isValid() && ! container_isdirty.isDirty() && (container_isdirty->count() == 3));
|
||||
|
||||
author_ptr author_ptr_dirty = container_isdirty->at(1);
|
||||
author_ptr_dirty->m_name = "author name modified at index 1 => container is dirty !!!";
|
||||
bDirty = container_isdirty.isDirty(lstDiff);
|
||||
qAssert(bDirty && (lstDiff.count() == 1));
|
||||
if (bDirty) { qDebug("[QxOrm] test dirty 2 : container is dirty => '%s'", qPrintable(lstDiff.join("|"))); }
|
||||
|
||||
author_ptr_dirty = container_isdirty->at(2);
|
||||
author_ptr_dirty->m_birthdate = QDate(1998, 03, 06);
|
||||
bDirty = container_isdirty.isDirty(lstDiff);
|
||||
qAssert(bDirty && (lstDiff.count() == 2));
|
||||
if (bDirty) { qDebug("[QxOrm] test dirty 3 : container is dirty => '%s'", qPrintable(lstDiff.join("|"))); }
|
||||
|
||||
daoError = qx::dao::save(container_isdirty);
|
||||
qAssert(! daoError.isValid() && ! container_isdirty.isDirty());
|
||||
qx::dump(container_isdirty);
|
||||
|
||||
return 0;
|
||||
}
|
||||
56
test/qxBlogCpp11/CMakeLists.txt
Normal file
56
test/qxBlogCpp11/CMakeLists.txt
Normal file
@@ -0,0 +1,56 @@
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
project(qxBlogCpp11 LANGUAGES CXX)
|
||||
|
||||
include(../../QxOrm.cmake)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
set(CMAKE_DEBUG_POSTFIX "d")
|
||||
|
||||
set(HEADERS
|
||||
./include/precompiled.h
|
||||
./include/export.h
|
||||
./include/author.h
|
||||
./include/blog.h
|
||||
./include/category.h
|
||||
./include/comment.h
|
||||
)
|
||||
|
||||
set(SRCS
|
||||
./src/author.cpp
|
||||
./src/blog.cpp
|
||||
./src/category.cpp
|
||||
./src/comment.cpp
|
||||
./src/main.cpp
|
||||
)
|
||||
|
||||
add_executable(qxBlogCpp11 ${SRCS} ${HEADERS})
|
||||
|
||||
target_compile_definitions(qxBlogCpp11 PRIVATE -D_BUILDING_QX_BLOG)
|
||||
|
||||
if(COMMAND target_precompile_headers)
|
||||
target_precompile_headers(qxBlogCpp11 PRIVATE ./include/precompiled.h)
|
||||
endif() # (COMMAND target_precompile_headers)
|
||||
|
||||
target_link_libraries(qxBlogCpp11 ${QX_LIBRARIES} QxOrm)
|
||||
|
||||
set_target_properties(qxBlogCpp11 PROPERTIES
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
ARCHIVE_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
)
|
||||
|
||||
set_target_properties(qxBlogCpp11 PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
|
||||
7
test/qxBlogCpp11/debug/.gitignore
vendored
Normal file
7
test/qxBlogCpp11/debug/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# git does not allow empty directories.
|
||||
# Yet, we need to add this empty directory on git.
|
||||
# To achieve that, we created this .gitignore file, so that the directory will not be empty thus enabling us to commit it.
|
||||
# Since we want all generated files/folders in this directory to be ignored by git, we add a rule for this.
|
||||
*
|
||||
# And then add an exception for this specifc file (so that we can commit it).
|
||||
!.gitignore
|
||||
57
test/qxBlogCpp11/include/author.h
Normal file
57
test/qxBlogCpp11/include/author.h
Normal file
@@ -0,0 +1,57 @@
|
||||
#ifndef _QX_BLOG_AUTHOR_H_
|
||||
#define _QX_BLOG_AUTHOR_H_
|
||||
|
||||
class blog;
|
||||
|
||||
class QX_BLOG_DLL_EXPORT author
|
||||
{
|
||||
|
||||
QX_REGISTER_FRIEND_CLASS(author)
|
||||
|
||||
public:
|
||||
|
||||
// -- composite key (multi-column primary key in database)
|
||||
typedef QX_TUPLE<QString, long, QString> type_composite_key;
|
||||
static QString str_composite_key() { return "author_id_0|author_id_1|author_id_2"; }
|
||||
|
||||
// -- typedef
|
||||
typedef std::shared_ptr<blog> blog_ptr;
|
||||
typedef std::vector<blog_ptr> list_blog;
|
||||
|
||||
// -- enum
|
||||
enum enum_sex { male, female, unknown };
|
||||
|
||||
// -- properties
|
||||
type_composite_key m_id;
|
||||
QString m_name;
|
||||
QDate m_birthdate;
|
||||
enum_sex m_sex;
|
||||
list_blog m_blogX;
|
||||
|
||||
// -- contructor, virtual destructor
|
||||
author() : m_id("", 0, ""), m_sex(unknown) { ; }
|
||||
virtual ~author() { ; }
|
||||
|
||||
// -- methods
|
||||
int age() const;
|
||||
|
||||
// -- methods "get" to composite key
|
||||
type_composite_key getId() const { return m_id; }
|
||||
QString getId_0() const { return QX_TUPLE_GET<0>(m_id); }
|
||||
long getId_1() const { return QX_TUPLE_GET<1>(m_id); }
|
||||
QString getId_2() const { return QX_TUPLE_GET<2>(m_id); }
|
||||
|
||||
// -- methods "set" to composite key
|
||||
void setId_0(const QString & s) { QX_TUPLE_GET<0>(m_id) = s; }
|
||||
void setId_1(long l) { QX_TUPLE_GET<1>(m_id) = l; }
|
||||
void setId_2(const QString & s) { QX_TUPLE_GET<2>(m_id) = s; }
|
||||
|
||||
};
|
||||
|
||||
QX_REGISTER_PRIMARY_KEY(author, author::type_composite_key)
|
||||
QX_REGISTER_HPP_QX_BLOG(author, qx::trait::no_base_class_defined, 0)
|
||||
|
||||
typedef std::shared_ptr<author> author_ptr;
|
||||
typedef qx::QxCollection<author::type_composite_key, author_ptr> list_author;
|
||||
|
||||
#endif // _QX_BLOG_AUTHOR_H_
|
||||
48
test/qxBlogCpp11/include/blog.h
Normal file
48
test/qxBlogCpp11/include/blog.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef _QX_BLOG_BLOG_H_
|
||||
#define _QX_BLOG_BLOG_H_
|
||||
|
||||
#include "author.h"
|
||||
#include "comment.h"
|
||||
#include "category.h"
|
||||
|
||||
class QX_BLOG_DLL_EXPORT blog
|
||||
{
|
||||
|
||||
QX_REGISTER_FRIEND_CLASS(blog)
|
||||
|
||||
public:
|
||||
|
||||
// -- composite key (multi-column primary key in database)
|
||||
typedef QPair<long, QString> type_composite_key;
|
||||
static QString str_composite_key() { return "blog_id_0|blog_id_1"; }
|
||||
|
||||
// -- properties
|
||||
type_composite_key m_id;
|
||||
QString m_text;
|
||||
QDateTime m_dt_creation;
|
||||
author_ptr m_author;
|
||||
list_comment m_commentX;
|
||||
list_category m_categoryX;
|
||||
|
||||
// -- contructor, virtual destructor
|
||||
blog() : m_id(0, "") { ; }
|
||||
virtual ~blog() { ; }
|
||||
|
||||
// -- methods "get" to composite key
|
||||
type_composite_key getId() const { return m_id; }
|
||||
long getId_0() const { return m_id.first; }
|
||||
QString getId_1() const { return m_id.second; }
|
||||
|
||||
// -- methods "set" to composite key
|
||||
void setId_0(long l) { m_id.first = l; }
|
||||
void setId_1(const QString & s) { m_id.second = s; }
|
||||
|
||||
};
|
||||
|
||||
QX_REGISTER_PRIMARY_KEY(blog, blog::type_composite_key)
|
||||
QX_REGISTER_HPP_QX_BLOG(blog, qx::trait::no_base_class_defined, 0)
|
||||
|
||||
typedef std::shared_ptr<blog> blog_ptr;
|
||||
typedef std::vector<blog_ptr> list_blog;
|
||||
|
||||
#endif // _QX_BLOG_BLOG_H_
|
||||
52
test/qxBlogCpp11/include/category.h
Normal file
52
test/qxBlogCpp11/include/category.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#ifndef _QX_BLOG_CATEGORY_H_
|
||||
#define _QX_BLOG_CATEGORY_H_
|
||||
|
||||
class blog;
|
||||
|
||||
class QX_BLOG_DLL_EXPORT category
|
||||
{
|
||||
|
||||
QX_REGISTER_FRIEND_CLASS(category)
|
||||
|
||||
public:
|
||||
|
||||
// -- composite key (multi-column primary key in database)
|
||||
typedef QX_TUPLE<QString, long, QString, long> type_composite_key;
|
||||
static QString str_composite_key() { return "category_id_0|category_id_1|category_id_2|category_id_3"; }
|
||||
|
||||
// -- typedef
|
||||
typedef std::shared_ptr<blog> blog_ptr;
|
||||
typedef qx::QxCollection<long, blog_ptr> list_blog;
|
||||
|
||||
// -- properties
|
||||
type_composite_key m_id;
|
||||
QString m_name;
|
||||
QString m_desc;
|
||||
list_blog m_blogX;
|
||||
|
||||
// -- contructor, virtual destructor
|
||||
category() : m_id("", 0, "", 0) { ; }
|
||||
virtual ~category() { ; }
|
||||
|
||||
// -- methods "get" to composite key
|
||||
type_composite_key getId() const { return m_id; }
|
||||
QString getId_0() const { return QX_TUPLE_GET<0>(m_id); }
|
||||
long getId_1() const { return QX_TUPLE_GET<1>(m_id); }
|
||||
QString getId_2() const { return QX_TUPLE_GET<2>(m_id); }
|
||||
long getId_3() const { return QX_TUPLE_GET<3>(m_id); }
|
||||
|
||||
// -- methods "set" to composite key
|
||||
void setId_0(const QString & s) { QX_TUPLE_GET<0>(m_id) = s; }
|
||||
void setId_1(long l) { QX_TUPLE_GET<1>(m_id) = l; }
|
||||
void setId_2(const QString & s) { QX_TUPLE_GET<2>(m_id) = s; }
|
||||
void setId_3(long l) { QX_TUPLE_GET<3>(m_id) = l; }
|
||||
|
||||
};
|
||||
|
||||
QX_REGISTER_PRIMARY_KEY(category, category::type_composite_key)
|
||||
QX_REGISTER_HPP_QX_BLOG(category, qx::trait::no_base_class_defined, 0)
|
||||
|
||||
typedef QSharedPointer<category> category_ptr;
|
||||
typedef qx::QxCollection<category::type_composite_key, category_ptr> list_category;
|
||||
|
||||
#endif // _QX_BLOG_CATEGORY_H_
|
||||
47
test/qxBlogCpp11/include/comment.h
Normal file
47
test/qxBlogCpp11/include/comment.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#ifndef _QX_BLOG_COMMENT_H_
|
||||
#define _QX_BLOG_COMMENT_H_
|
||||
|
||||
class blog;
|
||||
|
||||
class QX_BLOG_DLL_EXPORT comment
|
||||
{
|
||||
|
||||
QX_REGISTER_FRIEND_CLASS(comment)
|
||||
|
||||
public:
|
||||
|
||||
// -- composite key (multi-column primary key in database)
|
||||
typedef QX_TUPLE<long, QString> type_composite_key;
|
||||
static QString str_composite_key() { return "comment_id_0|comment_id_1"; }
|
||||
|
||||
// -- typedef
|
||||
typedef std::shared_ptr<blog> blog_ptr;
|
||||
|
||||
// -- properties
|
||||
type_composite_key m_id;
|
||||
QString m_text;
|
||||
QDateTime m_dt_create;
|
||||
blog_ptr m_blog;
|
||||
|
||||
// -- contructor, virtual destructor
|
||||
comment() : m_id(0, "") { ; }
|
||||
virtual ~comment() { ; }
|
||||
|
||||
// -- methods "get" to composite key
|
||||
type_composite_key getId() const { return m_id; }
|
||||
long getId_0() const { return QX_TUPLE_GET<0>(m_id); }
|
||||
QString getId_1() const { return QX_TUPLE_GET<1>(m_id); }
|
||||
|
||||
// -- methods "set" to composite key
|
||||
void setId_0(long l) { QX_TUPLE_GET<0>(m_id) = l; }
|
||||
void setId_1(const QString & s) { QX_TUPLE_GET<1>(m_id) = s; }
|
||||
|
||||
};
|
||||
|
||||
QX_REGISTER_PRIMARY_KEY(comment, comment::type_composite_key)
|
||||
QX_REGISTER_HPP_QX_BLOG(comment, qx::trait::no_base_class_defined, 0)
|
||||
|
||||
typedef std::shared_ptr<comment> comment_ptr;
|
||||
typedef QList<comment_ptr> list_comment;
|
||||
|
||||
#endif // _QX_BLOG_COMMENT_H_
|
||||
18
test/qxBlogCpp11/include/export.h
Normal file
18
test/qxBlogCpp11/include/export.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef _QX_BLOG_EXPORT_H_
|
||||
#define _QX_BLOG_EXPORT_H_
|
||||
|
||||
#ifdef _BUILDING_QX_BLOG
|
||||
#define QX_BLOG_DLL_EXPORT QX_DLL_EXPORT_HELPER
|
||||
#else // _BUILDING_QX_BLOG
|
||||
#define QX_BLOG_DLL_EXPORT QX_DLL_IMPORT_HELPER
|
||||
#endif // _BUILDING_QX_BLOG
|
||||
|
||||
#ifdef _BUILDING_QX_BLOG
|
||||
#define QX_REGISTER_HPP_QX_BLOG QX_REGISTER_HPP_EXPORT_DLL
|
||||
#define QX_REGISTER_CPP_QX_BLOG QX_REGISTER_CPP_EXPORT_DLL
|
||||
#else // _BUILDING_QX_BLOG
|
||||
#define QX_REGISTER_HPP_QX_BLOG QX_REGISTER_HPP_IMPORT_DLL
|
||||
#define QX_REGISTER_CPP_QX_BLOG QX_REGISTER_CPP_IMPORT_DLL
|
||||
#endif // _BUILDING_QX_BLOG
|
||||
|
||||
#endif // _QX_BLOG_EXPORT_H_
|
||||
24
test/qxBlogCpp11/include/precompiled.h
Normal file
24
test/qxBlogCpp11/include/precompiled.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef _QX_BLOG_PRECOMPILED_HEADER_H_
|
||||
#define _QX_BLOG_PRECOMPILED_HEADER_H_
|
||||
|
||||
#include <QxOrm.h>
|
||||
|
||||
#include "export.h"
|
||||
|
||||
/*
|
||||
// To resolve a problem with MSVC++ 2010 and MSVC++ 2012 (and later ?) :
|
||||
// These compilers provide a tuple header but BOOST_NO_CXX11_HDR_TUPLE macro is defined !
|
||||
// This is because these compilers doesn't provide variadic templates
|
||||
#if (defined(_QX_CPP_11_TUPLE) && !defined(BOOST_NO_CXX11_HDR_TUPLE))
|
||||
#define QX_TUPLE std::tuple
|
||||
#define QX_TUPLE_GET std::get
|
||||
#else // (defined(_QX_CPP_11_TUPLE) && !defined(BOOST_NO_CXX11_HDR_TUPLE))
|
||||
#define QX_TUPLE boost::tuple
|
||||
#define QX_TUPLE_GET boost::tuples::get
|
||||
#endif // (defined(_QX_CPP_11_TUPLE) && !defined(BOOST_NO_CXX11_HDR_TUPLE))
|
||||
*/
|
||||
|
||||
#define QX_TUPLE std::tuple
|
||||
#define QX_TUPLE_GET std::get
|
||||
|
||||
#endif // _QX_BLOG_PRECOMPILED_HEADER_H_
|
||||
7
test/qxBlogCpp11/qt/moc/.gitignore
vendored
Normal file
7
test/qxBlogCpp11/qt/moc/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# git does not allow empty directories.
|
||||
# Yet, we need to add this empty directory on git.
|
||||
# To achieve that, we created this .gitignore file, so that the directory will not be empty thus enabling us to commit it.
|
||||
# Since we want all generated files/folders in this directory to be ignored by git, we add a rule for this.
|
||||
*
|
||||
# And then add an exception for this specifc file (so that we can commit it).
|
||||
!.gitignore
|
||||
36
test/qxBlogCpp11/qxBlog.pro
Normal file
36
test/qxBlogCpp11/qxBlog.pro
Normal file
@@ -0,0 +1,36 @@
|
||||
include(../../QxOrm.pri)
|
||||
|
||||
TEMPLATE = app
|
||||
DEFINES += _BUILDING_QX_BLOG
|
||||
INCLUDEPATH += ../../../QxOrm/include/
|
||||
DESTDIR = ../../../QxOrm/test/_bin/
|
||||
LIBS += -L"../../../QxOrm/lib"
|
||||
|
||||
!contains(DEFINES, _QX_NO_PRECOMPILED_HEADER) {
|
||||
PRECOMPILED_HEADER = ./include/precompiled.h
|
||||
} # !contains(DEFINES, _QX_NO_PRECOMPILED_HEADER)
|
||||
|
||||
CONFIG += c++11
|
||||
|
||||
macx:CONFIG-=app_bundle
|
||||
|
||||
CONFIG(debug, debug|release) {
|
||||
TARGET = qxBlogCpp11d
|
||||
LIBS += -l"QxOrmd"
|
||||
} else {
|
||||
TARGET = qxBlogCpp11
|
||||
LIBS += -l"QxOrm"
|
||||
} # CONFIG(debug, debug|release)
|
||||
|
||||
HEADERS += ./include/precompiled.h
|
||||
HEADERS += ./include/export.h
|
||||
HEADERS += ./include/author.h
|
||||
HEADERS += ./include/blog.h
|
||||
HEADERS += ./include/category.h
|
||||
HEADERS += ./include/comment.h
|
||||
|
||||
SOURCES += ./src/author.cpp
|
||||
SOURCES += ./src/blog.cpp
|
||||
SOURCES += ./src/category.cpp
|
||||
SOURCES += ./src/comment.cpp
|
||||
SOURCES += ./src/main.cpp
|
||||
7
test/qxBlogCpp11/release/.gitignore
vendored
Normal file
7
test/qxBlogCpp11/release/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# git does not allow empty directories.
|
||||
# Yet, we need to add this empty directory on git.
|
||||
# To achieve that, we created this .gitignore file, so that the directory will not be empty thus enabling us to commit it.
|
||||
# Since we want all generated files/folders in this directory to be ignored by git, we add a rule for this.
|
||||
*
|
||||
# And then add an exception for this specifc file (so that we can commit it).
|
||||
!.gitignore
|
||||
28
test/qxBlogCpp11/src/author.cpp
Normal file
28
test/qxBlogCpp11/src/author.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#include "../include/precompiled.h"
|
||||
|
||||
#include "../include/author.h"
|
||||
#include "../include/blog.h"
|
||||
|
||||
#include <QxOrm_Impl.h>
|
||||
|
||||
QX_REGISTER_CPP_QX_BLOG(author)
|
||||
|
||||
namespace qx {
|
||||
template <> void register_class(QxClass<author> & t)
|
||||
{
|
||||
t.id(& author::m_id, author::str_composite_key());
|
||||
|
||||
t.data(& author::m_name, "name");
|
||||
t.data(& author::m_birthdate, "birthdate");
|
||||
t.data(& author::m_sex, "sex");
|
||||
|
||||
t.relationOneToMany(& author::m_blogX, blog::str_composite_key(), author::str_composite_key());
|
||||
|
||||
t.fct_0<int>(std::mem_fn(& author::age), "age"); // using std::mem_fn() here is just a workaround for an issue with some versions of MSVC, it is not required with a full compliant C++11 compiler (http://stackoverflow.com/questions/23778883/vs2013-stdfunction-with-member-function)
|
||||
}}
|
||||
|
||||
int author::age() const
|
||||
{
|
||||
if (! m_birthdate.isValid()) { return -1; }
|
||||
return (QDate::currentDate().year() - m_birthdate.year());
|
||||
}
|
||||
20
test/qxBlogCpp11/src/blog.cpp
Normal file
20
test/qxBlogCpp11/src/blog.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "../include/precompiled.h"
|
||||
|
||||
#include "../include/blog.h"
|
||||
|
||||
#include <QxOrm_Impl.h>
|
||||
|
||||
QX_REGISTER_CPP_QX_BLOG(blog)
|
||||
|
||||
namespace qx {
|
||||
template <> void register_class(QxClass<blog> & t)
|
||||
{
|
||||
t.id(& blog::m_id, blog::str_composite_key());
|
||||
|
||||
t.data(& blog::m_text, "blog_text");
|
||||
t.data(& blog::m_dt_creation, "date_creation");
|
||||
|
||||
t.relationManyToOne(& blog::m_author, author::str_composite_key());
|
||||
t.relationOneToMany(& blog::m_commentX, comment::str_composite_key(), blog::str_composite_key());
|
||||
t.relationManyToMany(& blog::m_categoryX, "list_category", "category_blog", blog::str_composite_key(), category::str_composite_key());
|
||||
}}
|
||||
19
test/qxBlogCpp11/src/category.cpp
Normal file
19
test/qxBlogCpp11/src/category.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "../include/precompiled.h"
|
||||
|
||||
#include "../include/category.h"
|
||||
#include "../include/blog.h"
|
||||
|
||||
#include <QxOrm_Impl.h>
|
||||
|
||||
QX_REGISTER_CPP_QX_BLOG(category)
|
||||
|
||||
namespace qx {
|
||||
template <> void register_class(QxClass<category> & t)
|
||||
{
|
||||
t.id(& category::m_id, category::str_composite_key());
|
||||
|
||||
t.data(& category::m_name, "name");
|
||||
t.data(& category::m_desc, "description");
|
||||
|
||||
t.relationManyToMany(& category::m_blogX, "list_blog", "category_blog", category::str_composite_key(), blog::str_composite_key());
|
||||
}}
|
||||
19
test/qxBlogCpp11/src/comment.cpp
Normal file
19
test/qxBlogCpp11/src/comment.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "../include/precompiled.h"
|
||||
|
||||
#include "../include/comment.h"
|
||||
#include "../include/blog.h"
|
||||
|
||||
#include <QxOrm_Impl.h>
|
||||
|
||||
QX_REGISTER_CPP_QX_BLOG(comment)
|
||||
|
||||
namespace qx {
|
||||
template <> void register_class(QxClass<comment> & t)
|
||||
{
|
||||
t.id(& comment::m_id, comment::str_composite_key());
|
||||
|
||||
t.data(& comment::m_text, "comment_text");
|
||||
t.data(& comment::m_dt_create, "date_creation");
|
||||
|
||||
t.relationManyToOne(& comment::m_blog, blog::str_composite_key());
|
||||
}}
|
||||
209
test/qxBlogCpp11/src/main.cpp
Normal file
209
test/qxBlogCpp11/src/main.cpp
Normal file
@@ -0,0 +1,209 @@
|
||||
#include "../include/precompiled.h"
|
||||
|
||||
#include <QtCore/qcoreapplication.h>
|
||||
|
||||
#include "../include/blog.h"
|
||||
#include "../include/author.h"
|
||||
#include "../include/comment.h"
|
||||
#include "../include/category.h"
|
||||
|
||||
#include <QxOrm_Impl.h>
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
// Qt application
|
||||
QCoreApplication app(argc, argv);
|
||||
QFile::remove("./qxBlogCpp11.sqlite");
|
||||
|
||||
// Parameters to connect to database
|
||||
qx::QxSqlDatabase::getSingleton()->setDriverName("QSQLITE");
|
||||
qx::QxSqlDatabase::getSingleton()->setDatabaseName("./qxBlogCpp11.sqlite");
|
||||
qx::QxSqlDatabase::getSingleton()->setHostName("localhost");
|
||||
qx::QxSqlDatabase::getSingleton()->setUserName("root");
|
||||
qx::QxSqlDatabase::getSingleton()->setPassword("");
|
||||
|
||||
// Only for debug purpose : assert if invalid offset detected fetching a relation
|
||||
qx::QxSqlDatabase::getSingleton()->setVerifyOffsetRelation(true);
|
||||
|
||||
// Create all tables in database
|
||||
QSqlError daoError = qx::dao::create_table<author>();
|
||||
daoError = qx::dao::create_table<comment>();
|
||||
daoError = qx::dao::create_table<category>();
|
||||
daoError = qx::dao::create_table<blog>();
|
||||
|
||||
// Create a list of 3 author
|
||||
author_ptr author_1; author_1.reset(new author());
|
||||
author_ptr author_2; author_2.reset(new author());
|
||||
author_ptr author_3; author_3.reset(new author());
|
||||
|
||||
author_1->setId_0("_111_"); author_1->setId_1(100); author_1->setId_2("1_1");
|
||||
author_1->m_name = "author_1"; author_1->m_sex = author::male; author_1->m_birthdate = QDate::currentDate();
|
||||
author_2->setId_0("_222_"); author_2->setId_1(200); author_2->setId_2("2_2");
|
||||
author_2->m_name = "author_2"; author_2->m_sex = author::female; author_2->m_birthdate = QDate::currentDate();
|
||||
author_3->setId_0("_333_"); author_3->setId_1(300); author_3->setId_2("3_3");
|
||||
author_3->m_name = "author_3"; author_3->m_sex = author::female; author_3->m_birthdate = QDate::currentDate();
|
||||
|
||||
list_author authorX;
|
||||
authorX.insert(author_1->getId(), author_1);
|
||||
authorX.insert(author_2->getId(), author_2);
|
||||
authorX.insert(author_3->getId(), author_3);
|
||||
|
||||
// Insert list of 3 author into database
|
||||
daoError = qx::dao::insert(authorX);
|
||||
qAssert(qx::dao::count<author>() == 3);
|
||||
|
||||
// Clone author 2 : 'author_id_2'
|
||||
author_ptr author_clone = qx::clone_to_std_shared_ptr(* author_2);
|
||||
qAssert(author_clone->getId() == author::type_composite_key("_222_", 200, "2_2"));
|
||||
qAssert(author_clone->m_sex == author::female);
|
||||
|
||||
// Create a query to fetch only female author : 'author_id_2' and 'author_id_3'
|
||||
qx::QxSqlQuery query("WHERE author.sex = :sex");
|
||||
query.bind(":sex", author::female);
|
||||
|
||||
list_author list_of_female_author;
|
||||
daoError = qx::dao::fetch_by_query(query, list_of_female_author);
|
||||
qAssert(list_of_female_author.count() == 2);
|
||||
|
||||
// Dump list of female author (xml serialization)
|
||||
qx::dump(list_of_female_author);
|
||||
|
||||
// Create 3 categories
|
||||
category_ptr category_1 = category_ptr(new category());
|
||||
category_ptr category_2 = category_ptr(new category());
|
||||
category_ptr category_3 = category_ptr(new category());
|
||||
|
||||
category_1->setId_0("101"); category_1->setId_1(10);
|
||||
category_1->setId_2("__11_XX"); category_1->setId_3(10010);
|
||||
category_1->m_name = "category_1"; category_1->m_desc = "desc_1";
|
||||
category_2->setId_0("202"); category_2->setId_1(20);
|
||||
category_2->setId_2("__22_XX"); category_2->setId_3(20020);
|
||||
category_2->m_name = "category_2"; category_2->m_desc = "desc_2";
|
||||
category_3->setId_0("303"); category_3->setId_1(30);
|
||||
category_3->setId_2("__33_XX"); category_3->setId_3(30030);
|
||||
category_3->m_name = "category_3"; category_3->m_desc = "desc_3";
|
||||
|
||||
{ // Create a scope to destroy temporary connexion to database
|
||||
|
||||
// Open a transaction to database
|
||||
QSqlDatabase db = qx::QxSqlDatabase::getDatabase();
|
||||
bool bCommit = db.transaction();
|
||||
|
||||
// Insert 3 categories into database, use 'db' parameter for the transaction
|
||||
daoError = qx::dao::insert(category_1, (& db)); bCommit = (bCommit && ! daoError.isValid());
|
||||
daoError = qx::dao::insert(category_2, (& db)); bCommit = (bCommit && ! daoError.isValid());
|
||||
daoError = qx::dao::insert(category_3, (& db)); bCommit = (bCommit && ! daoError.isValid());
|
||||
|
||||
qAssert(bCommit);
|
||||
qAssert(category_1->getId() == category::type_composite_key("101", 10, "__11_XX", 10010));
|
||||
qAssert(category_2->getId() == category::type_composite_key("202", 20, "__22_XX", 20020));
|
||||
qAssert(category_3->getId() == category::type_composite_key("303", 30, "__33_XX", 30030));
|
||||
|
||||
// Terminate transaction => commit or rollback if there is error
|
||||
if (bCommit) { db.commit(); }
|
||||
else { db.rollback(); }
|
||||
|
||||
} // End of scope : 'db' is destroyed
|
||||
|
||||
// Create a blog with the class name (factory)
|
||||
qx::any blog_any = qx::create("blog");
|
||||
blog_ptr blog_1;
|
||||
try { blog_1 = qx::any_cast<blog_ptr>(blog_any); }
|
||||
catch (...) { blog_1.reset(new blog()); }
|
||||
blog_1->setId_0(1);
|
||||
blog_1->setId_1("blog 1");
|
||||
blog_1->m_text = "blog_text_1";
|
||||
blog_1->m_dt_creation = QDateTime::currentDateTime();
|
||||
blog_1->m_author = author_1;
|
||||
|
||||
// Insert 'blog_1' into database with 'save()' method
|
||||
daoError = qx::dao::save(blog_1);
|
||||
|
||||
// Modify 'blog_1' properties and save into database
|
||||
blog_1->m_text = "update blog_text_1";
|
||||
blog_1->m_author = author_2;
|
||||
daoError = qx::dao::save(blog_1);
|
||||
|
||||
// Add 2 comments to 'blog_1'
|
||||
comment_ptr comment_1; comment_1.reset(new comment());
|
||||
comment_ptr comment_2; comment_2.reset(new comment());
|
||||
|
||||
comment_1->setId_0(1);
|
||||
comment_1->setId_1("comment 1");
|
||||
comment_1->m_text = "comment_1 text";
|
||||
comment_1->m_dt_create = QDateTime::currentDateTime();
|
||||
comment_1->m_blog = blog_1;
|
||||
comment_2->setId_0(2);
|
||||
comment_2->setId_1("comment 2");
|
||||
comment_2->m_text = "comment_2 text";
|
||||
comment_2->m_dt_create = QDateTime::currentDateTime();
|
||||
comment_2->m_blog = blog_1;
|
||||
|
||||
daoError = qx::dao::insert(comment_1);
|
||||
daoError = qx::dao::insert(comment_2);
|
||||
qAssert(! daoError.isValid() && (qx::dao::count<comment>() == 2));
|
||||
|
||||
// Add 2 categories to 'blog_1' => must insert into extra-table 'category_blog'
|
||||
blog_1->m_categoryX.insert(category_1->getId(), category_1);
|
||||
blog_1->m_categoryX.insert(category_3->getId(), category_3);
|
||||
daoError = qx::dao::save_with_relation("list_category", blog_1);
|
||||
|
||||
// Fetch blog into a new variable with all relation : 'author', 'comment' and 'category'
|
||||
blog_ptr blog_tmp; blog_tmp.reset(new blog());
|
||||
blog_tmp->setId_0(blog_1->getId_0());
|
||||
blog_tmp->setId_1(blog_1->getId_1());
|
||||
daoError = qx::dao::fetch_by_id_with_all_relation(blog_tmp);
|
||||
|
||||
qAssert(! daoError.isValid());
|
||||
qAssert(blog_tmp->m_commentX.count() == 2);
|
||||
qAssert(blog_tmp->m_categoryX.count() == 2);
|
||||
qAssert(blog_tmp->m_text == "update blog_text_1");
|
||||
qAssert(blog_tmp->m_author && blog_tmp->m_author->getId() == author::type_composite_key("_222_", 200, "2_2"));
|
||||
|
||||
// Dump 'blog_tmp' result from database (xml serialization)
|
||||
qx::dump(blog_tmp);
|
||||
|
||||
// Call 'age()' method with class name and method name (reflexion)
|
||||
qx_bool bInvokeOk = qx::QxClassX::invoke("author", "age", author_1);
|
||||
qAssert(bInvokeOk);
|
||||
|
||||
// Test 'isDirty()' method
|
||||
qx::dao::ptr<blog> blog_isdirty = qx::dao::ptr<blog>(new blog());
|
||||
blog_isdirty->setId_0(blog_1->getId_0());
|
||||
blog_isdirty->setId_1(blog_1->getId_1());
|
||||
daoError = qx::dao::fetch_by_id(blog_isdirty);
|
||||
qAssert(! daoError.isValid() && ! blog_isdirty.isDirty());
|
||||
|
||||
blog_isdirty->m_text = "blog property 'text' modified => blog is dirty !!!";
|
||||
QStringList lstDiff; bool bDirty = blog_isdirty.isDirty(lstDiff);
|
||||
qAssert(bDirty && (lstDiff.count() == 1) && (lstDiff.at(0) == "blog_text"));
|
||||
if (bDirty) { qDebug("[QxOrm] test dirty 1 : blog is dirty => '%s'", qPrintable(lstDiff.join("|"))); }
|
||||
|
||||
daoError = qx::dao::update(blog_isdirty);
|
||||
qAssert(! daoError.isValid() && ! blog_isdirty.isDirty());
|
||||
qx::dump(blog_isdirty);
|
||||
|
||||
// Test 'isDirty()' method with a container
|
||||
typedef qx::dao::ptr< QList<author_ptr> > type_lst_author_test_is_dirty;
|
||||
type_lst_author_test_is_dirty container_isdirty = type_lst_author_test_is_dirty(new QList<author_ptr>());
|
||||
daoError = qx::dao::fetch_all(container_isdirty);
|
||||
qAssert(! daoError.isValid() && ! container_isdirty.isDirty() && (container_isdirty->count() == 3));
|
||||
|
||||
author_ptr author_ptr_dirty = container_isdirty->at(1);
|
||||
author_ptr_dirty->m_name = "author name modified at index 1 => container is dirty !!!";
|
||||
bDirty = container_isdirty.isDirty(lstDiff);
|
||||
qAssert(bDirty && (lstDiff.count() == 1));
|
||||
if (bDirty) { qDebug("[QxOrm] test dirty 2 : container is dirty => '%s'", qPrintable(lstDiff.join("|"))); }
|
||||
|
||||
author_ptr_dirty = container_isdirty->at(2);
|
||||
author_ptr_dirty->m_birthdate = QDate(1998, 03, 06);
|
||||
bDirty = container_isdirty.isDirty(lstDiff);
|
||||
qAssert(bDirty && (lstDiff.count() == 2));
|
||||
if (bDirty) { qDebug("[QxOrm] test dirty 3 : container is dirty => '%s'", qPrintable(lstDiff.join("|"))); }
|
||||
|
||||
daoError = qx::dao::save(container_isdirty);
|
||||
qAssert(! daoError.isValid() && ! container_isdirty.isDirty());
|
||||
qx::dump(container_isdirty);
|
||||
|
||||
return 0;
|
||||
}
|
||||
76
test/qxBlogModelView/CMakeLists.txt
Normal file
76
test/qxBlogModelView/CMakeLists.txt
Normal file
@@ -0,0 +1,76 @@
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
project(qxBlogModelView LANGUAGES CXX)
|
||||
|
||||
include(../../QxOrm.cmake)
|
||||
|
||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Sql Gui Widgets Quick Qml REQUIRED)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
set(CMAKE_DEBUG_POSTFIX "d")
|
||||
|
||||
set(HEADERS
|
||||
./include/precompiled.h
|
||||
./include/export.h
|
||||
./include/author.h
|
||||
./include/blog.h
|
||||
./include/category.h
|
||||
./include/comment.h
|
||||
./include/model_view_from_qxee/author.model_view.gen.h
|
||||
./include/model_view_from_qxee/blog.model_view.gen.h
|
||||
./include/model_view_from_qxee/category.model_view.gen.h
|
||||
./include/model_view_from_qxee/comment.model_view.gen.h
|
||||
)
|
||||
|
||||
set(SRCS
|
||||
./src/author.cpp
|
||||
./src/blog.cpp
|
||||
./src/category.cpp
|
||||
./src/comment.cpp
|
||||
./src/main.cpp
|
||||
./src/model_view_from_qxee/author.model_view.gen.cpp
|
||||
./src/model_view_from_qxee/blog.model_view.gen.cpp
|
||||
./src/model_view_from_qxee/category.model_view.gen.cpp
|
||||
./src/model_view_from_qxee/comment.model_view.gen.cpp
|
||||
)
|
||||
|
||||
set(QRCS
|
||||
./qt/rcc/qxBlogModelView.qrc
|
||||
)
|
||||
|
||||
if(COMMAND qt_add_resources)
|
||||
qt_add_resources(QRCS_HDRS ${QRCS})
|
||||
else() # (COMMAND qt_add_resources)
|
||||
qt5_add_resources(QRCS_HDRS ${QRCS})
|
||||
endif() # (COMMAND qt_add_resources)
|
||||
|
||||
add_executable(qxBlogModelView ${SRCS} ${HEADERS} ${QRCS_HDRS})
|
||||
|
||||
target_compile_definitions(qxBlogModelView PRIVATE -D_BUILDING_QX_BLOG)
|
||||
|
||||
if(COMMAND target_precompile_headers)
|
||||
target_precompile_headers(qxBlogModelView PRIVATE ./include/precompiled.h)
|
||||
endif() # (COMMAND target_precompile_headers)
|
||||
|
||||
target_link_libraries(qxBlogModelView ${QX_LIBRARIES} QxOrm Qt${QT_VERSION_MAJOR}::Gui Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Quick Qt${QT_VERSION_MAJOR}::Qml)
|
||||
|
||||
set_target_properties(qxBlogModelView PROPERTIES
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
ARCHIVE_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
)
|
||||
|
||||
set_target_properties(qxBlogModelView PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
|
||||
7
test/qxBlogModelView/debug/.gitignore
vendored
Normal file
7
test/qxBlogModelView/debug/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# git does not allow empty directories.
|
||||
# Yet, we need to add this empty directory on git.
|
||||
# To achieve that, we created this .gitignore file, so that the directory will not be empty thus enabling us to commit it.
|
||||
# Since we want all generated files/folders in this directory to be ignored by git, we add a rule for this.
|
||||
*
|
||||
# And then add an exception for this specifc file (so that we can commit it).
|
||||
!.gitignore
|
||||
49
test/qxBlogModelView/include/author.h
Normal file
49
test/qxBlogModelView/include/author.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#ifndef _QX_BLOG_AUTHOR_H_
|
||||
#define _QX_BLOG_AUTHOR_H_
|
||||
|
||||
class blog;
|
||||
|
||||
class QX_BLOG_DLL_EXPORT author
|
||||
{
|
||||
public:
|
||||
// -- typedef
|
||||
typedef std::shared_ptr<blog> blog_ptr;
|
||||
typedef std::vector<blog_ptr> list_blog;
|
||||
typedef std::vector<blog_ptr> type_list_of_blog;
|
||||
// -- enum
|
||||
enum enum_sex { male, female, unknown };
|
||||
// -- properties
|
||||
QString m_id;
|
||||
QString m_name;
|
||||
QDate m_birthdate;
|
||||
enum_sex m_sex;
|
||||
list_blog m_blogX;
|
||||
// -- contructor, virtual destructor
|
||||
author() : m_id("0"), m_sex(unknown) { ; }
|
||||
virtual ~author() { ; }
|
||||
// -- methods
|
||||
int age() const;
|
||||
|
||||
QString getauthor_id() const;
|
||||
QString getname() const;
|
||||
QDate getbirthdate() const;
|
||||
enum_sex getsex() const;
|
||||
type_list_of_blog getlist_of_blog() const;
|
||||
type_list_of_blog & list_of_blog();
|
||||
const type_list_of_blog & list_of_blog() const;
|
||||
|
||||
void setauthor_id(const QString & val);
|
||||
void setname(const QString & val);
|
||||
void setbirthdate(const QDate & val);
|
||||
void setsex(const enum_sex & val);
|
||||
void setlist_of_blog(const type_list_of_blog & val);
|
||||
|
||||
};
|
||||
|
||||
QX_REGISTER_PRIMARY_KEY(author, QString)
|
||||
QX_REGISTER_HPP_QX_BLOG(author, qx::trait::no_base_class_defined, 0)
|
||||
|
||||
typedef std::shared_ptr<author> author_ptr;
|
||||
typedef qx::QxCollection<QString, author_ptr> list_author;
|
||||
|
||||
#endif // _QX_BLOG_AUTHOR_H_
|
||||
53
test/qxBlogModelView/include/blog.h
Normal file
53
test/qxBlogModelView/include/blog.h
Normal file
@@ -0,0 +1,53 @@
|
||||
#ifndef _QX_BLOG_BLOG_H_
|
||||
#define _QX_BLOG_BLOG_H_
|
||||
|
||||
#include "author.h"
|
||||
#include "comment.h"
|
||||
#include "category.h"
|
||||
|
||||
class QX_BLOG_DLL_EXPORT blog
|
||||
{
|
||||
public:
|
||||
|
||||
typedef std::shared_ptr<author> type_author;
|
||||
typedef QList<comment_ptr> type_list_of_comment;
|
||||
typedef qx::QxCollection<long, category_ptr> type_list_of_category;
|
||||
|
||||
// -- properties
|
||||
long m_id;
|
||||
QString m_title;
|
||||
QString m_text;
|
||||
QDateTime m_dt_creation;
|
||||
author_ptr m_author;
|
||||
list_comment m_commentX;
|
||||
list_category m_categoryX;
|
||||
// -- contructor, virtual destructor
|
||||
blog() : m_id(0) { ; }
|
||||
virtual ~blog() { ; }
|
||||
|
||||
long getblog_id() const;
|
||||
QString gettitle() const;
|
||||
QString gettext() const;
|
||||
type_author getauthor() const;
|
||||
type_list_of_comment getlist_of_comment() const;
|
||||
type_list_of_comment & list_of_comment();
|
||||
const type_list_of_comment & list_of_comment() const;
|
||||
type_list_of_category getlist_of_category() const;
|
||||
type_list_of_category & list_of_category();
|
||||
const type_list_of_category & list_of_category() const;
|
||||
|
||||
void setblog_id(const long & val);
|
||||
void settitle(const QString & val);
|
||||
void settext(const QString & val);
|
||||
void setauthor(const type_author & val);
|
||||
void setlist_of_comment(const type_list_of_comment & val);
|
||||
void setlist_of_category(const type_list_of_category & val);
|
||||
|
||||
};
|
||||
|
||||
QX_REGISTER_HPP_QX_BLOG(blog, qx::trait::no_base_class_defined, 0)
|
||||
|
||||
typedef std::shared_ptr<blog> blog_ptr;
|
||||
typedef std::vector<blog_ptr> list_blog;
|
||||
|
||||
#endif // _QX_BLOG_BLOG_H_
|
||||
41
test/qxBlogModelView/include/category.h
Normal file
41
test/qxBlogModelView/include/category.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef _QX_BLOG_CATEGORY_H_
|
||||
#define _QX_BLOG_CATEGORY_H_
|
||||
|
||||
class blog;
|
||||
|
||||
class QX_BLOG_DLL_EXPORT category
|
||||
{
|
||||
public:
|
||||
// -- typedef
|
||||
typedef std::shared_ptr<blog> blog_ptr;
|
||||
typedef qx::QxCollection<long, blog_ptr> list_blog;
|
||||
typedef qx::QxCollection<long, blog_ptr> type_list_of_blog;
|
||||
// -- properties
|
||||
long m_id;
|
||||
QString m_name;
|
||||
QString m_desc;
|
||||
list_blog m_blogX;
|
||||
// -- contructor, virtual destructor
|
||||
category() : m_id(0) { ; }
|
||||
virtual ~category() { ; }
|
||||
|
||||
long getcategory_id() const;
|
||||
QString getname() const;
|
||||
QString getdescription() const;
|
||||
type_list_of_blog getlist_of_blog() const;
|
||||
type_list_of_blog & list_of_blog();
|
||||
const type_list_of_blog & list_of_blog() const;
|
||||
|
||||
void setcategory_id(const long & val);
|
||||
void setname(const QString & val);
|
||||
void setdescription(const QString & val);
|
||||
void setlist_of_blog(const type_list_of_blog & val);
|
||||
|
||||
};
|
||||
|
||||
QX_REGISTER_HPP_QX_BLOG(category, qx::trait::no_base_class_defined, 0)
|
||||
|
||||
typedef QSharedPointer<category> category_ptr;
|
||||
typedef qx::QxCollection<long, category_ptr> list_category;
|
||||
|
||||
#endif // _QX_BLOG_CATEGORY_H_
|
||||
39
test/qxBlogModelView/include/comment.h
Normal file
39
test/qxBlogModelView/include/comment.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef _QX_BLOG_COMMENT_H_
|
||||
#define _QX_BLOG_COMMENT_H_
|
||||
|
||||
class blog;
|
||||
|
||||
class QX_BLOG_DLL_EXPORT comment
|
||||
{
|
||||
public:
|
||||
// -- typedef
|
||||
typedef std::shared_ptr<blog> blog_ptr;
|
||||
typedef std::shared_ptr<blog> type_blog_id;
|
||||
// -- properties
|
||||
long m_id;
|
||||
QString m_title;
|
||||
QString m_text;
|
||||
QDateTime m_dt_create;
|
||||
blog_ptr m_blog;
|
||||
// -- contructor, virtual destructor
|
||||
comment() : m_id(0) { ; }
|
||||
virtual ~comment() { ; }
|
||||
|
||||
long getcomment_id() const;
|
||||
QString gettitle() const;
|
||||
QString gettext() const;
|
||||
type_blog_id getblog_id() const;
|
||||
|
||||
void setcomment_id(const long & val);
|
||||
void settitle(const QString & val);
|
||||
void settext(const QString & val);
|
||||
void setblog_id(const type_blog_id & val);
|
||||
|
||||
};
|
||||
|
||||
QX_REGISTER_HPP_QX_BLOG(comment, qx::trait::no_base_class_defined, 0)
|
||||
|
||||
typedef std::shared_ptr<comment> comment_ptr;
|
||||
typedef QList<comment_ptr> list_comment;
|
||||
|
||||
#endif // _QX_BLOG_COMMENT_H_
|
||||
18
test/qxBlogModelView/include/export.h
Normal file
18
test/qxBlogModelView/include/export.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef _QX_BLOG_EXPORT_H_
|
||||
#define _QX_BLOG_EXPORT_H_
|
||||
|
||||
#ifdef _BUILDING_QX_BLOG
|
||||
#define QX_BLOG_DLL_EXPORT QX_DLL_EXPORT_HELPER
|
||||
#else // _BUILDING_QX_BLOG
|
||||
#define QX_BLOG_DLL_EXPORT QX_DLL_IMPORT_HELPER
|
||||
#endif // _BUILDING_QX_BLOG
|
||||
|
||||
#ifdef _BUILDING_QX_BLOG
|
||||
#define QX_REGISTER_HPP_QX_BLOG QX_REGISTER_HPP_EXPORT_DLL
|
||||
#define QX_REGISTER_CPP_QX_BLOG QX_REGISTER_CPP_EXPORT_DLL
|
||||
#else // _BUILDING_QX_BLOG
|
||||
#define QX_REGISTER_HPP_QX_BLOG QX_REGISTER_HPP_IMPORT_DLL
|
||||
#define QX_REGISTER_CPP_QX_BLOG QX_REGISTER_CPP_IMPORT_DLL
|
||||
#endif // _BUILDING_QX_BLOG
|
||||
|
||||
#endif // _QX_BLOG_EXPORT_H_
|
||||
@@ -0,0 +1,50 @@
|
||||
/************************************************************************************************
|
||||
** File created by QxEntityEditor 1.1.9 (2016/05/04 10:05) : please, do NOT modify this file ! **
|
||||
************************************************************************************************/
|
||||
|
||||
#ifndef _QXBLOG_AUTHOR_MODEL_VIEW_H_
|
||||
#define _QXBLOG_AUTHOR_MODEL_VIEW_H_
|
||||
|
||||
#ifdef _QX_NO_PRECOMPILED_HEADER
|
||||
#ifndef Q_MOC_RUN
|
||||
#include "../../include/precompiled.h" // Need to include precompiled header for the generated moc file
|
||||
#endif // Q_MOC_RUN
|
||||
#endif // _QX_NO_PRECOMPILED_HEADER
|
||||
|
||||
#include "../../include/author.h"
|
||||
|
||||
namespace model_view {
|
||||
|
||||
typedef qx::QxModel<author> author_model_base_class;
|
||||
|
||||
class QX_BLOG_DLL_EXPORT author_model : public author_model_base_class
|
||||
{
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
author_model(QObject * parent = 0);
|
||||
author_model(qx::IxModel * other, QObject * parent);
|
||||
virtual ~author_model();
|
||||
|
||||
Q_INVOKABLE QObject * list_of_blog(int row, bool bLoadFromDatabase = false, const QString & sAppendRelations = QString());
|
||||
|
||||
/* List of properties exposed by the model (5) :
|
||||
- author_id
|
||||
- firstname
|
||||
- lastname
|
||||
- birthdate
|
||||
- sex
|
||||
*/
|
||||
|
||||
protected:
|
||||
|
||||
virtual void syncNestedModel(int row, const QStringList & relation);
|
||||
virtual void syncAllNestedModel(const QStringList & relation);
|
||||
|
||||
};
|
||||
|
||||
} // namespace model_view
|
||||
|
||||
#endif // _QXBLOG_AUTHOR_MODEL_VIEW_H_
|
||||
@@ -0,0 +1,50 @@
|
||||
/************************************************************************************************
|
||||
** File created by QxEntityEditor 1.1.9 (2016/05/04 10:05) : please, do NOT modify this file ! **
|
||||
************************************************************************************************/
|
||||
|
||||
#ifndef _QXBLOG_BLOG_MODEL_VIEW_H_
|
||||
#define _QXBLOG_BLOG_MODEL_VIEW_H_
|
||||
|
||||
#ifdef _QX_NO_PRECOMPILED_HEADER
|
||||
#ifndef Q_MOC_RUN
|
||||
#include "../../include/precompiled.h" // Need to include precompiled header for the generated moc file
|
||||
#endif // Q_MOC_RUN
|
||||
#endif // _QX_NO_PRECOMPILED_HEADER
|
||||
|
||||
#include "../../include/blog.h"
|
||||
|
||||
namespace model_view {
|
||||
|
||||
typedef qx::QxModel<blog> blog_model_base_class;
|
||||
|
||||
class QX_BLOG_DLL_EXPORT blog_model : public blog_model_base_class
|
||||
{
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
blog_model(QObject * parent = 0);
|
||||
blog_model(qx::IxModel * other, QObject * parent);
|
||||
virtual ~blog_model();
|
||||
|
||||
Q_INVOKABLE QObject * author_id(int row, bool bLoadFromDatabase = false, const QString & sAppendRelations = QString());
|
||||
Q_INVOKABLE QObject * list_of_comment(int row, bool bLoadFromDatabase = false, const QString & sAppendRelations = QString());
|
||||
Q_INVOKABLE QObject * list_of_category(int row, bool bLoadFromDatabase = false, const QString & sAppendRelations = QString());
|
||||
|
||||
/* List of properties exposed by the model (3) :
|
||||
- blog_id
|
||||
- title
|
||||
- text
|
||||
*/
|
||||
|
||||
protected:
|
||||
|
||||
virtual void syncNestedModel(int row, const QStringList & relation);
|
||||
virtual void syncAllNestedModel(const QStringList & relation);
|
||||
|
||||
};
|
||||
|
||||
} // namespace model_view
|
||||
|
||||
#endif // _QXBLOG_BLOG_MODEL_VIEW_H_
|
||||
@@ -0,0 +1,48 @@
|
||||
/************************************************************************************************
|
||||
** File created by QxEntityEditor 1.1.9 (2016/05/04 10:05) : please, do NOT modify this file ! **
|
||||
************************************************************************************************/
|
||||
|
||||
#ifndef _QXBLOG_CATEGORY_MODEL_VIEW_H_
|
||||
#define _QXBLOG_CATEGORY_MODEL_VIEW_H_
|
||||
|
||||
#ifdef _QX_NO_PRECOMPILED_HEADER
|
||||
#ifndef Q_MOC_RUN
|
||||
#include "../../include/precompiled.h" // Need to include precompiled header for the generated moc file
|
||||
#endif // Q_MOC_RUN
|
||||
#endif // _QX_NO_PRECOMPILED_HEADER
|
||||
|
||||
#include "../../include/category.h"
|
||||
|
||||
namespace model_view {
|
||||
|
||||
typedef qx::QxModel<category> category_model_base_class;
|
||||
|
||||
class QX_BLOG_DLL_EXPORT category_model : public category_model_base_class
|
||||
{
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
category_model(QObject * parent = 0);
|
||||
category_model(qx::IxModel * other, QObject * parent);
|
||||
virtual ~category_model();
|
||||
|
||||
Q_INVOKABLE QObject * list_of_blog(int row, bool bLoadFromDatabase = false, const QString & sAppendRelations = QString());
|
||||
|
||||
/* List of properties exposed by the model (3) :
|
||||
- category_id
|
||||
- name
|
||||
- description
|
||||
*/
|
||||
|
||||
protected:
|
||||
|
||||
virtual void syncNestedModel(int row, const QStringList & relation);
|
||||
virtual void syncAllNestedModel(const QStringList & relation);
|
||||
|
||||
};
|
||||
|
||||
} // namespace model_view
|
||||
|
||||
#endif // _QXBLOG_CATEGORY_MODEL_VIEW_H_
|
||||
@@ -0,0 +1,48 @@
|
||||
/************************************************************************************************
|
||||
** File created by QxEntityEditor 1.1.9 (2016/05/04 10:05) : please, do NOT modify this file ! **
|
||||
************************************************************************************************/
|
||||
|
||||
#ifndef _QXBLOG_COMMENT_MODEL_VIEW_H_
|
||||
#define _QXBLOG_COMMENT_MODEL_VIEW_H_
|
||||
|
||||
#ifdef _QX_NO_PRECOMPILED_HEADER
|
||||
#ifndef Q_MOC_RUN
|
||||
#include "../../include/precompiled.h" // Need to include precompiled header for the generated moc file
|
||||
#endif // Q_MOC_RUN
|
||||
#endif // _QX_NO_PRECOMPILED_HEADER
|
||||
|
||||
#include "../../include/comment.h"
|
||||
|
||||
namespace model_view {
|
||||
|
||||
typedef qx::QxModel<comment> comment_model_base_class;
|
||||
|
||||
class QX_BLOG_DLL_EXPORT comment_model : public comment_model_base_class
|
||||
{
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
comment_model(QObject * parent = 0);
|
||||
comment_model(qx::IxModel * other, QObject * parent);
|
||||
virtual ~comment_model();
|
||||
|
||||
Q_INVOKABLE QObject * blog_id(int row, bool bLoadFromDatabase = false, const QString & sAppendRelations = QString());
|
||||
|
||||
/* List of properties exposed by the model (3) :
|
||||
- comment_id
|
||||
- title
|
||||
- text
|
||||
*/
|
||||
|
||||
protected:
|
||||
|
||||
virtual void syncNestedModel(int row, const QStringList & relation);
|
||||
virtual void syncAllNestedModel(const QStringList & relation);
|
||||
|
||||
};
|
||||
|
||||
} // namespace model_view
|
||||
|
||||
#endif // _QXBLOG_COMMENT_MODEL_VIEW_H_
|
||||
9
test/qxBlogModelView/include/precompiled.h
Normal file
9
test/qxBlogModelView/include/precompiled.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef _QX_BLOG_PRECOMPILED_HEADER_H_
|
||||
#define _QX_BLOG_PRECOMPILED_HEADER_H_
|
||||
|
||||
#include <QxOrm.h>
|
||||
#include <QxModelView.h>
|
||||
|
||||
#include "export.h"
|
||||
|
||||
#endif // _QX_BLOG_PRECOMPILED_HEADER_H_
|
||||
7
test/qxBlogModelView/qt/moc/.gitignore
vendored
Normal file
7
test/qxBlogModelView/qt/moc/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# git does not allow empty directories.
|
||||
# Yet, we need to add this empty directory on git.
|
||||
# To achieve that, we created this .gitignore file, so that the directory will not be empty thus enabling us to commit it.
|
||||
# Since we want all generated files/folders in this directory to be ignored by git, we add a rule for this.
|
||||
*
|
||||
# And then add an exception for this specifc file (so that we can commit it).
|
||||
!.gitignore
|
||||
37
test/qxBlogModelView/qt/rcc/documents/main.qml
Normal file
37
test/qxBlogModelView/qt/rcc/documents/main.qml
Normal file
@@ -0,0 +1,37 @@
|
||||
import QtQuick 2.1
|
||||
import QtQuick.Controls 1.0
|
||||
|
||||
Item {
|
||||
width: 400
|
||||
height: 300
|
||||
Row {
|
||||
height: 20
|
||||
spacing: 20
|
||||
Button {
|
||||
text: "Clear"
|
||||
onClicked: myModel.clear()
|
||||
}
|
||||
Button {
|
||||
text: "Fetch All"
|
||||
onClicked: myModel.qxFetchAll_()
|
||||
}
|
||||
Button {
|
||||
text: "Save"
|
||||
onClicked: myModel.qxSave_()
|
||||
}
|
||||
}
|
||||
ListView {
|
||||
y: 30
|
||||
height: 270
|
||||
model: myModel
|
||||
delegate: Row {
|
||||
height: 20
|
||||
spacing: 10
|
||||
Text { text: "id: " + author_id }
|
||||
TextField {
|
||||
text: name
|
||||
onTextChanged: name = text
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
16
test/qxBlogModelView/qt/rcc/documents/main_qt4.qml
Normal file
16
test/qxBlogModelView/qt/rcc/documents/main_qt4.qml
Normal file
@@ -0,0 +1,16 @@
|
||||
import QtQuick 1.0
|
||||
|
||||
Item {
|
||||
width: 400
|
||||
height: 300
|
||||
ListView {
|
||||
anchors.fill: parent
|
||||
model: myModel
|
||||
delegate: Row {
|
||||
height: 20
|
||||
spacing: 10
|
||||
Text { text: "id: " + author_id }
|
||||
Text { text: "name: " + name }
|
||||
}
|
||||
}
|
||||
}
|
||||
37
test/qxBlogModelView/qt/rcc/documents/main_qt6.qml
Normal file
37
test/qxBlogModelView/qt/rcc/documents/main_qt6.qml
Normal file
@@ -0,0 +1,37 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
|
||||
Item {
|
||||
width: 400
|
||||
height: 300
|
||||
Row {
|
||||
height: 20
|
||||
spacing: 20
|
||||
Button {
|
||||
text: "Clear"
|
||||
onClicked: myModel.clear()
|
||||
}
|
||||
Button {
|
||||
text: "Fetch All"
|
||||
onClicked: myModel.qxFetchAll_()
|
||||
}
|
||||
Button {
|
||||
text: "Save"
|
||||
onClicked: myModel.qxSave_()
|
||||
}
|
||||
}
|
||||
ListView {
|
||||
y: 30
|
||||
height: 270
|
||||
model: myModel
|
||||
delegate: Row {
|
||||
height: 20
|
||||
spacing: 10
|
||||
Text { text: "id: " + author_id }
|
||||
TextField {
|
||||
text: name
|
||||
onTextChanged: name = text
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
93
test/qxBlogModelView/qt/rcc/documents/main_relationship.qml
Normal file
93
test/qxBlogModelView/qt/rcc/documents/main_relationship.qml
Normal file
@@ -0,0 +1,93 @@
|
||||
import QtQuick 2.1
|
||||
import QtQuick.Controls 1.0
|
||||
|
||||
Item {
|
||||
width: 500
|
||||
height: 300
|
||||
|
||||
/*
|
||||
1- How to display a relationship value :
|
||||
* root model : blog
|
||||
* child model : author
|
||||
* display author name using getModelValue() method of qx::IxModel base class
|
||||
*/
|
||||
Text {
|
||||
y: 30
|
||||
color: "blue"
|
||||
text: "--- 1. display relationship author name using getModelValue() method of qx::IxModel base class ---"
|
||||
}
|
||||
ListView {
|
||||
y: 50
|
||||
height: 270
|
||||
model: myModel
|
||||
delegate: Row {
|
||||
height: 20
|
||||
spacing: 10
|
||||
Text { text: "blog id : " + blog_id }
|
||||
TextField {
|
||||
text: blog_text
|
||||
onTextChanged: blog_text = text
|
||||
}
|
||||
Text { text: "author name : " + myModel.author_id(0).getModelValue(0, "name") } // display author name using getModelValue() method of qx::IxModel base class
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
2- How to display a relationship value :
|
||||
* root model : blog
|
||||
* child model : author
|
||||
* display author name passing the author child model to another QML component, then using the role value
|
||||
*/
|
||||
Text {
|
||||
y: 80
|
||||
color: "blue"
|
||||
text: "--- 2. display relationship author name passing the author child model to another QML component, then using the author 'name' role value ---"
|
||||
}
|
||||
ListView {
|
||||
y: 100
|
||||
height: 270
|
||||
model: myModel
|
||||
delegate: Row {
|
||||
height: 20
|
||||
spacing: 10
|
||||
Text { text: "blog id : " + blog_id }
|
||||
TextField {
|
||||
text: blog_text
|
||||
onTextChanged: blog_text = text
|
||||
}
|
||||
ListView {
|
||||
x: 200
|
||||
height: 270
|
||||
model: myModel.author_id(0) // pass the author child model to another QML component
|
||||
delegate: Row {
|
||||
Text { text: "author name : " + name } // use role 'name' defined in author class to display the author name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
3- Display the author row id in database using the 'author_id' role defined in blog class
|
||||
*/
|
||||
Text {
|
||||
y: 130
|
||||
color: "blue"
|
||||
text: "--- 3. display the author row id in database using the 'author_id' role defined in blog class ---"
|
||||
}
|
||||
ListView {
|
||||
y: 150
|
||||
height: 270
|
||||
model: myModel
|
||||
delegate: Row {
|
||||
height: 20
|
||||
spacing: 10
|
||||
Text { text: "blog id : " + blog_id }
|
||||
TextField {
|
||||
text: blog_text
|
||||
onTextChanged: blog_text = text
|
||||
}
|
||||
Text { text: "author id : " + author_id }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
|
||||
Item {
|
||||
width: 500
|
||||
height: 300
|
||||
|
||||
/*
|
||||
1- How to display a relationship value :
|
||||
* root model : blog
|
||||
* child model : author
|
||||
* display author name using getModelValue() method of qx::IxModel base class
|
||||
*/
|
||||
Text {
|
||||
y: 30
|
||||
color: "blue"
|
||||
text: "--- 1. display relationship author name using getModelValue() method of qx::IxModel base class ---"
|
||||
}
|
||||
ListView {
|
||||
y: 50
|
||||
height: 270
|
||||
model: myModel
|
||||
delegate: Row {
|
||||
height: 20
|
||||
spacing: 10
|
||||
Text { text: "blog id : " + blog_id }
|
||||
TextField {
|
||||
text: blog_text
|
||||
onTextChanged: blog_text = text
|
||||
}
|
||||
Text { text: "author name : " + myModel.author_id(0).getModelValue(0, "name") } // display author name using getModelValue() method of qx::IxModel base class
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
2- How to display a relationship value :
|
||||
* root model : blog
|
||||
* child model : author
|
||||
* display author name passing the author child model to another QML component, then using the role value
|
||||
*/
|
||||
Text {
|
||||
y: 80
|
||||
color: "blue"
|
||||
text: "--- 2. display relationship author name passing the author child model to another QML component, then using the author 'name' role value ---"
|
||||
}
|
||||
ListView {
|
||||
y: 100
|
||||
height: 270
|
||||
model: myModel
|
||||
delegate: Row {
|
||||
height: 20
|
||||
spacing: 10
|
||||
Text { text: "blog id : " + blog_id }
|
||||
TextField {
|
||||
text: blog_text
|
||||
onTextChanged: blog_text = text
|
||||
}
|
||||
ListView {
|
||||
x: 200
|
||||
height: 270
|
||||
model: myModel.author_id(0) // pass the author child model to another QML component
|
||||
delegate: Row {
|
||||
Text { text: "author name : " + name } // use role 'name' defined in author class to display the author name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
3- Display the author row id in database using the 'author_id' role defined in blog class
|
||||
*/
|
||||
Text {
|
||||
y: 130
|
||||
color: "blue"
|
||||
text: "--- 3. display the author row id in database using the 'author_id' role defined in blog class ---"
|
||||
}
|
||||
ListView {
|
||||
y: 150
|
||||
height: 270
|
||||
model: myModel
|
||||
delegate: Row {
|
||||
height: 20
|
||||
spacing: 10
|
||||
Text { text: "blog id : " + blog_id }
|
||||
TextField {
|
||||
text: blog_text
|
||||
onTextChanged: blog_text = text
|
||||
}
|
||||
Text { text: "author id : " + author_id }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
7
test/qxBlogModelView/qt/rcc/images/.gitignore
vendored
Normal file
7
test/qxBlogModelView/qt/rcc/images/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# git does not allow empty directories.
|
||||
# Yet, we need to add this empty directory on git.
|
||||
# To achieve that, we created this .gitignore file, so that the directory will not be empty thus enabling us to commit it.
|
||||
# Since we want all generated files/folders in this directory to be ignored by git, we add a rule for this.
|
||||
*
|
||||
# And then add an exception for this specifc file (so that we can commit it).
|
||||
!.gitignore
|
||||
9
test/qxBlogModelView/qt/rcc/qxBlogModelView.qrc
Normal file
9
test/qxBlogModelView/qt/rcc/qxBlogModelView.qrc
Normal file
@@ -0,0 +1,9 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource>
|
||||
<file>documents/main.qml</file>
|
||||
<file>documents/main_qt4.qml</file>
|
||||
<file>documents/main_qt6.qml</file>
|
||||
<file>documents/main_relationship.qml</file>
|
||||
<file>documents/main_relationship_qt6.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
53
test/qxBlogModelView/qxBlog.pro
Normal file
53
test/qxBlogModelView/qxBlog.pro
Normal file
@@ -0,0 +1,53 @@
|
||||
include(../../QxOrm.pri)
|
||||
|
||||
TEMPLATE = app
|
||||
DEFINES += _BUILDING_QX_BLOG
|
||||
INCLUDEPATH += ../../../QxOrm/include/
|
||||
DESTDIR = ../../../QxOrm/test/_bin/
|
||||
LIBS += -L"../../../QxOrm/lib"
|
||||
QT += gui
|
||||
|
||||
!contains(DEFINES, _QX_NO_PRECOMPILED_HEADER) {
|
||||
PRECOMPILED_HEADER = ./include/precompiled.h
|
||||
} # !contains(DEFINES, _QX_NO_PRECOMPILED_HEADER)
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4) {
|
||||
QT += widgets
|
||||
QT += quick
|
||||
QT += qml
|
||||
} else {
|
||||
QT += declarative
|
||||
}
|
||||
|
||||
CONFIG(debug, debug|release) {
|
||||
TARGET = qxBlogModelViewd
|
||||
LIBS += -l"QxOrmd"
|
||||
} else {
|
||||
TARGET = qxBlogModelView
|
||||
LIBS += -l"QxOrm"
|
||||
} # CONFIG(debug, debug|release)
|
||||
|
||||
HEADERS += ./include/precompiled.h
|
||||
HEADERS += ./include/export.h
|
||||
HEADERS += ./include/author.h
|
||||
HEADERS += ./include/blog.h
|
||||
HEADERS += ./include/category.h
|
||||
HEADERS += ./include/comment.h
|
||||
|
||||
HEADERS += ./include/model_view_from_qxee/author.model_view.gen.h
|
||||
HEADERS += ./include/model_view_from_qxee/blog.model_view.gen.h
|
||||
HEADERS += ./include/model_view_from_qxee/category.model_view.gen.h
|
||||
HEADERS += ./include/model_view_from_qxee/comment.model_view.gen.h
|
||||
|
||||
SOURCES += ./src/author.cpp
|
||||
SOURCES += ./src/blog.cpp
|
||||
SOURCES += ./src/category.cpp
|
||||
SOURCES += ./src/comment.cpp
|
||||
SOURCES += ./src/main.cpp
|
||||
|
||||
SOURCES += ./src/model_view_from_qxee/author.model_view.gen.cpp
|
||||
SOURCES += ./src/model_view_from_qxee/blog.model_view.gen.cpp
|
||||
SOURCES += ./src/model_view_from_qxee/category.model_view.gen.cpp
|
||||
SOURCES += ./src/model_view_from_qxee/comment.model_view.gen.cpp
|
||||
|
||||
RESOURCES += ./qt/rcc/qxBlogModelView.qrc
|
||||
7
test/qxBlogModelView/release/.gitignore
vendored
Normal file
7
test/qxBlogModelView/release/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# git does not allow empty directories.
|
||||
# Yet, we need to add this empty directory on git.
|
||||
# To achieve that, we created this .gitignore file, so that the directory will not be empty thus enabling us to commit it.
|
||||
# Since we want all generated files/folders in this directory to be ignored by git, we add a rule for this.
|
||||
*
|
||||
# And then add an exception for this specifc file (so that we can commit it).
|
||||
!.gitignore
|
||||
52
test/qxBlogModelView/src/author.cpp
Normal file
52
test/qxBlogModelView/src/author.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#include "../include/precompiled.h"
|
||||
|
||||
#include "../include/author.h"
|
||||
#include "../include/blog.h"
|
||||
|
||||
#include <QxOrm_Impl.h>
|
||||
|
||||
QX_REGISTER_CPP_QX_BLOG(author)
|
||||
|
||||
namespace qx {
|
||||
template <> void register_class(QxClass<author> & t)
|
||||
{
|
||||
t.id(& author::m_id, "author_id");
|
||||
|
||||
t.data(& author::m_name, "name");
|
||||
t.data(& author::m_birthdate, "birthdate");
|
||||
t.data(& author::m_sex, "sex");
|
||||
|
||||
t.relationOneToMany(& author::m_blogX, "list_blog", "author_id");
|
||||
|
||||
t.fct_0<int>(std::mem_fn(& author::age), "age"); // using std::mem_fn() here is just a workaround for an issue with some versions of MSVC, it is not required with a full compliant C++11 compiler (http://stackoverflow.com/questions/23778883/vs2013-stdfunction-with-member-function)
|
||||
}}
|
||||
|
||||
int author::age() const
|
||||
{
|
||||
if (! m_birthdate.isValid()) { return -1; }
|
||||
return (QDate::currentDate().year() - m_birthdate.year());
|
||||
}
|
||||
|
||||
QString author::getauthor_id() const { return m_id; }
|
||||
|
||||
QString author::getname() const { return m_name; }
|
||||
|
||||
QDate author::getbirthdate() const { return m_birthdate; }
|
||||
|
||||
author::enum_sex author::getsex() const { return m_sex; }
|
||||
|
||||
author::type_list_of_blog author::getlist_of_blog() const { return m_blogX; }
|
||||
|
||||
author::type_list_of_blog & author::list_of_blog() { return m_blogX; }
|
||||
|
||||
const author::type_list_of_blog & author::list_of_blog() const { return m_blogX; }
|
||||
|
||||
void author::setauthor_id(const QString & val) { m_id = val; }
|
||||
|
||||
void author::setname(const QString & val) { m_name = val; }
|
||||
|
||||
void author::setbirthdate(const QDate & val) { m_birthdate = val; }
|
||||
|
||||
void author::setsex(const author::enum_sex & val) { m_sex = val; }
|
||||
|
||||
void author::setlist_of_blog(const author::type_list_of_blog & val) { m_blogX = val; }
|
||||
53
test/qxBlogModelView/src/blog.cpp
Normal file
53
test/qxBlogModelView/src/blog.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
#include "../include/precompiled.h"
|
||||
|
||||
#include "../include/blog.h"
|
||||
|
||||
#include <QxOrm_Impl.h>
|
||||
|
||||
QX_REGISTER_CPP_QX_BLOG(blog)
|
||||
|
||||
namespace qx {
|
||||
template <> void register_class(QxClass<blog> & t)
|
||||
{
|
||||
t.id(& blog::m_id, "blog_id");
|
||||
|
||||
t.data(& blog::m_title, "blog_title");
|
||||
t.data(& blog::m_text, "blog_text");
|
||||
t.data(& blog::m_dt_creation, "date_creation");
|
||||
|
||||
t.relationManyToOne(& blog::m_author, "author_id");
|
||||
t.relationOneToMany(& blog::m_commentX, "list_comment", "blog_id");
|
||||
t.relationManyToMany(& blog::m_categoryX, "list_category", "category_blog", "blog_id", "category_id");
|
||||
}}
|
||||
|
||||
long blog::getblog_id() const { return m_id; }
|
||||
|
||||
QString blog::gettitle() const { return m_title; }
|
||||
|
||||
QString blog::gettext() const { return m_text; }
|
||||
|
||||
blog::type_author blog::getauthor() const { return m_author; }
|
||||
|
||||
blog::type_list_of_comment blog::getlist_of_comment() const { return m_commentX; }
|
||||
|
||||
blog::type_list_of_comment & blog::list_of_comment() { return m_commentX; }
|
||||
|
||||
const blog::type_list_of_comment & blog::list_of_comment() const { return m_commentX; }
|
||||
|
||||
blog::type_list_of_category blog::getlist_of_category() const { return m_categoryX; }
|
||||
|
||||
blog::type_list_of_category & blog::list_of_category() { return m_categoryX; }
|
||||
|
||||
const blog::type_list_of_category & blog::list_of_category() const { return m_categoryX; }
|
||||
|
||||
void blog::setblog_id(const long & val) { m_id = val; }
|
||||
|
||||
void blog::settitle(const QString & val) { m_title = val; }
|
||||
|
||||
void blog::settext(const QString & val) { m_text = val; }
|
||||
|
||||
void blog::setauthor(const blog::type_author & val) { m_author = val; }
|
||||
|
||||
void blog::setlist_of_comment(const blog::type_list_of_comment & val) { m_commentX = val; }
|
||||
|
||||
void blog::setlist_of_category(const blog::type_list_of_category & val) { m_categoryX = val; }
|
||||
39
test/qxBlogModelView/src/category.cpp
Normal file
39
test/qxBlogModelView/src/category.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
#include "../include/precompiled.h"
|
||||
|
||||
#include "../include/category.h"
|
||||
#include "../include/blog.h"
|
||||
|
||||
#include <QxOrm_Impl.h>
|
||||
|
||||
QX_REGISTER_CPP_QX_BLOG(category)
|
||||
|
||||
namespace qx {
|
||||
template <> void register_class(QxClass<category> & t)
|
||||
{
|
||||
t.id(& category::m_id, "category_id");
|
||||
|
||||
t.data(& category::m_name, "name");
|
||||
t.data(& category::m_desc, "description");
|
||||
|
||||
t.relationManyToMany(& category::m_blogX, "list_blog", "category_blog", "category_id", "blog_id");
|
||||
}}
|
||||
|
||||
long category::getcategory_id() const { return m_id; }
|
||||
|
||||
QString category::getname() const { return m_name; }
|
||||
|
||||
QString category::getdescription() const { return m_desc; }
|
||||
|
||||
category::type_list_of_blog category::getlist_of_blog() const { return m_blogX; }
|
||||
|
||||
category::type_list_of_blog & category::list_of_blog() { return m_blogX; }
|
||||
|
||||
const category::type_list_of_blog & category::list_of_blog() const { return m_blogX; }
|
||||
|
||||
void category::setcategory_id(const long & val) { m_id = val; }
|
||||
|
||||
void category::setname(const QString & val) { m_name = val; }
|
||||
|
||||
void category::setdescription(const QString & val) { m_desc = val; }
|
||||
|
||||
void category::setlist_of_blog(const category::type_list_of_blog & val) { m_blogX = val; }
|
||||
36
test/qxBlogModelView/src/comment.cpp
Normal file
36
test/qxBlogModelView/src/comment.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#include "../include/precompiled.h"
|
||||
|
||||
#include "../include/comment.h"
|
||||
#include "../include/blog.h"
|
||||
|
||||
#include <QxOrm_Impl.h>
|
||||
|
||||
QX_REGISTER_CPP_QX_BLOG(comment)
|
||||
|
||||
namespace qx {
|
||||
template <> void register_class(QxClass<comment> & t)
|
||||
{
|
||||
t.id(& comment::m_id, "comment_id");
|
||||
|
||||
t.data(& comment::m_title, "comment_title");
|
||||
t.data(& comment::m_text, "comment_text");
|
||||
t.data(& comment::m_dt_create, "date_creation");
|
||||
|
||||
t.relationManyToOne(& comment::m_blog, "blog_id");
|
||||
}}
|
||||
|
||||
long comment::getcomment_id() const { return m_id; }
|
||||
|
||||
QString comment::gettitle() const { return m_title; }
|
||||
|
||||
QString comment::gettext() const { return m_text; }
|
||||
|
||||
comment::type_blog_id comment::getblog_id() const { return m_blog; }
|
||||
|
||||
void comment::setcomment_id(const long & val) { m_id = val; }
|
||||
|
||||
void comment::settitle(const QString & val) { m_title = val; }
|
||||
|
||||
void comment::settext(const QString & val) { m_text = val; }
|
||||
|
||||
void comment::setblog_id(const comment::type_blog_id & val) { m_blog = val; }
|
||||
325
test/qxBlogModelView/src/main.cpp
Normal file
325
test/qxBlogModelView/src/main.cpp
Normal file
@@ -0,0 +1,325 @@
|
||||
#include "../include/precompiled.h"
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
|
||||
#include <QtWidgets/qapplication.h>
|
||||
#include <QtWidgets/qtableview.h>
|
||||
#include <QtQuick/qquickview.h>
|
||||
#include <QtQml/qqmlcontext.h>
|
||||
#else // (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
|
||||
#include <QtGui/qapplication.h>
|
||||
#include <QtGui/qtableview.h>
|
||||
#include <QtDeclarative/qdeclarativeview.h>
|
||||
#include <QtDeclarative/qdeclarativecontext.h>
|
||||
#endif // (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
|
||||
|
||||
#include "../include/blog.h"
|
||||
#include "../include/author.h"
|
||||
#include "../include/comment.h"
|
||||
#include "../include/category.h"
|
||||
|
||||
#include "../include/model_view_from_qxee/blog.model_view.gen.h"
|
||||
|
||||
#include <QxOrm_Impl.h>
|
||||
|
||||
void init_data();
|
||||
void test_qt_widget();
|
||||
void test_qml_view();
|
||||
void test_qml_view_with_relationship();
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
init_data();
|
||||
test_qt_widget();
|
||||
test_qml_view();
|
||||
test_qml_view_with_relationship();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void init_data()
|
||||
{
|
||||
QFile::remove("./qxBlog.sqlite");
|
||||
|
||||
// Parameters to connect to database
|
||||
qx::QxSqlDatabase::getSingleton()->setDriverName("QSQLITE");
|
||||
qx::QxSqlDatabase::getSingleton()->setDatabaseName("./qxBlog.sqlite");
|
||||
qx::QxSqlDatabase::getSingleton()->setHostName("localhost");
|
||||
qx::QxSqlDatabase::getSingleton()->setUserName("root");
|
||||
qx::QxSqlDatabase::getSingleton()->setPassword("");
|
||||
|
||||
// Only for debug purpose : assert if invalid offset detected fetching a relation
|
||||
qx::QxSqlDatabase::getSingleton()->setVerifyOffsetRelation(true);
|
||||
|
||||
// Create all tables in database
|
||||
QSqlError daoError = qx::dao::create_table<author>();
|
||||
daoError = qx::dao::create_table<comment>();
|
||||
daoError = qx::dao::create_table<category>();
|
||||
daoError = qx::dao::create_table<blog>();
|
||||
|
||||
// Create a list of 3 author
|
||||
author_ptr author_1; author_1.reset(new author());
|
||||
author_ptr author_2; author_2.reset(new author());
|
||||
author_ptr author_3; author_3.reset(new author());
|
||||
|
||||
author_1->m_id = "author_id_1"; author_1->m_name = "author_1";
|
||||
author_1->m_sex = author::male; author_1->m_birthdate = QDate::currentDate();
|
||||
author_2->m_id = "author_id_2"; author_2->m_name = "author_2";
|
||||
author_2->m_sex = author::female; author_2->m_birthdate = QDate::currentDate();
|
||||
author_3->m_id = "author_id_3"; author_3->m_name = "author_3";
|
||||
author_3->m_sex = author::female; author_3->m_birthdate = QDate::currentDate();
|
||||
|
||||
list_author authorX;
|
||||
authorX.insert(author_1->m_id, author_1);
|
||||
authorX.insert(author_2->m_id, author_2);
|
||||
authorX.insert(author_3->m_id, author_3);
|
||||
|
||||
// Insert list of 3 author into database
|
||||
daoError = qx::dao::insert(authorX);
|
||||
qAssert(qx::dao::count<author>() == 3);
|
||||
|
||||
// Clone author 2 : 'author_id_2'
|
||||
author_ptr author_clone = qx::clone(* author_2);
|
||||
qAssert(author_clone->m_id == "author_id_2");
|
||||
qAssert(author_clone->m_sex == author::female);
|
||||
|
||||
// Create a query to fetch only female author : 'author_id_2' and 'author_id_3'
|
||||
qx::QxSqlQuery query("WHERE author.sex = :sex");
|
||||
query.bind(":sex", author::female);
|
||||
|
||||
list_author list_of_female_author;
|
||||
daoError = qx::dao::fetch_by_query(query, list_of_female_author);
|
||||
qAssert(list_of_female_author.count() == 2);
|
||||
|
||||
// Dump list of female author (xml serialization)
|
||||
qx::dump(list_of_female_author);
|
||||
|
||||
// Create 3 categories
|
||||
category_ptr category_1 = category_ptr(new category());
|
||||
category_ptr category_2 = category_ptr(new category());
|
||||
category_ptr category_3 = category_ptr(new category());
|
||||
|
||||
category_1->m_name = "category_1"; category_1->m_desc = "desc_1";
|
||||
category_2->m_name = "category_2"; category_2->m_desc = "desc_2";
|
||||
category_3->m_name = "category_3"; category_3->m_desc = "desc_3";
|
||||
|
||||
{ // Create a scope to destroy temporary connexion to database
|
||||
|
||||
// Open a transaction to database
|
||||
QSqlDatabase db = qx::QxSqlDatabase::getDatabase();
|
||||
bool bCommit = db.transaction();
|
||||
|
||||
// Insert 3 categories into database, use 'db' parameter for the transaction
|
||||
daoError = qx::dao::insert(category_1, (& db)); bCommit = (bCommit && ! daoError.isValid());
|
||||
daoError = qx::dao::insert(category_2, (& db)); bCommit = (bCommit && ! daoError.isValid());
|
||||
daoError = qx::dao::insert(category_3, (& db)); bCommit = (bCommit && ! daoError.isValid());
|
||||
|
||||
qAssert(bCommit);
|
||||
qAssert(category_1->m_id != 0);
|
||||
qAssert(category_2->m_id != 0);
|
||||
qAssert(category_3->m_id != 0);
|
||||
|
||||
// Terminate transaction => commit or rollback if there is error
|
||||
if (bCommit) { db.commit(); }
|
||||
else { db.rollback(); }
|
||||
|
||||
} // End of scope : 'db' is destroyed
|
||||
|
||||
// Create a blog with the class name (factory)
|
||||
qx::any blog_any = qx::create("blog");
|
||||
blog_ptr blog_1;
|
||||
try { blog_1 = qx::any_cast<blog_ptr>(blog_any); }
|
||||
catch (...) { blog_1.reset(new blog()); }
|
||||
blog_1->m_text = "blog_text_1";
|
||||
blog_1->m_dt_creation = QDateTime::currentDateTime();
|
||||
blog_1->m_author = author_1;
|
||||
|
||||
// Insert 'blog_1' into database with 'save()' method
|
||||
daoError = qx::dao::save(blog_1);
|
||||
|
||||
// Modify 'blog_1' properties and save into database
|
||||
blog_1->m_text = "update blog_text_1";
|
||||
blog_1->m_author = author_2;
|
||||
daoError = qx::dao::save(blog_1);
|
||||
|
||||
// Add 2 comments to 'blog_1'
|
||||
comment_ptr comment_1; comment_1.reset(new comment());
|
||||
comment_ptr comment_2; comment_2.reset(new comment());
|
||||
|
||||
comment_1->m_text = "comment_1 text";
|
||||
comment_1->m_dt_create = QDateTime::currentDateTime();
|
||||
comment_1->m_blog = blog_1;
|
||||
comment_2->m_text = "comment_2 text";
|
||||
comment_2->m_dt_create = QDateTime::currentDateTime();
|
||||
comment_2->m_blog = blog_1;
|
||||
|
||||
daoError = qx::dao::insert(comment_1);
|
||||
daoError = qx::dao::insert(comment_2);
|
||||
qAssert(qx::dao::count<comment>() == 2);
|
||||
|
||||
// Add 2 categories to 'blog_1' => must insert into extra-table 'category_blog'
|
||||
blog_1->m_categoryX.insert(category_1->m_id, category_1);
|
||||
blog_1->m_categoryX.insert(category_3->m_id, category_3);
|
||||
daoError = qx::dao::save_with_relation("list_category", blog_1);
|
||||
|
||||
// Fetch blog into a new variable with all relation : 'author', 'comment' and 'category'
|
||||
blog_ptr blog_tmp; blog_tmp.reset(new blog());
|
||||
blog_tmp->m_id = blog_1->m_id;
|
||||
daoError = qx::dao::fetch_by_id_with_all_relation(blog_tmp);
|
||||
|
||||
qAssert(blog_tmp->m_commentX.count() == 2);
|
||||
qAssert(blog_tmp->m_categoryX.count() == 2);
|
||||
qAssert(blog_tmp->m_text == "update blog_text_1");
|
||||
qAssert(blog_tmp->m_author && blog_tmp->m_author->m_id == "author_id_2");
|
||||
|
||||
// Fetch blog into a new variable with many relations using "*->*->*->*" (4 levels of relationships)
|
||||
blog_tmp.reset(new blog());
|
||||
blog_tmp->m_id = blog_1->m_id;
|
||||
daoError = qx::dao::fetch_by_id_with_relation("*->*->*->*", blog_tmp);
|
||||
|
||||
qAssert(blog_tmp->m_commentX.count() == 2);
|
||||
qAssert(blog_tmp->m_categoryX.count() == 2);
|
||||
qAssert(blog_tmp->m_text == "update blog_text_1");
|
||||
qAssert(blog_tmp->m_author && blog_tmp->m_author->m_id == "author_id_2");
|
||||
|
||||
// Dump 'blog_tmp' result from database (xml serialization)
|
||||
qx::dump(blog_tmp);
|
||||
|
||||
// Check qx::dao::save_with_relation_recursive() function
|
||||
daoError = qx::dao::save_with_relation_recursive(blog_tmp);
|
||||
qAssert(! daoError.isValid());
|
||||
daoError = qx::dao::save_with_relation_recursive(blog_tmp, qx::dao::save_mode::e_update_only);
|
||||
qAssert(! daoError.isValid());
|
||||
|
||||
// Call 'age()' method with class name and method name (reflexion)
|
||||
qx_bool bInvokeOk = qx::QxClassX::invoke("author", "age", author_1);
|
||||
qAssert(bInvokeOk);
|
||||
|
||||
// Test 'isDirty()' method
|
||||
qx::dao::ptr<blog> blog_isdirty = qx::dao::ptr<blog>(new blog());
|
||||
blog_isdirty->m_id = blog_1->m_id;
|
||||
daoError = qx::dao::fetch_by_id(blog_isdirty);
|
||||
qAssert(! daoError.isValid() && ! blog_isdirty.isDirty());
|
||||
|
||||
blog_isdirty->m_text = "blog property 'text' modified => blog is dirty !!!";
|
||||
QStringList lstDiff; bool bDirty = blog_isdirty.isDirty(lstDiff);
|
||||
qAssert(bDirty && (lstDiff.count() == 1) && (lstDiff.at(0) == "blog_text"));
|
||||
if (bDirty) { qDebug("[QxOrm] test dirty 1 : blog is dirty => '%s'", qPrintable(lstDiff.join("|"))); }
|
||||
|
||||
// Update only property 'm_text' of 'blog_isdirty'
|
||||
daoError = qx::dao::update_optimized(blog_isdirty);
|
||||
qAssert(! daoError.isValid() && ! blog_isdirty.isDirty());
|
||||
qx::dump(blog_isdirty);
|
||||
|
||||
// Test 'isDirty()' method with a container
|
||||
typedef qx::dao::ptr< QList<author_ptr> > type_lst_author_test_is_dirty;
|
||||
type_lst_author_test_is_dirty container_isdirty = type_lst_author_test_is_dirty(new QList<author_ptr>());
|
||||
daoError = qx::dao::fetch_all(container_isdirty);
|
||||
qAssert(! daoError.isValid() && ! container_isdirty.isDirty() && (container_isdirty->count() == 3));
|
||||
|
||||
author_ptr author_ptr_dirty = container_isdirty->at(1);
|
||||
author_ptr_dirty->m_name = "author name modified at index 1 => container is dirty !!!";
|
||||
bDirty = container_isdirty.isDirty(lstDiff);
|
||||
qAssert(bDirty && (lstDiff.count() == 1));
|
||||
if (bDirty) { qDebug("[QxOrm] test dirty 2 : container is dirty => '%s'", qPrintable(lstDiff.join("|"))); }
|
||||
|
||||
author_ptr_dirty = container_isdirty->at(2);
|
||||
author_ptr_dirty->m_birthdate = QDate(1998, 03, 06);
|
||||
bDirty = container_isdirty.isDirty(lstDiff);
|
||||
qAssert(bDirty && (lstDiff.count() == 2));
|
||||
if (bDirty) { qDebug("[QxOrm] test dirty 3 : container is dirty => '%s'", qPrintable(lstDiff.join("|"))); }
|
||||
|
||||
// Update only property 'm_name' at position 1, only property 'm_birthdate' at position 2 and nothing at position 0
|
||||
daoError = qx::dao::update_optimized(container_isdirty);
|
||||
qAssert(! daoError.isValid() && ! container_isdirty.isDirty());
|
||||
qx::dump(container_isdirty);
|
||||
|
||||
// Fetch only property 'm_dt_creation' of blog
|
||||
QStringList lstColumns = QStringList() << "date_creation";
|
||||
list_blog lst_blog_with_only_date_creation;
|
||||
daoError = qx::dao::fetch_all(lst_blog_with_only_date_creation, NULL, lstColumns);
|
||||
qAssert(! daoError.isValid() && (lst_blog_with_only_date_creation.size() > 0));
|
||||
if ((lst_blog_with_only_date_creation.size() > 0) && (lst_blog_with_only_date_creation[0].get() != NULL))
|
||||
{ qAssert(lst_blog_with_only_date_creation[0]->m_text.isEmpty()); }
|
||||
qx::dump(lst_blog_with_only_date_creation);
|
||||
|
||||
// Dump all registered classes into QxOrm context (introspection engine)
|
||||
qx::QxClassX::dumpAllClasses();
|
||||
|
||||
// Call a custom SQL query or a stored procedure
|
||||
qx_query testStoredProc("SELECT * FROM author");
|
||||
daoError = qx::dao::call_query(testStoredProc);
|
||||
qAssert(! daoError.isValid());
|
||||
testStoredProc.dumpSqlResult();
|
||||
|
||||
// Call a custom SQL query or a stored procedure and fetch automatically properties (with a collection of items)
|
||||
qx_query testStoredProcBis("SELECT * FROM author");
|
||||
authorX.clear();
|
||||
daoError = qx::dao::execute_query(testStoredProcBis, authorX);
|
||||
qAssert(! daoError.isValid()); qAssert(authorX.count() > 0);
|
||||
qx::dump(authorX);
|
||||
|
||||
// Call a custom SQL query or a stored procedure and fetch automatically properties
|
||||
qx_query testStoredProcThird("SELECT name, category_id FROM category");
|
||||
category_ptr category_tmp = category_ptr(new category());
|
||||
daoError = qx::dao::execute_query(testStoredProcThird, category_tmp);
|
||||
qAssert(! daoError.isValid()); qAssert(category_tmp->m_id != 0);
|
||||
qx::dump(category_tmp);
|
||||
|
||||
// Just to test compilation of nested models
|
||||
qx::IxModel * pNestedModel1 = qx::model_view::create_nested_model(NULL, QModelIndex(), category_tmp); Q_UNUSED(pNestedModel1);
|
||||
qx::IxModel * pNestedModel2 = qx::model_view::create_nested_model(NULL, QModelIndex(), authorX); Q_UNUSED(pNestedModel2);
|
||||
}
|
||||
|
||||
void test_qt_widget()
|
||||
{
|
||||
qx::IxModel * pModel = new qx::QxModel<author>();
|
||||
pModel->qxFetchAll();
|
||||
|
||||
QTableView tableView;
|
||||
tableView.setModel(pModel);
|
||||
tableView.setSortingEnabled(true);
|
||||
tableView.show();
|
||||
qApp->exec();
|
||||
}
|
||||
|
||||
void test_qml_view()
|
||||
{
|
||||
qx::IxModel * pModel = new qx::QxModel<author>();
|
||||
pModel->qxFetchAll();
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
QQuickView qmlView;
|
||||
QString sQmlFile = "qrc:/documents/main_qt6.qml";
|
||||
#elif (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) // (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
QQuickView qmlView;
|
||||
QString sQmlFile = "qrc:/documents/main.qml";
|
||||
#else // (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
QDeclarativeView qmlView;
|
||||
QString sQmlFile = "qrc:/documents/main_qt4.qml";
|
||||
#endif // (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
|
||||
qmlView.rootContext()->setContextProperty("myModel", pModel);
|
||||
qmlView.setSource(QUrl(sQmlFile));
|
||||
qmlView.show();
|
||||
qApp->exec();
|
||||
}
|
||||
|
||||
void test_qml_view_with_relationship()
|
||||
{
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
|
||||
qx::IxModel * pModel = new model_view::blog_model();
|
||||
pModel->qxFetchAll(QStringList() << "*");
|
||||
|
||||
QQuickView qmlView;
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
QString sQmlFile = "qrc:/documents/main_relationship_qt6.qml";
|
||||
#else // (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
QString sQmlFile = "qrc:/documents/main_relationship.qml";
|
||||
#endif // (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
|
||||
qmlView.rootContext()->setContextProperty("myModel", pModel);
|
||||
qmlView.setSource(QUrl(sQmlFile));
|
||||
qmlView.show();
|
||||
qApp->exec();
|
||||
#endif // (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/************************************************************************************************
|
||||
** File created by QxEntityEditor 1.1.9 (2016/05/04 10:05) : please, do NOT modify this file ! **
|
||||
************************************************************************************************/
|
||||
|
||||
#include "../../include/precompiled.h"
|
||||
|
||||
#include "../../include/model_view_from_qxee/author.model_view.gen.h"
|
||||
#include "../../include/model_view_from_qxee/blog.model_view.gen.h"
|
||||
|
||||
#include <QxMemLeak.h>
|
||||
|
||||
namespace model_view {
|
||||
|
||||
author_model::author_model(QObject * parent /* = 0 */) : author_model_base_class(parent) { ; }
|
||||
|
||||
author_model::author_model(qx::IxModel * other, QObject * parent) : author_model_base_class(other, parent) { ; }
|
||||
|
||||
author_model::~author_model() { ; }
|
||||
|
||||
QObject * author_model::list_of_blog(int row, bool bLoadFromDatabase /* = false */, const QString & sAppendRelations /* = QString() */)
|
||||
{
|
||||
QString sRelation = "list_blog";
|
||||
qx::IxModel * pChild = (bLoadFromDatabase ? NULL : this->getChild(row, sRelation));
|
||||
if (pChild) { return static_cast<QObject *>(pChild); }
|
||||
|
||||
if ((row < 0) || (row >= this->m_model.count())) { qAssert(false); return NULL; }
|
||||
author_model_base_class::type_ptr ptr = this->m_model.getByIndex(row);
|
||||
if (! ptr) { qAssert(false); return NULL; }
|
||||
QString id = ptr->getauthor_id();
|
||||
author::type_list_of_blog value = ptr->getlist_of_blog();
|
||||
|
||||
if (bLoadFromDatabase)
|
||||
{
|
||||
if (! sAppendRelations.isEmpty() && ! sAppendRelations.startsWith("->") && ! sAppendRelations.startsWith(">>")) { sRelation += "->" + sAppendRelations; }
|
||||
else if (! sAppendRelations.isEmpty()) { sRelation += sAppendRelations; }
|
||||
author tmp;
|
||||
tmp.setauthor_id(id);
|
||||
this->m_lastError = qx::dao::fetch_by_id_with_relation(sRelation, tmp);
|
||||
if (this->m_lastError.isValid()) { return NULL; }
|
||||
value = tmp.getlist_of_blog();
|
||||
ptr->setlist_of_blog(value);
|
||||
}
|
||||
|
||||
model_view::blog_model * pNewChild = NULL;
|
||||
pChild = qx::model_view::create_nested_model_with_type(this, QModelIndex(), value, pNewChild);
|
||||
if (pChild) { this->insertChild(row, "list_blog", pChild); }
|
||||
return static_cast<QObject *>(pChild);
|
||||
}
|
||||
|
||||
void author_model::syncNestedModel(int row, const QStringList & relation)
|
||||
{
|
||||
Q_UNUSED(relation);
|
||||
qx::IxModel * pNestedModel = NULL;
|
||||
if ((row < 0) || (row >= this->m_model.count())) { return; }
|
||||
author_model_base_class::type_ptr ptr = this->m_model.getByIndex(row);
|
||||
if (! ptr) { return; }
|
||||
|
||||
pNestedModel = this->getChild(row, "list_blog");
|
||||
if (pNestedModel)
|
||||
{
|
||||
this->syncNestedModelRecursive(pNestedModel, relation);
|
||||
author::type_list_of_blog value;
|
||||
qx::model_view::sync_nested_model(pNestedModel, value);
|
||||
ptr->setlist_of_blog(value);
|
||||
}
|
||||
}
|
||||
|
||||
void author_model::syncAllNestedModel(const QStringList & relation)
|
||||
{
|
||||
if (this->m_lstChild.count() <= 0) { return; }
|
||||
for (long l = 0; l < this->m_model.count(); l++)
|
||||
{ this->syncNestedModel(static_cast<int>(l), relation); }
|
||||
}
|
||||
|
||||
} // namespace model_view
|
||||
@@ -0,0 +1,155 @@
|
||||
/************************************************************************************************
|
||||
** File created by QxEntityEditor 1.1.9 (2016/05/04 10:05) : please, do NOT modify this file ! **
|
||||
************************************************************************************************/
|
||||
|
||||
#include "../../include/precompiled.h"
|
||||
|
||||
#include "../../include/model_view_from_qxee/blog.model_view.gen.h"
|
||||
#include "../../include/model_view_from_qxee/author.model_view.gen.h"
|
||||
#include "../../include/model_view_from_qxee/comment.model_view.gen.h"
|
||||
#include "../../include/model_view_from_qxee/category.model_view.gen.h"
|
||||
|
||||
#include <QxMemLeak.h>
|
||||
|
||||
namespace model_view {
|
||||
|
||||
blog_model::blog_model(QObject * parent /* = 0 */) : blog_model_base_class(parent) { ; }
|
||||
|
||||
blog_model::blog_model(qx::IxModel * other, QObject * parent) : blog_model_base_class(other, parent) { ; }
|
||||
|
||||
blog_model::~blog_model() { ; }
|
||||
|
||||
QObject * blog_model::author_id(int row, bool bLoadFromDatabase /* = false */, const QString & sAppendRelations /* = QString() */)
|
||||
{
|
||||
QString sRelation = "author_id";
|
||||
qx::IxModel * pChild = (bLoadFromDatabase ? NULL : this->getChild(row, sRelation));
|
||||
if (pChild) { return static_cast<QObject *>(pChild); }
|
||||
|
||||
if ((row < 0) || (row >= this->m_model.count())) { qAssert(false); return NULL; }
|
||||
blog_model_base_class::type_ptr ptr = this->m_model.getByIndex(row);
|
||||
if (! ptr) { qAssert(false); return NULL; }
|
||||
long id = ptr->getblog_id();
|
||||
blog::type_author value = ptr->getauthor();
|
||||
|
||||
if (bLoadFromDatabase)
|
||||
{
|
||||
if (! sAppendRelations.isEmpty() && ! sAppendRelations.startsWith("->") && ! sAppendRelations.startsWith(">>")) { sRelation += "->" + sAppendRelations; }
|
||||
else if (! sAppendRelations.isEmpty()) { sRelation += sAppendRelations; }
|
||||
blog tmp;
|
||||
tmp.setblog_id(id);
|
||||
this->m_lastError = qx::dao::fetch_by_id_with_relation(sRelation, tmp);
|
||||
if (this->m_lastError.isValid()) { return NULL; }
|
||||
value = tmp.getauthor();
|
||||
ptr->setauthor(value);
|
||||
}
|
||||
|
||||
model_view::author_model * pNewChild = NULL;
|
||||
pChild = qx::model_view::create_nested_model_with_type(this, QModelIndex(), value, pNewChild);
|
||||
if (pChild) { this->insertChild(row, "author_id", pChild); }
|
||||
return static_cast<QObject *>(pChild);
|
||||
}
|
||||
|
||||
QObject * blog_model::list_of_comment(int row, bool bLoadFromDatabase /* = false */, const QString & sAppendRelations /* = QString() */)
|
||||
{
|
||||
QString sRelation = "list_comment";
|
||||
qx::IxModel * pChild = (bLoadFromDatabase ? NULL : this->getChild(row, sRelation));
|
||||
if (pChild) { return static_cast<QObject *>(pChild); }
|
||||
|
||||
if ((row < 0) || (row >= this->m_model.count())) { qAssert(false); return NULL; }
|
||||
blog_model_base_class::type_ptr ptr = this->m_model.getByIndex(row);
|
||||
if (! ptr) { qAssert(false); return NULL; }
|
||||
long id = ptr->getblog_id();
|
||||
blog::type_list_of_comment value = ptr->getlist_of_comment();
|
||||
|
||||
if (bLoadFromDatabase)
|
||||
{
|
||||
if (! sAppendRelations.isEmpty() && ! sAppendRelations.startsWith("->") && ! sAppendRelations.startsWith(">>")) { sRelation += "->" + sAppendRelations; }
|
||||
else if (! sAppendRelations.isEmpty()) { sRelation += sAppendRelations; }
|
||||
blog tmp;
|
||||
tmp.setblog_id(id);
|
||||
this->m_lastError = qx::dao::fetch_by_id_with_relation(sRelation, tmp);
|
||||
if (this->m_lastError.isValid()) { return NULL; }
|
||||
value = tmp.getlist_of_comment();
|
||||
ptr->setlist_of_comment(value);
|
||||
}
|
||||
|
||||
model_view::comment_model * pNewChild = NULL;
|
||||
pChild = qx::model_view::create_nested_model_with_type(this, QModelIndex(), value, pNewChild);
|
||||
if (pChild) { this->insertChild(row, "list_comment", pChild); }
|
||||
return static_cast<QObject *>(pChild);
|
||||
}
|
||||
|
||||
QObject * blog_model::list_of_category(int row, bool bLoadFromDatabase /* = false */, const QString & sAppendRelations /* = QString() */)
|
||||
{
|
||||
QString sRelation = "list_category";
|
||||
qx::IxModel * pChild = (bLoadFromDatabase ? NULL : this->getChild(row, sRelation));
|
||||
if (pChild) { return static_cast<QObject *>(pChild); }
|
||||
|
||||
if ((row < 0) || (row >= this->m_model.count())) { qAssert(false); return NULL; }
|
||||
blog_model_base_class::type_ptr ptr = this->m_model.getByIndex(row);
|
||||
if (! ptr) { qAssert(false); return NULL; }
|
||||
long id = ptr->getblog_id();
|
||||
blog::type_list_of_category value = ptr->getlist_of_category();
|
||||
|
||||
if (bLoadFromDatabase)
|
||||
{
|
||||
if (! sAppendRelations.isEmpty() && ! sAppendRelations.startsWith("->") && ! sAppendRelations.startsWith(">>")) { sRelation += "->" + sAppendRelations; }
|
||||
else if (! sAppendRelations.isEmpty()) { sRelation += sAppendRelations; }
|
||||
blog tmp;
|
||||
tmp.setblog_id(id);
|
||||
this->m_lastError = qx::dao::fetch_by_id_with_relation(sRelation, tmp);
|
||||
if (this->m_lastError.isValid()) { return NULL; }
|
||||
value = tmp.getlist_of_category();
|
||||
ptr->setlist_of_category(value);
|
||||
}
|
||||
|
||||
model_view::category_model * pNewChild = NULL;
|
||||
pChild = qx::model_view::create_nested_model_with_type(this, QModelIndex(), value, pNewChild);
|
||||
if (pChild) { this->insertChild(row, "list_category", pChild); }
|
||||
return static_cast<QObject *>(pChild);
|
||||
}
|
||||
|
||||
void blog_model::syncNestedModel(int row, const QStringList & relation)
|
||||
{
|
||||
Q_UNUSED(relation);
|
||||
qx::IxModel * pNestedModel = NULL;
|
||||
if ((row < 0) || (row >= this->m_model.count())) { return; }
|
||||
blog_model_base_class::type_ptr ptr = this->m_model.getByIndex(row);
|
||||
if (! ptr) { return; }
|
||||
|
||||
pNestedModel = this->getChild(row, "author_id");
|
||||
if (pNestedModel)
|
||||
{
|
||||
this->syncNestedModelRecursive(pNestedModel, relation);
|
||||
blog::type_author value;
|
||||
qx::model_view::sync_nested_model(pNestedModel, value);
|
||||
ptr->setauthor(value);
|
||||
}
|
||||
|
||||
pNestedModel = this->getChild(row, "list_comment");
|
||||
if (pNestedModel)
|
||||
{
|
||||
this->syncNestedModelRecursive(pNestedModel, relation);
|
||||
blog::type_list_of_comment value;
|
||||
qx::model_view::sync_nested_model(pNestedModel, value);
|
||||
ptr->setlist_of_comment(value);
|
||||
}
|
||||
|
||||
pNestedModel = this->getChild(row, "list_category");
|
||||
if (pNestedModel)
|
||||
{
|
||||
this->syncNestedModelRecursive(pNestedModel, relation);
|
||||
blog::type_list_of_category value;
|
||||
qx::model_view::sync_nested_model(pNestedModel, value);
|
||||
ptr->setlist_of_category(value);
|
||||
}
|
||||
}
|
||||
|
||||
void blog_model::syncAllNestedModel(const QStringList & relation)
|
||||
{
|
||||
if (this->m_lstChild.count() <= 0) { return; }
|
||||
for (long l = 0; l < this->m_model.count(); l++)
|
||||
{ this->syncNestedModel(static_cast<int>(l), relation); }
|
||||
}
|
||||
|
||||
} // namespace model_view
|
||||
@@ -0,0 +1,75 @@
|
||||
/************************************************************************************************
|
||||
** File created by QxEntityEditor 1.1.9 (2016/05/04 10:05) : please, do NOT modify this file ! **
|
||||
************************************************************************************************/
|
||||
|
||||
#include "../../include/precompiled.h"
|
||||
|
||||
#include "../../include/model_view_from_qxee/category.model_view.gen.h"
|
||||
#include "../../include/model_view_from_qxee/blog.model_view.gen.h"
|
||||
|
||||
#include <QxMemLeak.h>
|
||||
|
||||
namespace model_view {
|
||||
|
||||
category_model::category_model(QObject * parent /* = 0 */) : category_model_base_class(parent) { ; }
|
||||
|
||||
category_model::category_model(qx::IxModel * other, QObject * parent) : category_model_base_class(other, parent) { ; }
|
||||
|
||||
category_model::~category_model() { ; }
|
||||
|
||||
QObject * category_model::list_of_blog(int row, bool bLoadFromDatabase /* = false */, const QString & sAppendRelations /* = QString() */)
|
||||
{
|
||||
QString sRelation = "list_blog";
|
||||
qx::IxModel * pChild = (bLoadFromDatabase ? NULL : this->getChild(row, sRelation));
|
||||
if (pChild) { return static_cast<QObject *>(pChild); }
|
||||
|
||||
if ((row < 0) || (row >= this->m_model.count())) { qAssert(false); return NULL; }
|
||||
category_model_base_class::type_ptr ptr = this->m_model.getByIndex(row);
|
||||
if (! ptr) { qAssert(false); return NULL; }
|
||||
long id = ptr->getcategory_id();
|
||||
category::type_list_of_blog value = ptr->getlist_of_blog();
|
||||
|
||||
if (bLoadFromDatabase)
|
||||
{
|
||||
if (! sAppendRelations.isEmpty() && ! sAppendRelations.startsWith("->") && ! sAppendRelations.startsWith(">>")) { sRelation += "->" + sAppendRelations; }
|
||||
else if (! sAppendRelations.isEmpty()) { sRelation += sAppendRelations; }
|
||||
category tmp;
|
||||
tmp.setcategory_id(id);
|
||||
this->m_lastError = qx::dao::fetch_by_id_with_relation(sRelation, tmp);
|
||||
if (this->m_lastError.isValid()) { return NULL; }
|
||||
value = tmp.getlist_of_blog();
|
||||
ptr->setlist_of_blog(value);
|
||||
}
|
||||
|
||||
model_view::blog_model * pNewChild = NULL;
|
||||
pChild = qx::model_view::create_nested_model_with_type(this, QModelIndex(), value, pNewChild);
|
||||
if (pChild) { this->insertChild(row, "list_blog", pChild); }
|
||||
return static_cast<QObject *>(pChild);
|
||||
}
|
||||
|
||||
void category_model::syncNestedModel(int row, const QStringList & relation)
|
||||
{
|
||||
Q_UNUSED(relation);
|
||||
qx::IxModel * pNestedModel = NULL;
|
||||
if ((row < 0) || (row >= this->m_model.count())) { return; }
|
||||
category_model_base_class::type_ptr ptr = this->m_model.getByIndex(row);
|
||||
if (! ptr) { return; }
|
||||
|
||||
pNestedModel = this->getChild(row, "list_blog");
|
||||
if (pNestedModel)
|
||||
{
|
||||
this->syncNestedModelRecursive(pNestedModel, relation);
|
||||
category::type_list_of_blog value;
|
||||
qx::model_view::sync_nested_model(pNestedModel, value);
|
||||
ptr->setlist_of_blog(value);
|
||||
}
|
||||
}
|
||||
|
||||
void category_model::syncAllNestedModel(const QStringList & relation)
|
||||
{
|
||||
if (this->m_lstChild.count() <= 0) { return; }
|
||||
for (long l = 0; l < this->m_model.count(); l++)
|
||||
{ this->syncNestedModel(static_cast<int>(l), relation); }
|
||||
}
|
||||
|
||||
} // namespace model_view
|
||||
@@ -0,0 +1,75 @@
|
||||
/************************************************************************************************
|
||||
** File created by QxEntityEditor 1.1.9 (2016/05/04 10:05) : please, do NOT modify this file ! **
|
||||
************************************************************************************************/
|
||||
|
||||
#include "../../include/precompiled.h"
|
||||
|
||||
#include "../../include/model_view_from_qxee/comment.model_view.gen.h"
|
||||
#include "../../include/model_view_from_qxee/blog.model_view.gen.h"
|
||||
|
||||
#include <QxMemLeak.h>
|
||||
|
||||
namespace model_view {
|
||||
|
||||
comment_model::comment_model(QObject * parent /* = 0 */) : comment_model_base_class(parent) { ; }
|
||||
|
||||
comment_model::comment_model(qx::IxModel * other, QObject * parent) : comment_model_base_class(other, parent) { ; }
|
||||
|
||||
comment_model::~comment_model() { ; }
|
||||
|
||||
QObject * comment_model::blog_id(int row, bool bLoadFromDatabase /* = false */, const QString & sAppendRelations /* = QString() */)
|
||||
{
|
||||
QString sRelation = "blog_id";
|
||||
qx::IxModel * pChild = (bLoadFromDatabase ? NULL : this->getChild(row, sRelation));
|
||||
if (pChild) { return static_cast<QObject *>(pChild); }
|
||||
|
||||
if ((row < 0) || (row >= this->m_model.count())) { qAssert(false); return NULL; }
|
||||
comment_model_base_class::type_ptr ptr = this->m_model.getByIndex(row);
|
||||
if (! ptr) { qAssert(false); return NULL; }
|
||||
long id = ptr->getcomment_id();
|
||||
comment::type_blog_id value = ptr->getblog_id();
|
||||
|
||||
if (bLoadFromDatabase)
|
||||
{
|
||||
if (! sAppendRelations.isEmpty() && ! sAppendRelations.startsWith("->") && ! sAppendRelations.startsWith(">>")) { sRelation += "->" + sAppendRelations; }
|
||||
else if (! sAppendRelations.isEmpty()) { sRelation += sAppendRelations; }
|
||||
comment tmp;
|
||||
tmp.setcomment_id(id);
|
||||
this->m_lastError = qx::dao::fetch_by_id_with_relation(sRelation, tmp);
|
||||
if (this->m_lastError.isValid()) { return NULL; }
|
||||
value = tmp.getblog_id();
|
||||
ptr->setblog_id(value);
|
||||
}
|
||||
|
||||
model_view::blog_model * pNewChild = NULL;
|
||||
pChild = qx::model_view::create_nested_model_with_type(this, QModelIndex(), value, pNewChild);
|
||||
if (pChild) { this->insertChild(row, "blog_id", pChild); }
|
||||
return static_cast<QObject *>(pChild);
|
||||
}
|
||||
|
||||
void comment_model::syncNestedModel(int row, const QStringList & relation)
|
||||
{
|
||||
Q_UNUSED(relation);
|
||||
qx::IxModel * pNestedModel = NULL;
|
||||
if ((row < 0) || (row >= this->m_model.count())) { return; }
|
||||
comment_model_base_class::type_ptr ptr = this->m_model.getByIndex(row);
|
||||
if (! ptr) { return; }
|
||||
|
||||
pNestedModel = this->getChild(row, "blog_id");
|
||||
if (pNestedModel)
|
||||
{
|
||||
this->syncNestedModelRecursive(pNestedModel, relation);
|
||||
comment::type_blog_id value;
|
||||
qx::model_view::sync_nested_model(pNestedModel, value);
|
||||
ptr->setblog_id(value);
|
||||
}
|
||||
}
|
||||
|
||||
void comment_model::syncAllNestedModel(const QStringList & relation)
|
||||
{
|
||||
if (this->m_lstChild.count() <= 0) { return; }
|
||||
for (long l = 0; l < this->m_model.count(); l++)
|
||||
{ this->syncNestedModel(static_cast<int>(l), relation); }
|
||||
}
|
||||
|
||||
} // namespace model_view
|
||||
66
test/qxBlogMongoDB/CMakeLists.txt
Normal file
66
test/qxBlogMongoDB/CMakeLists.txt
Normal file
@@ -0,0 +1,66 @@
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
project(qxBlogMongoDB LANGUAGES CXX)
|
||||
|
||||
include(../../QxOrm.cmake)
|
||||
|
||||
if(_QX_ENABLE_MONGODB)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
set(CMAKE_DEBUG_POSTFIX "d")
|
||||
|
||||
set(HEADERS
|
||||
./include/precompiled.h
|
||||
./include/export.h
|
||||
./include/author.h
|
||||
./include/blog.h
|
||||
./include/category.h
|
||||
./include/comment.h
|
||||
./include/TestQtProperty.h
|
||||
)
|
||||
|
||||
set(SRCS
|
||||
./src/author.cpp
|
||||
./src/blog.cpp
|
||||
./src/category.cpp
|
||||
./src/comment.cpp
|
||||
./src/TestQtProperty.cpp
|
||||
./src/main.cpp
|
||||
)
|
||||
|
||||
add_executable(qxBlogMongoDB ${SRCS} ${HEADERS})
|
||||
|
||||
target_compile_definitions(qxBlogMongoDB PRIVATE -D_BUILDING_QX_BLOG)
|
||||
|
||||
if(COMMAND target_precompile_headers)
|
||||
target_precompile_headers(qxBlogMongoDB PRIVATE ./include/precompiled.h)
|
||||
endif() # (COMMAND target_precompile_headers)
|
||||
|
||||
target_link_libraries(qxBlogMongoDB ${QX_LIBRARIES} QxOrm)
|
||||
|
||||
set_target_properties(qxBlogMongoDB PROPERTIES
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
ARCHIVE_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
)
|
||||
|
||||
set_target_properties(qxBlogMongoDB PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
|
||||
|
||||
else() # _QX_ENABLE_MONGODB
|
||||
|
||||
message(STATUS "qxBlogMongoDB project not loaded because _QX_ENABLE_MONGODB option not enabled (QxOrm MongoDB database driver is not available)")
|
||||
|
||||
endif() # _QX_ENABLE_MONGODB
|
||||
7
test/qxBlogMongoDB/debug/.gitignore
vendored
Normal file
7
test/qxBlogMongoDB/debug/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# git does not allow empty directories.
|
||||
# Yet, we need to add this empty directory on git.
|
||||
# To achieve that, we created this .gitignore file, so that the directory will not be empty thus enabling us to commit it.
|
||||
# Since we want all generated files/folders in this directory to be ignored by git, we add a rule for this.
|
||||
*
|
||||
# And then add an exception for this specifc file (so that we can commit it).
|
||||
!.gitignore
|
||||
55
test/qxBlogMongoDB/include/TestQtProperty.h
Normal file
55
test/qxBlogMongoDB/include/TestQtProperty.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#ifndef _QX_TEST_QT_META_PROPERTY_H_
|
||||
#define _QX_TEST_QT_META_PROPERTY_H_
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifdef _QX_NO_PRECOMPILED_HEADER
|
||||
#ifndef Q_MOC_RUN
|
||||
#include "../include/precompiled.h" // Need to include precompiled header for the generated moc file
|
||||
#endif // Q_MOC_RUN
|
||||
#endif // _QX_NO_PRECOMPILED_HEADER
|
||||
|
||||
class QX_BLOG_DLL_EXPORT TestQtProperty : public QObject, public qx::IxPersistable
|
||||
{
|
||||
|
||||
Q_OBJECT
|
||||
QX_PERSISTABLE_HPP(TestQtProperty)
|
||||
Q_PROPERTY(QString id READ id WRITE setId)
|
||||
Q_PROPERTY(long number READ number WRITE setNumber)
|
||||
Q_PROPERTY(QString desc READ desc WRITE setDesc)
|
||||
Q_PROPERTY(QDateTime birthDate READ birthDate WRITE setBirthDate)
|
||||
Q_PROPERTY(QVariant photo READ photo WRITE setPhoto)
|
||||
|
||||
protected:
|
||||
|
||||
QString m_id;
|
||||
long m_number;
|
||||
QString m_desc;
|
||||
QDateTime m_birthDate;
|
||||
QVariant m_photo;
|
||||
|
||||
public:
|
||||
|
||||
TestQtProperty() : QObject(), m_number(0) { ; }
|
||||
virtual ~TestQtProperty() { ; }
|
||||
|
||||
QString id() const { return m_id; }
|
||||
long number() const { return m_number; }
|
||||
QString desc() const { return m_desc; }
|
||||
QDateTime birthDate() const { return m_birthDate; }
|
||||
QVariant photo() const { return m_photo; }
|
||||
|
||||
void setId(const QString & id) { m_id = id; }
|
||||
void setNumber(long l) { m_number = l; }
|
||||
void setDesc(const QString & s) { m_desc = s; }
|
||||
void setBirthDate(const QDateTime & dt) { m_birthDate = dt; }
|
||||
void setPhoto(const QVariant & v) { m_photo = v; }
|
||||
|
||||
};
|
||||
|
||||
QX_REGISTER_PRIMARY_KEY(TestQtProperty, QString)
|
||||
QX_REGISTER_HPP_QX_BLOG(TestQtProperty, QObject, 0)
|
||||
|
||||
#endif // _QX_TEST_QT_META_PROPERTY_H_
|
||||
33
test/qxBlogMongoDB/include/author.h
Normal file
33
test/qxBlogMongoDB/include/author.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef _QX_BLOG_AUTHOR_H_
|
||||
#define _QX_BLOG_AUTHOR_H_
|
||||
|
||||
class blog;
|
||||
|
||||
class QX_BLOG_DLL_EXPORT author
|
||||
{
|
||||
public:
|
||||
// -- typedef
|
||||
typedef std::shared_ptr<blog> blog_ptr;
|
||||
typedef std::vector<blog_ptr> list_blog;
|
||||
// -- enum
|
||||
enum enum_sex { male, female, unknown };
|
||||
// -- properties
|
||||
QString m_id;
|
||||
QString m_name;
|
||||
QDate m_birthdate;
|
||||
enum_sex m_sex;
|
||||
list_blog m_blogX;
|
||||
// -- contructor, virtual destructor
|
||||
author() : m_sex(unknown) { ; }
|
||||
virtual ~author() { ; }
|
||||
// -- methods
|
||||
int age() const;
|
||||
};
|
||||
|
||||
QX_REGISTER_PRIMARY_KEY(author, QString)
|
||||
QX_REGISTER_HPP_QX_BLOG(author, qx::trait::no_base_class_defined, 0)
|
||||
|
||||
typedef std::shared_ptr<author> author_ptr;
|
||||
typedef qx::QxCollection<QString, author_ptr> list_author;
|
||||
|
||||
#endif // _QX_BLOG_AUTHOR_H_
|
||||
29
test/qxBlogMongoDB/include/blog.h
Normal file
29
test/qxBlogMongoDB/include/blog.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef _QX_BLOG_BLOG_H_
|
||||
#define _QX_BLOG_BLOG_H_
|
||||
|
||||
#include "author.h"
|
||||
#include "comment.h"
|
||||
#include "category.h"
|
||||
|
||||
class QX_BLOG_DLL_EXPORT blog
|
||||
{
|
||||
public:
|
||||
// -- properties
|
||||
QString m_id;
|
||||
QString m_text;
|
||||
QDateTime m_dt_creation;
|
||||
author_ptr m_author;
|
||||
list_comment m_commentX;
|
||||
list_category m_categoryX;
|
||||
// -- contructor, virtual destructor
|
||||
blog() { ; }
|
||||
virtual ~blog() { ; }
|
||||
};
|
||||
|
||||
QX_REGISTER_PRIMARY_KEY(blog, QString)
|
||||
QX_REGISTER_HPP_QX_BLOG(blog, qx::trait::no_base_class_defined, 0)
|
||||
|
||||
typedef std::shared_ptr<blog> blog_ptr;
|
||||
typedef std::vector<blog_ptr> list_blog;
|
||||
|
||||
#endif // _QX_BLOG_BLOG_H_
|
||||
28
test/qxBlogMongoDB/include/category.h
Normal file
28
test/qxBlogMongoDB/include/category.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef _QX_BLOG_CATEGORY_H_
|
||||
#define _QX_BLOG_CATEGORY_H_
|
||||
|
||||
class blog;
|
||||
|
||||
class QX_BLOG_DLL_EXPORT category
|
||||
{
|
||||
public:
|
||||
// -- typedef
|
||||
typedef std::shared_ptr<blog> blog_ptr;
|
||||
typedef qx::QxCollection<long, blog_ptr> list_blog;
|
||||
// -- properties
|
||||
QString m_id;
|
||||
QString m_name;
|
||||
QString m_desc;
|
||||
list_blog m_blogX;
|
||||
// -- contructor, virtual destructor
|
||||
category() { ; }
|
||||
virtual ~category() { ; }
|
||||
};
|
||||
|
||||
QX_REGISTER_PRIMARY_KEY(category, QString)
|
||||
QX_REGISTER_HPP_QX_BLOG(category, qx::trait::no_base_class_defined, 0)
|
||||
|
||||
typedef QSharedPointer<category> category_ptr;
|
||||
typedef qx::QxCollection<QString, category_ptr> list_category;
|
||||
|
||||
#endif // _QX_BLOG_CATEGORY_H_
|
||||
27
test/qxBlogMongoDB/include/comment.h
Normal file
27
test/qxBlogMongoDB/include/comment.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef _QX_BLOG_COMMENT_H_
|
||||
#define _QX_BLOG_COMMENT_H_
|
||||
|
||||
class blog;
|
||||
|
||||
class QX_BLOG_DLL_EXPORT comment
|
||||
{
|
||||
public:
|
||||
// -- typedef
|
||||
typedef std::shared_ptr<blog> blog_ptr;
|
||||
// -- properties
|
||||
QString m_id;
|
||||
QString m_text;
|
||||
QDateTime m_dt_create;
|
||||
blog_ptr m_blog;
|
||||
// -- contructor, virtual destructor
|
||||
comment() { ; }
|
||||
virtual ~comment() { ; }
|
||||
};
|
||||
|
||||
QX_REGISTER_PRIMARY_KEY(comment, QString)
|
||||
QX_REGISTER_HPP_QX_BLOG(comment, qx::trait::no_base_class_defined, 0)
|
||||
|
||||
typedef std::shared_ptr<comment> comment_ptr;
|
||||
typedef QList<comment_ptr> list_comment;
|
||||
|
||||
#endif // _QX_BLOG_COMMENT_H_
|
||||
18
test/qxBlogMongoDB/include/export.h
Normal file
18
test/qxBlogMongoDB/include/export.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef _QX_BLOG_EXPORT_H_
|
||||
#define _QX_BLOG_EXPORT_H_
|
||||
|
||||
#ifdef _BUILDING_QX_BLOG
|
||||
#define QX_BLOG_DLL_EXPORT QX_DLL_EXPORT_HELPER
|
||||
#else // _BUILDING_QX_BLOG
|
||||
#define QX_BLOG_DLL_EXPORT QX_DLL_IMPORT_HELPER
|
||||
#endif // _BUILDING_QX_BLOG
|
||||
|
||||
#ifdef _BUILDING_QX_BLOG
|
||||
#define QX_REGISTER_HPP_QX_BLOG QX_REGISTER_HPP_EXPORT_DLL
|
||||
#define QX_REGISTER_CPP_QX_BLOG QX_REGISTER_CPP_EXPORT_DLL
|
||||
#else // _BUILDING_QX_BLOG
|
||||
#define QX_REGISTER_HPP_QX_BLOG QX_REGISTER_HPP_IMPORT_DLL
|
||||
#define QX_REGISTER_CPP_QX_BLOG QX_REGISTER_CPP_IMPORT_DLL
|
||||
#endif // _BUILDING_QX_BLOG
|
||||
|
||||
#endif // _QX_BLOG_EXPORT_H_
|
||||
8
test/qxBlogMongoDB/include/precompiled.h
Normal file
8
test/qxBlogMongoDB/include/precompiled.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef _QX_BLOG_PRECOMPILED_HEADER_H_
|
||||
#define _QX_BLOG_PRECOMPILED_HEADER_H_
|
||||
|
||||
#include <QxOrm.h>
|
||||
|
||||
#include "export.h"
|
||||
|
||||
#endif // _QX_BLOG_PRECOMPILED_HEADER_H_
|
||||
7
test/qxBlogMongoDB/qt/moc/.gitignore
vendored
Normal file
7
test/qxBlogMongoDB/qt/moc/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# git does not allow empty directories.
|
||||
# Yet, we need to add this empty directory on git.
|
||||
# To achieve that, we created this .gitignore file, so that the directory will not be empty thus enabling us to commit it.
|
||||
# Since we want all generated files/folders in this directory to be ignored by git, we add a rule for this.
|
||||
*
|
||||
# And then add an exception for this specifc file (so that we can commit it).
|
||||
!.gitignore
|
||||
40
test/qxBlogMongoDB/qxBlog.pro
Normal file
40
test/qxBlogMongoDB/qxBlog.pro
Normal file
@@ -0,0 +1,40 @@
|
||||
include(../../QxOrm.pri)
|
||||
|
||||
!contains(DEFINES, _QX_ENABLE_MONGODB) {
|
||||
error(unable to use QxOrm MongoDB database driver : please define _QX_ENABLE_MONGODB compilation option in QxOrm.pri configuration file)
|
||||
} # !contains(DEFINES, _QX_ENABLE_MONGODB)
|
||||
|
||||
TEMPLATE = app
|
||||
DEFINES += _BUILDING_QX_BLOG
|
||||
INCLUDEPATH += ../../../QxOrm/include/
|
||||
DESTDIR = ../../../QxOrm/test/_bin/
|
||||
LIBS += -L"../../../QxOrm/lib"
|
||||
|
||||
!contains(DEFINES, _QX_NO_PRECOMPILED_HEADER) {
|
||||
PRECOMPILED_HEADER = ./include/precompiled.h
|
||||
} # !contains(DEFINES, _QX_NO_PRECOMPILED_HEADER)
|
||||
|
||||
macx:CONFIG-=app_bundle
|
||||
|
||||
CONFIG(debug, debug|release) {
|
||||
TARGET = qxBlogMongoDBd
|
||||
LIBS += -l"QxOrmd"
|
||||
} else {
|
||||
TARGET = qxBlogMongoDB
|
||||
LIBS += -l"QxOrm"
|
||||
} # CONFIG(debug, debug|release)
|
||||
|
||||
HEADERS += ./include/precompiled.h
|
||||
HEADERS += ./include/export.h
|
||||
HEADERS += ./include/author.h
|
||||
HEADERS += ./include/blog.h
|
||||
HEADERS += ./include/category.h
|
||||
HEADERS += ./include/comment.h
|
||||
HEADERS += ./include/TestQtProperty.h
|
||||
|
||||
SOURCES += ./src/author.cpp
|
||||
SOURCES += ./src/blog.cpp
|
||||
SOURCES += ./src/category.cpp
|
||||
SOURCES += ./src/comment.cpp
|
||||
SOURCES += ./src/TestQtProperty.cpp
|
||||
SOURCES += ./src/main.cpp
|
||||
7
test/qxBlogMongoDB/release/.gitignore
vendored
Normal file
7
test/qxBlogMongoDB/release/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# git does not allow empty directories.
|
||||
# Yet, we need to add this empty directory on git.
|
||||
# To achieve that, we created this .gitignore file, so that the directory will not be empty thus enabling us to commit it.
|
||||
# Since we want all generated files/folders in this directory to be ignored by git, we add a rule for this.
|
||||
*
|
||||
# And then add an exception for this specifc file (so that we can commit it).
|
||||
!.gitignore
|
||||
25
test/qxBlogMongoDB/src/TestQtProperty.cpp
Normal file
25
test/qxBlogMongoDB/src/TestQtProperty.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#include "../include/precompiled.h"
|
||||
|
||||
#include "../include/TestQtProperty.h"
|
||||
|
||||
#include <QxOrm_Impl.h>
|
||||
|
||||
QX_REGISTER_CPP_QX_BLOG(TestQtProperty)
|
||||
QX_REGISTER_ALL_QT_PROPERTIES(TestQtProperty, "id")
|
||||
QX_PERSISTABLE_CPP(TestQtProperty)
|
||||
|
||||
/*
|
||||
Instead of using 'QX_REGISTER_ALL_QT_PROPERTIES(...)' macro, it's also
|
||||
possible to write classic 'void qx::register_class<T>(...)' function, like this :
|
||||
|
||||
namespace qx {
|
||||
template <> void register_class(QxClass<MyQObject> & t)
|
||||
{ qx::register_all_qt_properties<MyQObject>(t, "my_id"); }
|
||||
} // namespace qx
|
||||
|
||||
So, you can mix Qt meta-properties and classic registration data-member.
|
||||
All is stored using the same interface : 'qx::IxDataMember *'.
|
||||
To more details about advantages and disadvantages of using Qt meta-property,
|
||||
go to the FAQ of QxOrm library :
|
||||
- How to register automatically Qt meta-properties to QxOrm context ?
|
||||
*/
|
||||
28
test/qxBlogMongoDB/src/author.cpp
Normal file
28
test/qxBlogMongoDB/src/author.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#include "../include/precompiled.h"
|
||||
|
||||
#include "../include/author.h"
|
||||
#include "../include/blog.h"
|
||||
|
||||
#include <QxOrm_Impl.h>
|
||||
|
||||
QX_REGISTER_CPP_QX_BLOG(author)
|
||||
|
||||
namespace qx {
|
||||
template <> void register_class(QxClass<author> & t)
|
||||
{
|
||||
t.id(& author::m_id, "author_id");
|
||||
|
||||
t.data(& author::m_name, "name");
|
||||
t.data(& author::m_birthdate, "birthdate")->setIsIndex(true); // Index created automatically with qx::dao::mongodb::QxMongoDB_Helper::autoCreateIndexes() function
|
||||
t.data(& author::m_sex, "sex");
|
||||
|
||||
t.relationOneToMany(& author::m_blogX, "list_blog", "author_id");
|
||||
|
||||
t.fct_0<int>(std::mem_fn(& author::age), "age"); // using std::mem_fn() here is just a workaround for an issue with some versions of MSVC, it is not required with a full compliant C++11 compiler (http://stackoverflow.com/questions/23778883/vs2013-stdfunction-with-member-function)
|
||||
}}
|
||||
|
||||
int author::age() const
|
||||
{
|
||||
if (! m_birthdate.isValid()) { return -1; }
|
||||
return (QDate::currentDate().year() - m_birthdate.year());
|
||||
}
|
||||
20
test/qxBlogMongoDB/src/blog.cpp
Normal file
20
test/qxBlogMongoDB/src/blog.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "../include/precompiled.h"
|
||||
|
||||
#include "../include/blog.h"
|
||||
|
||||
#include <QxOrm_Impl.h>
|
||||
|
||||
QX_REGISTER_CPP_QX_BLOG(blog)
|
||||
|
||||
namespace qx {
|
||||
template <> void register_class(QxClass<blog> & t)
|
||||
{
|
||||
t.id(& blog::m_id, "blog_id");
|
||||
|
||||
t.data(& blog::m_text, "blog_text");
|
||||
t.data(& blog::m_dt_creation, "date_creation");
|
||||
t.data(& blog::m_categoryX, "list_category");
|
||||
|
||||
t.relationManyToOne(& blog::m_author, "author_id");
|
||||
t.relationOneToMany(& blog::m_commentX, "list_comment", "blog_id");
|
||||
}}
|
||||
19
test/qxBlogMongoDB/src/category.cpp
Normal file
19
test/qxBlogMongoDB/src/category.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "../include/precompiled.h"
|
||||
|
||||
#include "../include/category.h"
|
||||
#include "../include/blog.h"
|
||||
|
||||
#include <QxOrm_Impl.h>
|
||||
|
||||
QX_REGISTER_CPP_QX_BLOG(category)
|
||||
|
||||
namespace qx {
|
||||
template <> void register_class(QxClass<category> & t)
|
||||
{
|
||||
t.id(& category::m_id, "category_id");
|
||||
|
||||
t.data(& category::m_name, "name");
|
||||
t.data(& category::m_desc, "description");
|
||||
|
||||
t.relationManyToMany(& category::m_blogX, "list_blog", "category_blog", "category_id", "blog_id");
|
||||
}}
|
||||
19
test/qxBlogMongoDB/src/comment.cpp
Normal file
19
test/qxBlogMongoDB/src/comment.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "../include/precompiled.h"
|
||||
|
||||
#include "../include/comment.h"
|
||||
#include "../include/blog.h"
|
||||
|
||||
#include <QxOrm_Impl.h>
|
||||
|
||||
QX_REGISTER_CPP_QX_BLOG(comment)
|
||||
|
||||
namespace qx {
|
||||
template <> void register_class(QxClass<comment> & t)
|
||||
{
|
||||
t.id(& comment::m_id, "comment_id");
|
||||
|
||||
t.data(& comment::m_text, "comment_text");
|
||||
t.data(& comment::m_dt_create, "date_creation");
|
||||
|
||||
t.relationManyToOne(& comment::m_blog, "blog_id");
|
||||
}}
|
||||
480
test/qxBlogMongoDB/src/main.cpp
Normal file
480
test/qxBlogMongoDB/src/main.cpp
Normal file
@@ -0,0 +1,480 @@
|
||||
#include "../include/precompiled.h"
|
||||
|
||||
#include <QtCore/qcoreapplication.h>
|
||||
|
||||
#include "../include/blog.h"
|
||||
#include "../include/author.h"
|
||||
#include "../include/comment.h"
|
||||
#include "../include/category.h"
|
||||
#include "../include/TestQtProperty.h"
|
||||
|
||||
#include <QxOrm_Impl.h>
|
||||
|
||||
void basicCRUDOnAuthor(bool withDelete);
|
||||
void basicCRUDOnCategory();
|
||||
void basicCRUDOnBlog();
|
||||
void complexQueriesOnBlog();
|
||||
void miscellaneousOperations();
|
||||
void testQtProperty();
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
// Qt application
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
// Following command is recommanded to initialize QxOrm introspection engine
|
||||
qx::QxClassX::registerAllClasses();
|
||||
|
||||
// Parameters to connect to MongoDB database
|
||||
qx::QxSqlDatabase * pDatabase = qx::QxSqlDatabase::getSingleton();
|
||||
pDatabase->setDriverName("QXMONGODB");
|
||||
pDatabase->setDatabaseName("qxBlog");
|
||||
pDatabase->setHostName("localhost");
|
||||
pDatabase->setPort(27017);
|
||||
pDatabase->setUserName("");
|
||||
pDatabase->setPassword("");
|
||||
|
||||
// For debug purpose : log all replies from MongoDB database
|
||||
qx::dao::mongodb::QxMongoDB_Helper::setLogDatabaseReply(true);
|
||||
|
||||
// Clear previous sample database
|
||||
qx_query dropDB("{ \"dropDatabase\" : 1 }");
|
||||
QSqlError daoError = qx::dao::call_query(dropDB); qAssert(! daoError.isValid());
|
||||
|
||||
// To optimize queries : create automatically indexes based on relationships and properties marked as 'index'
|
||||
daoError = qx::dao::mongodb::QxMongoDB_Helper::autoCreateIndexes(true); qAssert(! daoError.isValid());
|
||||
|
||||
// Basic CRUD operations
|
||||
basicCRUDOnAuthor(true);
|
||||
basicCRUDOnAuthor(false);
|
||||
|
||||
// Populate category collection
|
||||
basicCRUDOnCategory();
|
||||
|
||||
// Populate blog collection
|
||||
basicCRUDOnBlog();
|
||||
|
||||
// Process some complex queries on blog collection (with relationships)
|
||||
complexQueriesOnBlog();
|
||||
|
||||
// Process some others operations on database
|
||||
miscellaneousOperations();
|
||||
|
||||
// Test Qt properties registered via QX_REGISTER_ALL_QT_PROPERTIES() macro (https://www.qxorm.com/qxorm_en/manual.html#manual_520)
|
||||
testQtProperty();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void basicCRUDOnAuthor(bool withDelete)
|
||||
{
|
||||
// Test delete all author
|
||||
QSqlError daoError = qx::dao::delete_all<author>(); qAssert(! daoError.isValid());
|
||||
qAssert(qx::dao::count<author>() == 0);
|
||||
|
||||
// Test insert one without id
|
||||
author_ptr author_1 = std::make_shared<author>();
|
||||
author_1->m_name = "author_1";
|
||||
author_1->m_sex = author::male;
|
||||
author_1->m_birthdate = QDate(1998, 07, 12);
|
||||
daoError = qx::dao::insert(author_1); qAssert(! daoError.isValid());
|
||||
qAssert(! author_1->m_id.isEmpty());
|
||||
qAssert(qx::dao::count<author>() == 1);
|
||||
|
||||
// Test insert one author with a custom id
|
||||
author_ptr author_2 = std::make_shared<author>();
|
||||
author_2->m_id = "my_custom_id_author_2";
|
||||
author_2->m_name = "author_2";
|
||||
author_2->m_sex = author::female;
|
||||
author_2->m_birthdate = QDate(2003, 02, 28);
|
||||
daoError = qx::dao::insert(author_2); qAssert(! daoError.isValid());
|
||||
qAssert(author_2->m_id == "my_custom_id_author_2");
|
||||
qAssert(qx::dao::count<author>() == 2);
|
||||
|
||||
// Test insert many author with/without ids
|
||||
QList<author> authorX;
|
||||
author author_3; author_3.m_name = "author_3"; author_3.m_sex = author::female; author_3.m_birthdate = QDate(1968, 05, 01); authorX.append(author_3);
|
||||
author author_4; author_4.m_id = "my_custom_id_author_4"; author_4.m_name = "author_4"; author_4.m_sex = author::male; author_4.m_birthdate = QDate(1980, 12, 19); authorX.append(author_4);
|
||||
author author_5; author_5.m_name = "author_5"; author_5.m_sex = author::female; author_5.m_birthdate = QDate(1978, 03, 03); authorX.append(author_5);
|
||||
daoError = qx::dao::insert(authorX); qAssert(! daoError.isValid());
|
||||
qAssert(qx::dao::count<author>() == 5);
|
||||
qAssert(authorX.at(1).m_id == "my_custom_id_author_4");
|
||||
QString author_3_id = authorX.at(0).m_id; qAssert(! author_3_id.isEmpty());
|
||||
QString author_5_id = authorX.at(2).m_id; qAssert(! author_5_id.isEmpty());
|
||||
|
||||
// Test update one author
|
||||
author_3 = authorX.at(0);
|
||||
author_3.m_name = "author_3_modified";
|
||||
daoError = qx::dao::update(author_3); qAssert(! daoError.isValid());
|
||||
|
||||
// Test update many author
|
||||
authorX.clear();
|
||||
author_3.m_name = "author_3_modified_twice"; authorX.append(author_3);
|
||||
author_2->m_name = "author_2_modified"; authorX.append(* author_2);
|
||||
author_1->m_name = "author_1_modified"; authorX.append(* author_1);
|
||||
daoError = qx::dao::update(authorX); qAssert(! daoError.isValid());
|
||||
qAssert(qx::dao::count<author>() == 5);
|
||||
|
||||
// Test fetch all author (inside QList)
|
||||
authorX.clear();
|
||||
daoError = qx::dao::fetch_all(authorX); qAssert(! daoError.isValid());
|
||||
qAssert(authorX.count() == 5);
|
||||
qx::dump(authorX);
|
||||
|
||||
// Test fetch all author (inside QHash by id)
|
||||
QHash<QString, author_ptr> authorXById;
|
||||
daoError = qx::dao::fetch_all(authorXById); qAssert(! daoError.isValid());
|
||||
qAssert(authorXById.count() == 5);
|
||||
qx::dump(authorXById);
|
||||
|
||||
// Test fetch author by query (only female)
|
||||
list_author list_of_female_author;
|
||||
qx_query query("{ \"sex\" : " + QString::number(static_cast<int>(author::female)) + " }");
|
||||
daoError = qx::dao::fetch_by_query(query, list_of_female_author); qAssert(! daoError.isValid());
|
||||
qAssert(list_of_female_author.count() == 3);
|
||||
qx::dump(list_of_female_author);
|
||||
|
||||
// Test fetch by query using MongoDB aggregation framework (only female)
|
||||
list_author list_of_female_author_other;
|
||||
qx_query queryAggregate("aggregate", "[ { \"$match\" : { \"sex\" : " + QString::number(static_cast<int>(author::female)) + " } } ]");
|
||||
daoError = qx::dao::fetch_by_query(queryAggregate, list_of_female_author_other); qAssert(! daoError.isValid());
|
||||
qAssert(list_of_female_author_other.count() == 3);
|
||||
qx::dump(list_of_female_author_other);
|
||||
|
||||
// Test fetch by query (only female) adding 'sort', 'limit', 'skip', etc... commands (see second query QStringList parameter)
|
||||
list_of_female_author_other.clear();
|
||||
qx_query queryOpts(QStringList() << "{ \"sex\" : " + QString::number(static_cast<int>(author::female)) + " }"
|
||||
<< "{ \"sort\" : { \"sex\" : -1 }, \"limit\" : 2 }");
|
||||
daoError = qx::dao::fetch_by_query(queryOpts, list_of_female_author_other); qAssert(! daoError.isValid());
|
||||
qAssert(list_of_female_author_other.count() == 2);
|
||||
qx::dump(list_of_female_author_other);
|
||||
|
||||
// Test update one author after fetch
|
||||
author_5 = authorX.at(4);
|
||||
author_5.m_name = "author_5_modified_after_fetch";
|
||||
daoError = qx::dao::update(author_5); qAssert(! daoError.isValid());
|
||||
qAssert(qx::dao::count<author>() == 5);
|
||||
|
||||
// Test update many author after fetch
|
||||
author_ptr pAuthor = list_of_female_author.getByIndex(0);
|
||||
pAuthor->m_name = pAuthor->m_name + "_female_modified_after_fetch";
|
||||
pAuthor = list_of_female_author.getByIndex(1);
|
||||
pAuthor->m_name = pAuthor->m_name + "_female_modified_after_fetch";
|
||||
pAuthor = list_of_female_author.getByIndex(2);
|
||||
pAuthor->m_name = pAuthor->m_name + "_female_modified_after_fetch";
|
||||
daoError = qx::dao::update(list_of_female_author); qAssert(! daoError.isValid());
|
||||
qAssert(qx::dao::count<author>() == 5);
|
||||
|
||||
// Test fetch one author by id
|
||||
pAuthor.reset(new author());
|
||||
pAuthor->m_id = "my_custom_id_author_2";
|
||||
daoError = qx::dao::fetch_by_id(pAuthor); qAssert(! daoError.isValid());
|
||||
qAssert(pAuthor->m_id == "my_custom_id_author_2");
|
||||
qAssert(! pAuthor->m_birthdate.isNull());
|
||||
|
||||
// Test fetch many author by id
|
||||
authorX.clear();
|
||||
QHashIterator<QString, author_ptr> itr(authorXById);
|
||||
while (itr.hasNext()) { itr.next(); author author_tmp; author_tmp.m_id = itr.key(); authorX.append(author_tmp); }
|
||||
daoError = qx::dao::fetch_by_id(authorX); qAssert(! daoError.isValid());
|
||||
qAssert(authorX.count() == 5);
|
||||
qAssert(! authorX.at(2).m_birthdate.isNull());
|
||||
qx::dump(authorX);
|
||||
|
||||
if (! withDelete) { return; }
|
||||
|
||||
// Test delete one author by id
|
||||
pAuthor.reset(new author());
|
||||
pAuthor->m_id = "my_custom_id_author_4";
|
||||
daoError = qx::dao::delete_by_id(pAuthor); qAssert(! daoError.isValid());
|
||||
qAssert(qx::dao::count<author>() == 4);
|
||||
|
||||
// Test delete many author by id
|
||||
authorX.clear();
|
||||
{ author author_tmp; author_tmp.m_id = author_3_id; authorX.append(author_tmp); }
|
||||
{ author author_tmp; author_tmp.m_id = author_5_id; authorX.append(author_tmp); }
|
||||
daoError = qx::dao::delete_by_id(authorX); qAssert(! daoError.isValid());
|
||||
qAssert(qx::dao::count<author>() == 2);
|
||||
|
||||
// Test delete author by query (all male)
|
||||
#ifdef Q_COMPILER_INITIALIZER_LISTS
|
||||
int iMale = static_cast<int>(author::male);
|
||||
query = qx_query{ { "sex", iMale } };
|
||||
#else // Q_COMPILER_INITIALIZER_LISTS
|
||||
query = qx_query("{ \"sex\" : " + QString::number(static_cast<int>(author::male)) + " }");
|
||||
#endif // Q_COMPILER_INITIALIZER_LISTS
|
||||
daoError = qx::dao::delete_by_query<author>(query); qAssert(! daoError.isValid());
|
||||
qAssert(qx::dao::count<author>() == 1);
|
||||
|
||||
// Now delete all author
|
||||
daoError = qx::dao::delete_all<author>(); qAssert(! daoError.isValid());
|
||||
qAssert(qx::dao::count<author>() == 0);
|
||||
}
|
||||
|
||||
void basicCRUDOnCategory()
|
||||
{
|
||||
// Create 3 categories
|
||||
category_ptr category_1 = category_ptr(new category());
|
||||
category_ptr category_2 = category_ptr(new category());
|
||||
category_ptr category_3 = category_ptr(new category());
|
||||
|
||||
category_1->m_name = "category_1"; category_1->m_desc = "desc_1";
|
||||
category_2->m_name = "category_2"; category_2->m_desc = "desc_2";
|
||||
category_3->m_name = "category_3"; category_3->m_desc = "desc_3";
|
||||
|
||||
// Insert 3 categories into database, use 'db' parameter for the transaction
|
||||
QSqlError daoError = qx::dao::insert(category_1); qAssert(! daoError.isValid());
|
||||
daoError = qx::dao::insert(category_2); qAssert(! daoError.isValid());
|
||||
daoError = qx::dao::insert(category_3); qAssert(! daoError.isValid());
|
||||
qAssert(qx::dao::count<category>() == 3);
|
||||
}
|
||||
|
||||
void basicCRUDOnBlog()
|
||||
{
|
||||
// Search author_1
|
||||
author_ptr author_1 = std::make_shared<author>();
|
||||
qx_query query("{ \"name\" : \"author_1_modified\" }");
|
||||
QSqlError daoError = qx::dao::fetch_by_query<author>(query, (* author_1)); qAssert(! daoError.isValid());
|
||||
qAssert(author_1 && ! author_1->m_id.isEmpty());
|
||||
|
||||
// Search author_2
|
||||
author_ptr author_2 = std::make_shared<author>();
|
||||
author_2->m_id = "my_custom_id_author_2";
|
||||
daoError = qx::dao::fetch_by_id(author_2); qAssert(! daoError.isValid());
|
||||
qAssert(author_2 && ! author_2->m_id.isEmpty());
|
||||
|
||||
// Create a blog from class name (factory)
|
||||
qx::any blog_any = qx::create("blog");
|
||||
blog_ptr blog_1;
|
||||
try { blog_1 = qx::any_cast<blog_ptr>(blog_any); }
|
||||
catch (...) { blog_1.reset(new blog()); }
|
||||
blog_1->m_text = "blog_text_1";
|
||||
blog_1->m_dt_creation = QDateTime::currentDateTime();
|
||||
blog_1->m_author = author_1;
|
||||
|
||||
// Insert 'blog_1' into database with 'save()' method
|
||||
daoError = qx::dao::save(blog_1); qAssert(! daoError.isValid());
|
||||
qAssert(qx::dao::count<blog>() == 1);
|
||||
|
||||
// Modify 'blog_1' properties and save into database
|
||||
blog_1->m_text = "update blog_text_1";
|
||||
blog_1->m_author = author_2;
|
||||
daoError = qx::dao::save(blog_1); qAssert(! daoError.isValid());
|
||||
qAssert(qx::dao::count<blog>() == 1);
|
||||
|
||||
// Add 2 comments to 'blog_1'
|
||||
comment_ptr comment_1; comment_1.reset(new comment());
|
||||
comment_ptr comment_2; comment_2.reset(new comment());
|
||||
|
||||
comment_1->m_text = "comment_1 text";
|
||||
comment_1->m_dt_create = QDateTime::currentDateTime();
|
||||
comment_1->m_blog = blog_1;
|
||||
comment_2->m_text = "comment_2 text";
|
||||
comment_2->m_dt_create = QDateTime::currentDateTime();
|
||||
comment_2->m_blog = blog_1;
|
||||
|
||||
daoError = qx::dao::insert(comment_1); qAssert(! daoError.isValid());
|
||||
daoError = qx::dao::insert(comment_2); qAssert(! daoError.isValid());
|
||||
qAssert(qx::dao::count<comment>() == 2);
|
||||
|
||||
// Add 2 categories to 'blog_1' => 'list_category' is not defined as relationship in 'blog' class => so all categories are embedded in 'blog' collection (instead of referenced for relationships)
|
||||
list_category categories;
|
||||
daoError = qx::dao::fetch_all(categories); qAssert(! daoError.isValid());
|
||||
qAssert(categories.count() == 3);
|
||||
|
||||
category_ptr category_1 = categories.getByIndex(0);
|
||||
category_ptr category_3 = categories.getByIndex(2);
|
||||
blog_1->m_categoryX.insert(category_1->m_id, category_1);
|
||||
blog_1->m_categoryX.insert(category_3->m_id, category_3);
|
||||
daoError = qx::dao::save(blog_1); qAssert(! daoError.isValid());
|
||||
qAssert(qx::dao::count<blog>() == 1);
|
||||
|
||||
// Push a second blog
|
||||
blog_ptr blog_2 = std::make_shared<blog>();
|
||||
blog_2->m_text = "blog_text_2";
|
||||
daoError = qx::dao::save(blog_2); qAssert(! daoError.isValid());
|
||||
}
|
||||
|
||||
void complexQueriesOnBlog()
|
||||
{
|
||||
// Fetch all blogs (without relation)
|
||||
list_blog allBlogs;
|
||||
QSqlError daoError = qx::dao::fetch_all(allBlogs); qAssert(! daoError.isValid());
|
||||
qx::dump(allBlogs);
|
||||
qAssert(allBlogs.size() == 2);
|
||||
|
||||
// Fetch blog into a new variable with all relations : 'author', 'comment' and 'category' (MongoDB version 3.6+ is required for relationships)
|
||||
blog_ptr blog_tmp = std::make_shared<blog>();
|
||||
blog_tmp->m_id = allBlogs[0]->m_id;
|
||||
daoError = qx::dao::fetch_by_id_with_all_relation(blog_tmp); qAssert(! daoError.isValid());
|
||||
qx::dump(blog_tmp);
|
||||
qAssert(blog_tmp->m_commentX.count() == 2);
|
||||
qAssert(blog_tmp->m_categoryX.count() == 2);
|
||||
qAssert(blog_tmp->m_text == "update blog_text_1");
|
||||
qAssert(blog_tmp->m_author && (blog_tmp->m_author->m_id == "my_custom_id_author_2"));
|
||||
|
||||
// Fetch blog into a new variable with many relations using "*->*->*->*" (4 levels of relationships)
|
||||
blog_tmp.reset(new blog());
|
||||
blog_tmp->m_id = allBlogs[0]->m_id;
|
||||
daoError = qx::dao::fetch_by_id_with_relation("*->*->*->*", blog_tmp); qAssert(! daoError.isValid());
|
||||
qx::dump(blog_tmp);
|
||||
qAssert(blog_tmp->m_commentX.count() == 2);
|
||||
qAssert(blog_tmp->m_categoryX.count() == 2);
|
||||
qAssert(blog_tmp->m_text == "update blog_text_1");
|
||||
qAssert(blog_tmp->m_author && blog_tmp->m_author->m_id == "my_custom_id_author_2");
|
||||
qAssert(blog_tmp->m_author->m_blogX[0]->m_commentX.count() > 0);
|
||||
|
||||
// Fetch blog into a new variable with many relations using "*->*" (2 levels of relationships)
|
||||
blog_tmp.reset(new blog());
|
||||
blog_tmp->m_id = allBlogs[0]->m_id;
|
||||
daoError = qx::dao::fetch_all_with_relation("*->*", blog_tmp); qAssert(! daoError.isValid());
|
||||
qx::dump(blog_tmp);
|
||||
qAssert(blog_tmp->m_commentX.count() == 2);
|
||||
qAssert(blog_tmp->m_categoryX.count() == 2);
|
||||
qAssert(blog_tmp->m_text == "update blog_text_1");
|
||||
qAssert(blog_tmp->m_author && blog_tmp->m_author->m_id == "my_custom_id_author_2");
|
||||
qAssert(blog_tmp->m_author->m_blogX[0]->m_commentX.count() == 0);
|
||||
|
||||
// Fetch only property 'm_dt_creation' of blog
|
||||
QStringList lstColumns = QStringList() << "date_creation";
|
||||
list_blog lst_blog_with_only_date_creation;
|
||||
daoError = qx::dao::fetch_all(lst_blog_with_only_date_creation, NULL, lstColumns);
|
||||
qAssert(! daoError.isValid() && (lst_blog_with_only_date_creation.size() > 0));
|
||||
if ((lst_blog_with_only_date_creation.size() > 0) && (lst_blog_with_only_date_creation[0].get() != NULL))
|
||||
{ qAssert(lst_blog_with_only_date_creation[0]->m_text.isEmpty()); }
|
||||
qx::dump(lst_blog_with_only_date_creation);
|
||||
|
||||
// Fetch relations defining fields to fetch with syntax { col_1, col_2, etc... }
|
||||
list_blog lstBlogComplexRelation;
|
||||
daoError = qx::dao::fetch_all_with_relation(QStringList() << "{ blog_text }" << "author_id { name, birthdate }" << "list_comment { comment_text } -> blog_id -> *", lstBlogComplexRelation); qAssert(! daoError.isValid());
|
||||
qx::dump(lstBlogComplexRelation);
|
||||
qAssert(lstBlogComplexRelation.size() > 0);
|
||||
qAssert(lstBlogComplexRelation[0]->m_text != ""); // Fetched
|
||||
qAssert(lstBlogComplexRelation[0]->m_dt_creation.isNull()); // Not fetched
|
||||
qAssert(lstBlogComplexRelation[0]->m_author->m_sex == author::unknown); // Not fetched
|
||||
qAssert(lstBlogComplexRelation[0]->m_author->m_name != ""); // Fetched
|
||||
qAssert(lstBlogComplexRelation[0]->m_commentX.size() > 0);
|
||||
qAssert(lstBlogComplexRelation[0]->m_commentX[0]->m_dt_create.isNull()); // Not fetched
|
||||
qAssert(lstBlogComplexRelation[0]->m_commentX[0]->m_text != ""); // Fetched
|
||||
qAssert(lstBlogComplexRelation[0]->m_commentX[0]->m_blog);
|
||||
|
||||
// Fetch relations defining columns to remove before fetching with syntax -{ col_1, col_2, etc... }
|
||||
list_blog lstBlogComplexRelation2;
|
||||
daoError = qx::dao::fetch_all_with_relation(QStringList() << "- { blog_text }" << "author_id -{ name, birthdate }" << "list_comment -{ comment_text } -> blog_id -> *", lstBlogComplexRelation2); qAssert(! daoError.isValid());
|
||||
qx::dump(lstBlogComplexRelation2);
|
||||
qAssert(lstBlogComplexRelation2.size() > 0);
|
||||
qAssert(lstBlogComplexRelation2[0]->m_text == ""); // Not fetched
|
||||
qAssert(! lstBlogComplexRelation2[0]->m_dt_creation.isNull()); // Fetched
|
||||
qAssert(lstBlogComplexRelation2[0]->m_author->m_sex != author::unknown); // Fetched
|
||||
qAssert(lstBlogComplexRelation2[0]->m_author->m_name == ""); // Not fetched
|
||||
qAssert(lstBlogComplexRelation2[0]->m_commentX.size() > 0);
|
||||
qAssert(! lstBlogComplexRelation2[0]->m_commentX[0]->m_dt_create.isNull()); // Fetched
|
||||
qAssert(lstBlogComplexRelation2[0]->m_commentX[0]->m_text == ""); // Not fetched
|
||||
qAssert(lstBlogComplexRelation2[0]->m_commentX[0]->m_blog);
|
||||
|
||||
// Check qx::dao::save_with_relation_recursive() function
|
||||
daoError = qx::dao::save_with_relation_recursive(blog_tmp); qAssert(! daoError.isValid());
|
||||
daoError = qx::dao::save_with_relation_recursive(blog_tmp, qx::dao::save_mode::e_update_only); qAssert(! daoError.isValid());
|
||||
|
||||
// Fetch the second blog stored in database
|
||||
blog_tmp = std::make_shared<blog>();
|
||||
blog_tmp->m_id = allBlogs[1]->m_id;
|
||||
daoError = qx::dao::fetch_by_id_with_all_relation(blog_tmp); qAssert(! daoError.isValid());
|
||||
qx::dump(blog_tmp);
|
||||
qAssert(blog_tmp->m_text == "blog_text_2");
|
||||
qAssert(blog_tmp->m_author == NULL);
|
||||
qAssert(blog_tmp->m_categoryX.size() == 0);
|
||||
qAssert(blog_tmp->m_commentX.size() == 0);
|
||||
|
||||
// Fetch 2 blogs by id with their relationships
|
||||
QList<blog_ptr> lstBlogById;
|
||||
blog_tmp = std::make_shared<blog>(); blog_tmp->m_id = allBlogs[1]->m_id; lstBlogById.append(blog_tmp);
|
||||
blog_tmp = std::make_shared<blog>(); blog_tmp->m_id = allBlogs[0]->m_id; lstBlogById.append(blog_tmp);
|
||||
daoError = qx::dao::fetch_by_id_with_all_relation(lstBlogById); qAssert(! daoError.isValid());
|
||||
qx::dump(lstBlogById);
|
||||
}
|
||||
|
||||
void miscellaneousOperations()
|
||||
{
|
||||
// Dump all registered classes into QxOrm context (introspection engine)
|
||||
qx::QxClassX::dumpAllClasses();
|
||||
|
||||
// Call 'age()' method with class name and method name (reflexion)
|
||||
author author_1; qx_bool bInvokeOk = qx::QxClassX::invoke("author", "age", author_1); qAssert(bInvokeOk);
|
||||
|
||||
// Fetch all blogs (without relation)
|
||||
list_blog allBlogs; QSqlError daoError = qx::dao::fetch_all(allBlogs); qAssert(! daoError.isValid());
|
||||
qx::dump(allBlogs); qAssert(allBlogs.size() == 2);
|
||||
|
||||
// Test 'isDirty()' method
|
||||
qx::dao::ptr<blog> blog_isdirty = qx::dao::ptr<blog>(new blog());
|
||||
blog_isdirty->m_id = allBlogs[0]->m_id;
|
||||
daoError = qx::dao::fetch_by_id(blog_isdirty);
|
||||
qAssert(! daoError.isValid() && ! blog_isdirty.isDirty());
|
||||
|
||||
blog_isdirty->m_text = "blog property 'text' modified => blog is dirty !!!";
|
||||
QStringList lstDiff; bool bDirty = blog_isdirty.isDirty(lstDiff);
|
||||
qAssert(bDirty && (lstDiff.count() == 1) && (lstDiff.at(0) == "blog_text"));
|
||||
if (bDirty) { qDebug("[QxOrm] test dirty 1 : blog is dirty => '%s'", qPrintable(lstDiff.join("|"))); }
|
||||
|
||||
// Update only property 'm_text' of 'blog_isdirty'
|
||||
daoError = qx::dao::update_optimized(blog_isdirty);
|
||||
qAssert(! daoError.isValid() && ! blog_isdirty.isDirty());
|
||||
qx::dump(blog_isdirty);
|
||||
|
||||
// Test 'isDirty()' method with a container
|
||||
typedef qx::dao::ptr< QList<author_ptr> > type_lst_author_test_is_dirty;
|
||||
type_lst_author_test_is_dirty container_isdirty = type_lst_author_test_is_dirty(new QList<author_ptr>());
|
||||
daoError = qx::dao::fetch_all(container_isdirty);
|
||||
qAssert(! daoError.isValid() && ! container_isdirty.isDirty() && (container_isdirty->count() == qx::dao::count<author>()));
|
||||
|
||||
author_ptr author_ptr_dirty = container_isdirty->at(1);
|
||||
author_ptr_dirty->m_name = "author name modified at index 1 => container is dirty !!!";
|
||||
bDirty = container_isdirty.isDirty(lstDiff);
|
||||
qAssert(bDirty && (lstDiff.count() == 1));
|
||||
if (bDirty) { qDebug("[QxOrm] test dirty 2 : container is dirty => '%s'", qPrintable(lstDiff.join("|"))); }
|
||||
|
||||
author_ptr_dirty = container_isdirty->at(2);
|
||||
author_ptr_dirty->m_birthdate = QDate(1998, 03, 06);
|
||||
bDirty = container_isdirty.isDirty(lstDiff);
|
||||
qAssert(bDirty && (lstDiff.count() == 2));
|
||||
if (bDirty) { qDebug("[QxOrm] test dirty 3 : container is dirty => '%s'", qPrintable(lstDiff.join("|"))); }
|
||||
|
||||
// Update only property 'm_name' at position 1, only property 'm_birthdate' at position 2 and nothing at position 0
|
||||
daoError = qx::dao::update_optimized(container_isdirty);
|
||||
qAssert(! daoError.isValid() && ! container_isdirty.isDirty());
|
||||
qx::dump(container_isdirty);
|
||||
|
||||
// Call a custom query and get JSON response as QVariantMap
|
||||
qx_query customQuery("{ \"find\": \"author\", \"filter\": { } }");
|
||||
daoError = qx::dao::call_query(customQuery); qAssert(! daoError.isValid());
|
||||
QString responseCustomQuery = customQuery.response().toString();
|
||||
QVariantMap responseCustomQueryAsJson;
|
||||
qx::serialization::json::from_string(responseCustomQueryAsJson, responseCustomQuery);
|
||||
qx::dump(responseCustomQueryAsJson);
|
||||
|
||||
// Call a custom query with cursor and get JSON response as QList<QVariantMap>
|
||||
qx_query customQueryCursor("cursor", "{ \"find\": \"author\", \"filter\": { } }");
|
||||
daoError = qx::dao::call_query(customQueryCursor); qAssert(! daoError.isValid());
|
||||
QString responseCustomQueryCursor = customQueryCursor.response().toString();
|
||||
QList<QVariantMap> responseCustomQueryCursorAsJson;
|
||||
qx::serialization::json::from_string(responseCustomQueryCursorAsJson, responseCustomQueryCursor);
|
||||
qx::dump(responseCustomQueryCursorAsJson);
|
||||
qAssert(responseCustomQueryCursorAsJson.count() == qx::dao::count<author>());
|
||||
|
||||
// Test delete by query using MongoDB aggregation framework (delete all female)
|
||||
qx_query queryAggregate("aggregate", "[ { \"$match\" : { \"sex\" : " + QString::number(static_cast<int>(author::female)) + " } } ]");
|
||||
daoError = qx::dao::delete_by_query<author>(queryAggregate); qAssert(! daoError.isValid());
|
||||
qAssert(qx::dao::count<author>() == 2);
|
||||
}
|
||||
|
||||
void testQtProperty()
|
||||
{
|
||||
TestQtProperty tst;
|
||||
tst.setDesc("tst");
|
||||
QSqlError daoError = qx::dao::insert(tst); qAssert(! daoError.isValid());
|
||||
tst.setDesc("tst update");
|
||||
daoError = qx::dao::update(tst); qAssert(! daoError.isValid());
|
||||
daoError = qx::dao::fetch_by_id(tst); qAssert(! daoError.isValid());
|
||||
std::shared_ptr<qx::IxPersistableCollection> lst = qx::IxPersistable::qxFetchAll("TestQtProperty"); qAssert(lst->__count() == 1);
|
||||
}
|
||||
56
test/qxBlogPImpl/CMakeLists.txt
Normal file
56
test/qxBlogPImpl/CMakeLists.txt
Normal file
@@ -0,0 +1,56 @@
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
project(qxBlogPImpl LANGUAGES CXX)
|
||||
|
||||
include(../../QxOrm.cmake)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
set(CMAKE_DEBUG_POSTFIX "d")
|
||||
|
||||
set(HEADERS
|
||||
./include/precompiled.h
|
||||
./include/export.h
|
||||
./include/author.h
|
||||
./include/blog.h
|
||||
./include/category.h
|
||||
./include/comment.h
|
||||
)
|
||||
|
||||
set(SRCS
|
||||
./src/author.cpp
|
||||
./src/blog.cpp
|
||||
./src/category.cpp
|
||||
./src/comment.cpp
|
||||
./src/main.cpp
|
||||
)
|
||||
|
||||
add_executable(qxBlogPImpl ${SRCS} ${HEADERS})
|
||||
|
||||
target_compile_definitions(qxBlogPImpl PRIVATE -D_BUILDING_QX_BLOG)
|
||||
|
||||
if(COMMAND target_precompile_headers)
|
||||
target_precompile_headers(qxBlogPImpl PRIVATE ./include/precompiled.h)
|
||||
endif() # (COMMAND target_precompile_headers)
|
||||
|
||||
target_link_libraries(qxBlogPImpl ${QX_LIBRARIES} QxOrm)
|
||||
|
||||
set_target_properties(qxBlogPImpl PROPERTIES
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
ARCHIVE_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_CURRENT_SOURCE_DIR}/../_bin"
|
||||
)
|
||||
|
||||
set_target_properties(qxBlogPImpl PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user