make master identical with dev

This commit is contained in:
Hamed Masafi 2021-06-25 11:18:02 +04:30
commit 8b8a3c37a9
230 changed files with 3558 additions and 5001 deletions

View File

@ -9,6 +9,7 @@ jobs:
matrix: matrix:
version: version:
- 5.15.0 - 5.15.0
platform: platform:
- gcc_64 - gcc_64
- android - android
@ -43,8 +44,6 @@ jobs:
os: windows-latest os: windows-latest
- platform: clang_64 - platform: clang_64
os: macos-latest os: macos-latest
- platform: ios
os: macos-latest
runs-on: ${{matrix.os}} runs-on: ${{matrix.os}}
steps: steps:
@ -62,11 +61,16 @@ jobs:
run: | run: |
qmake CONFIG+=install_ok QT_PLATFORM=${{matrix.platform}} "QT_TOOL_PATH=${{steps.qt.outputs.qtdir}}/Tools" nut.pro qmake CONFIG+=install_ok QT_PLATFORM=${{matrix.platform}} "QT_TOOL_PATH=${{steps.qt.outputs.qtdir}}/Tools" nut.pro
${{steps.qt.outputs.make}} qmake_all ${{steps.qt.outputs.make}} qmake_all
- name: make lib - name: make module
run: | run: |
${{steps.qt.outputs.make}} ${{steps.qt.outputs.make}}
${{steps.qt.outputs.make}} INSTALL_ROOT="${{steps.qt.outputs.installdir}}" install ${{steps.qt.outputs.make}} INSTALL_ROOT="${{steps.qt.outputs.installdir}}" install
- name: upload lib to releases - name: make tests
if: steps.qt.outputs.tests == 'true'
run: |
${{steps.qt.outputs.make}} all
${{steps.qt.outputs.make}} ${{steps.qt.outputs.testflags}} run-tests
- name: upload module to releases
uses: Skycoder42/action-upload-release@master uses: Skycoder42/action-upload-release@master
if: startsWith(github.ref, 'refs/tags/') if: startsWith(github.ref, 'refs/tags/')
with: with:

1
.gitignore vendored
View File

@ -35,6 +35,7 @@ Makefile*
*.qmlproject.user.* *.qmlproject.user.*
build build
build2
# KDE show hidden folder marker # KDE show hidden folder marker
.directory .directory

4
.gitmodules vendored
View File

@ -1,3 +1,3 @@
[submodule "3rdparty/serializer"] [submodule "src/nut/3rdparty/serializer"]
path = 3rdparty/serializer path = src/nut/3rdparty/serializer
url = https://github.com/HamedMasafi/Serializer.git url = https://github.com/HamedMasafi/Serializer.git

13
.qmake.conf Normal file
View File

@ -0,0 +1,13 @@
load(qt_build_config)
CONFIG += warning_clean exceptions qt_module_build c++17
DEFINES += QT_DEPRECATED_WARNINGS QT_ASCII_CAST_WARNINGS
MODULE_VERSION = 0.6.0
# had to be added because std::visit only works on macos 10.14 and above
# remove again once Qt raises the value to 10.14!
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.14
QMAKE_IOS_DEPLOYMENT_TARGET = 12.0

1
3rdparty/serializer vendored

@ -1 +0,0 @@
Subproject commit 0e794d6317595d077e95e8a06f1f3a8c92543b05

2403
Doxyfile

File diff suppressed because it is too large Load Diff

11
deploy.json Normal file
View File

@ -0,0 +1,11 @@
{
"title": "QtNut",
"description": "Advanced, Powerful and easy to use ORM for Qt5.",
"modules": [ "QtNut" ],
"dependencies": [],
"excludes": [],
"license": {
"name": "LGPL-3",
"path": "LICENSE"
}
}

View File

@ -4,23 +4,23 @@ In *shared pointer* mode results of queries is QList<QSharedPointer<T>> and in *
Almost in every case shared pointer mode is better, But nut support regular mode for backward comptability. Almost in every case shared pointer mode is better, But nut support regular mode for backward comptability.
To compiling in *shared pointer* define **NUT_SHARED_POINTER** macro By default _Nut_ compiles in shared pointer mode, to switch to ols raw pointer mode you must define **NUT_RAW_POINTER** macro
Nut has template alias Nut has template alias
```cpp ```cpp
#ifdef NUT_SHARED_POINTER #ifdef NUT_RAW_POINTER
template <typename T>
using RowList = QList<QSharedPointer<T>>;
template <typename T>
using Row = QSharedPointer<T>;
#else
template <typename T> template <typename T>
using RowList = QList<T*>; using RowList = QList<T*>;
template <typename T> template <typename T>
using Row = T*; using Row = T*;
#else
template <typename T>
using RowList = QList<QSharedPointer<T>>;
template <typename T>
using Row = QSharedPointer<T>;
#endif #endif
``` ```
@ -36,16 +36,16 @@ For the integration of your source, you can use these aliases.
Ans also Nut::create<T>() method are defined for two mode Ans also Nut::create<T>() method are defined for two mode
```cpp ```cpp
#ifdef NUT_SHARED_POINTER #ifdef NUT_RAW_POINTER
template<class T>
inline Row<T> create(QObject *parent) {
return QSharedPointer<T>(new T(parent));
}
#else
template<class T> template<class T>
inline Row<T> create() { inline Row<T> create() {
return new T; return new T;
} }
#else
template<class T>
inline Row<T> create(QObject *parent) {
return QSharedPointer<T>(new T(parent));
}
#endif #endif
``` ```
@ -54,6 +54,6 @@ So you can use the Nut::create function without considering in what way the libr
auto post = Nut::create<Post>(); auto post = Nut::create<Post>();
``` ```
In above example if *NUT_SHARED_POINTER* is defined *post* is *QSharedPointer<Post>* else is *Post\** In above example if *NUT_RAW_POINTER* is defined *post* is *Post\** else is *QSharedPointer<Post>*
I recommand use *NUT_SHARED_POINTER* always! I recommand use shared pointer mode (default) always!

View File

@ -1 +0,0 @@
#include "../src/database.h"

View File

@ -1 +0,0 @@
#include "../src/types/dbgeography.h"

View File

@ -1,7 +0,0 @@
#include "../src/table.h"
#include "../src/database.h"
#include "../src/sqlmodel.h"
#include "../src/tableset.h"
#include "../src/tablemodel.h"
#include "../src/query.h"

View File

@ -1 +0,0 @@
#include "../src/query.h"

View File

@ -1 +0,0 @@
#include "../src/sqlmodel.h"

View File

@ -1 +0,0 @@
#include "../src/table.h"

View File

@ -1 +0,0 @@
#include "../src/tablemodel.h"

View File

@ -1 +0,0 @@
#include "../src/tableset.h"

View File

@ -1 +0,0 @@
#include "../src/database.h"

View File

@ -1 +0,0 @@
#include "../src/types/dbgeography.h"

View File

@ -1,42 +0,0 @@
#!/bin/bash
src_dir="src"
namespace_name="nut"
#ns=$(echo $namespace_name|awk '{print tolower($0)}')
Ns="Nut"
NS=$(echo $namespace_name|awk '{print toupper($0)}')
create_sub_folder=true
exec 3< <(egrep -o "class\s${NS}_EXPORT\s(\S+)" "../$src_dir" -R 2>&1)
pattern="\.\.\/$src_dir\/([a-z]+)\.h\:class\s${NS}_EXPORT\s(\w+)"
echo "" > "$Ns"
echo "" > "$ns.h"
if [[ -z create_sub_folder ]]; then
mkdir -p $Ns
fi
while read line; do
if [[ $line =~ $pattern ]]; then
header=${BASH_REMATCH[1]}
class=${BASH_REMATCH[2]}
echo "#include \"../$src_dir/$header.h\"" > $class
echo "#include \"../$src_dir/$header.h\"" > "$header.h"
if [[ -z create_sub_folder ]]; then
echo "#include \"../$src_dir/$header.h\"" > "$Ns/$class"
echo "#include \"../$src_dir/$header.h\"" > "$Ns/$header.h"
fi
echo "#include \"../$src_dir/$header.h\"" >> "$Ns"
echo "#include \"../$src_dir/$header.h\"" >> "$ns.h"
fi
echo $Ns
done <&3
exec 3<&-

View File

@ -1,7 +0,0 @@
#include "../src/table.h"
#include "../src/database.h"
#include "../src/sqlmodel.h"
#include "../src/tableset.h"
#include "../src/tablemodel.h"
#include "../src/query.h"

View File

@ -1 +0,0 @@
#include "../src/query.h"

View File

@ -1 +0,0 @@
#include "../src/sqlmodel.h"

View File

@ -1 +0,0 @@
#include "../src/table.h"

View File

@ -1 +0,0 @@
#include "../src/tablemodel.h"

View File

@ -1 +0,0 @@
#include "../src/tableset.h"

81
nut.pri
View File

@ -1,81 +0,0 @@
QT += core sql
CONFIG += c++11
INCLUDEPATH += $$PWD/include
DEFINES += NUT_SHARED_POINTER
!exists(3rdparty/serializer/src/src.pri) {
error("Please do git submodule update --init --recursive in the Nut directory")
}
include(3rdparty/serializer/src/src.pri)
HEADERS += \
$$PWD/src/generators/sqlgeneratorbase_p.h \
$$PWD/src/generators/postgresqlgenerator.h \
$$PWD/src/generators/mysqlgenerator.h \
$$PWD/src/generators/sqlitegenerator.h \
$$PWD/src/generators/sqlservergenerator.h \
$$PWD/src/types/dbgeography.h \
$$PWD/src/tableset.h \
$$PWD/src/defines_p.h \
$$PWD/src/defines.h \
$$PWD/src/query.h \
$$PWD/src/databasemodel.h \
$$PWD/src/changelogtable.h \
$$PWD/src/tablesetbase_p.h \
$$PWD/src/querybase_p.h \
$$PWD/src/tablemodel.h \
$$PWD/src/query_p.h \
$$PWD/src/table.h \
$$PWD/src/database.h \
$$PWD/src/database_p.h \
$$PWD/src/serializableobject.h \
$$PWD/src/sqlmodel.h \
$$PWD/src/sqlmodel_p.h \
$$PWD/src/phrase.h \
$$PWD/src/tuple.h \
$$PWD/src/phrases/conditionalphrase.h \
$$PWD/src/phrases/abstractfieldphrase.h \
$$PWD/src/phrases/fieldphrase.h \
$$PWD/src/phrases/phraselist.h \
$$PWD/src/phrases/assignmentphraselist.h \
$$PWD/src/phrases/phrasedatalist.h \
$$PWD/src/phrases/phrasedata.h \
$$PWD/src/phrases/assignmentphrase.h \
$$PWD/src/phrases/numericphrase.h \
$$PWD/src/phrases/datephrase.h \
$$PWD/src/bulkinserter.h
SOURCES += \
$$PWD/src/generators/sqlgeneratorbase.cpp \
$$PWD/src/generators/postgresqlgenerator.cpp \
$$PWD/src/generators/mysqlgenerator.cpp \
$$PWD/src/generators/sqlitegenerator.cpp \
$$PWD/src/generators/sqlservergenerator.cpp \
$$PWD/src/types/dbgeography.cpp \
$$PWD/src/tableset.cpp \
$$PWD/src/query.cpp \
$$PWD/src/databasemodel.cpp \
$$PWD/src/tablesetbase.cpp \
$$PWD/src/changelogtable.cpp \
$$PWD/src/querybase.cpp \
$$PWD/src/tablemodel.cpp \
$$PWD/src/table.cpp \
$$PWD/src/database.cpp \
$$PWD/src/serializableobject.cpp \
$$PWD/src/sqlmodel.cpp \
$$PWD/src/phrase.cpp \
$$PWD/src/tuple.cpp \
$$PWD/src/phrases/conditionalphrase.cpp \
$$PWD/src/phrases/abstractfieldphrase.cpp \
$$PWD/src/phrases/fieldphrase.cpp \
$$PWD/src/phrases/phraselist.cpp \
$$PWD/src/phrases/assignmentphraselist.cpp \
$$PWD/src/phrases/phrasedatalist.cpp \
$$PWD/src/phrases/phrasedata.cpp \
$$PWD/src/phrases/assignmentphrase.cpp \
$$PWD/src/phrases/numericphrase.cpp \
$$PWD/src/phrases/datephrase.cpp \
$$PWD/src/bulkinserter.cpp

14
nut.pro
View File

@ -1,6 +1,10 @@
TEMPLATE = subdirs load(qt_parts)
CONFIG += ordered
SUBDIRS += \
src \
test
runtests.target = run-tests
runtests.CONFIG = recursive
runtests.recurse_target = run-tests
runtests.recurse += sub_tests sub_src
QMAKE_EXTRA_TARGETS += runtests
DISTFILES += .qmake.conf \
sync.profile

53
nut.qbs
View File

@ -1,53 +0,0 @@
import qbs
Project {
// StaticLibrary {
// name: "nut_static"
// files: [
// "src/*.h",
// "src/*.cpp",
// "src/generators/*.h",
// "src/generators/*.cpp"
// ]
// Depends { name: 'cpp' }
// Depends { name: "Qt.core" }
// Depends { name: "Qt.sql" }
// Group { qbs.install: true; fileTagsFilter: product.type;}
// Export {
// Depends { name: "cpp" }
// Depends { name: "Qt.core" }
// Depends { name: "Qt.sql" }
// cpp.includePaths: [
// product.sourceDirectory + "/src",
// product.sourceDirectory + "/include"
// ]
// }
// }
DynamicLibrary {
name: "nut"
files: [
"src/*.h",
"src/*.cpp",
"src/generators/*.h",
"src/generators/*.cpp"
]
Depends { name: 'cpp' }
Depends { name: "Qt.core" }
Depends { name: "Qt.sql" }
Group { qbs.install: true; fileTagsFilter: product.type;}
Export {
Depends { name: "cpp" }
Depends { name: "Qt.core" }
Depends { name: "Qt.sql" }
cpp.includePaths: [
product.sourceDirectory + "/src",
product.sourceDirectory + "/include"
]
}
}
}

View File

@ -1,24 +0,0 @@
project = Nut
description = Advanced, Powerful and easy to use ORM for Qt5
version = 0.1
outputdir = doc
source += src/query.cpp
headerdirs += src
sourcedirs += src
exampledirs = .
qhp.projects = Nut
qhp.qtestclass.file = nut.qhp
qhp.qtestclass.namespace = org.kaj.nut.0.1
qhp.qtestclass.virtualFolder = nut
qhp.qtestclass.indexTitle = nut
qhp.qtestclass.indexRoot =
qhp.qtestclass.filterAttributes = nut 0.1 qtrefdoc
qhp.qtestclass.customFilters.Qt.name = qtestclass 0.1
qhp.qtestclass.customFilters.Qt.filterAttributes = qtestclass 0.1

22
src/.qmake.stash Normal file
View File

@ -0,0 +1,22 @@
QMAKE_CXX.QT_COMPILER_STDCXX = 201402L
QMAKE_CXX.QMAKE_GCC_MAJOR_VERSION = 10
QMAKE_CXX.QMAKE_GCC_MINOR_VERSION = 2
QMAKE_CXX.QMAKE_GCC_PATCH_VERSION = 1
QMAKE_CXX.COMPILER_MACROS = \
QT_COMPILER_STDCXX \
QMAKE_GCC_MAJOR_VERSION \
QMAKE_GCC_MINOR_VERSION \
QMAKE_GCC_PATCH_VERSION
QMAKE_CXX.INCDIRS = \
/usr/include/c++/10 \
/usr/include/c++/10/x86_64-redhat-linux \
/usr/include/c++/10/backward \
/usr/lib/gcc/x86_64-redhat-linux/10/include \
/usr/local/include \
/usr/include
QMAKE_CXX.LIBDIRS = \
/usr/lib/gcc/x86_64-redhat-linux/10 \
/usr/lib64 \
/lib64 \
/usr/lib \
/lib

View File

@ -1,43 +0,0 @@
#include "bulkinserter.h"
#include "phrases/phraselist.h"
#include "database.h"
#include "generators/sqlgeneratorbase_p.h"
#include "databasemodel.h"
#include <QDebug>
Nut::BulkInserter::BulkInserter(Nut::Database *db, QString &className)
: _database(db), _fieldCount(0)
{
foreach (TableModel *m, db->model())
if (m->className() == className)
_className = m->name();
}
void Nut::BulkInserter::setFields(const Nut::PhraseList &ph)
{
_fields = ph;
_fieldCount = static_cast<size_t>(ph.data.count());
}
void Nut::BulkInserter::insert(std::initializer_list<QVariant> vars)
{
if (vars.size() != _fieldCount) {
qInfo("Number of rows mistake");
return;
}
QVariantList list;
std::initializer_list<QVariant>::iterator it;
for (it = vars.begin(); it != vars.end(); ++it)
list.append(*it);
variants.append(list);
}
int Nut::BulkInserter::apply()
{
auto sql = _database->sqlGenerator()->insertBulk(_className, _fields, variants);
QSqlQuery q = _database->exec(sql);
return q.numRowsAffected();
}

1
src/nut/3rdparty/serializer vendored Submodule

@ -0,0 +1 @@
Subproject commit 37eafb2414575ea2873698e77b95ba8fcfeddba7

View File

@ -0,0 +1,8 @@
INCLUDEPATH += $$PWD
HEADERS += \
$$PWD/nut_config.h \
$$PWD/nut_consts.h \
$$PWD/nut_global.h \
$$PWD/nut_macros.h \
$$PWD/nut_namespace.h

View File

@ -0,0 +1,20 @@
#ifndef NUT_CONFIG_H
#define NUT_CONFIG_H
#if defined(NUT_SHARED) || !defined(NUT_STATIC)
# ifdef NUT_STATIC
# error "Both NUT_SHARED and NUT_STATIC defined, please make up your mind"
# endif
# ifndef NUT_SHARED
# define NUT_SHARED
# endif
# if defined(NUT_BUILD_LIB)
# define NUT_EXPORT Q_DECL_EXPORT
# else
# define NUT_EXPORT Q_DECL_IMPORT
# endif
#else
# define NUT_EXPORT
#endif
#endif // NUT_CONFIG_H

View File

@ -18,8 +18,8 @@
** **
**************************************************************************/ **************************************************************************/
#ifndef DEFINES_P_H #ifndef NUT_CONSTS_H
#define DEFINES_P_H #define NUT_CONSTS_H
#define __NAME "name" #define __NAME "name"
#define __TYPE "type" #define __TYPE "type"
@ -41,7 +41,7 @@
#define __nut_DEFAULT_VALUE "def" #define __nut_DEFAULT_VALUE "def"
#define __nut_NOT_NULL "notnull" #define __nut_NOT_NULL "notnull"
#define __nut_FOREIGN_KEY "foreign_key" #define __nut_FOREIGN_KEY "foreign_key"
#define __nut_NEW "new" #define __nut_NEW "new"
#define __nut_REMOVE "remove" #define __nut_REMOVE "remove"
#define __nut_CHANGE "change" #define __nut_CHANGE "change"
@ -56,4 +56,4 @@
# define NUT_WRAP_NAMESPACE(x) x # define NUT_WRAP_NAMESPACE(x) x
#endif #endif
#endif // DEFINES_P_H #endif // NUT_CONSTS_H

View File

@ -0,0 +1,12 @@
#ifndef NUT_GLOBAL_H
#define NUT_GLOBAL_H
#define NUT_NAMESPACE Nut
#include <QtNut/nut_config.h>
#include <QtNut/nut_consts.h>
#include <QtNut/nut_macros.h>
#include <QtNut/nut_macros.h>
#include <QtNut/nut_namespace.h>
#endif // NUT_GLOBAL_H

View File

@ -1,51 +1,6 @@
/************************************************************************** #ifndef NUT_MACROS_H
** #define NUT_MACROS_H
** This file is part of Nut project.
** https://github.com/HamedMasafi/Nut
**
** Nut is free software: you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Nut is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with Nut. If not, see <http://www.gnu.org/licenses/>.
**
**************************************************************************/
#ifndef SYNTAX_DEFINES_H
#define SYNTAX_DEFINES_H
#define NUT_NAMESPACE Nut
#include "defines_p.h"
#include "qglobal.h"
#include <QString>
#include <QStringList>
#include <QVariant>
#include <QMetaClassInfo>
#if defined(NUT_SHARED) || !defined(NUT_STATIC)
# ifdef NUT_STATIC
# error "Both NUT_SHARED and NUT_STATIC defined, please make up your mind"
# endif
# ifndef NUT_SHARED
# define NUT_SHARED
# endif
# if defined(NUT_BUILD_LIB)
# define NUT_EXPORT Q_DECL_EXPORT
# else
# define NUT_EXPORT Q_DECL_IMPORT
# endif
#else
# define NUT_EXPORT
#endif
#define NUT_INFO(type, name, value) \ #define NUT_INFO(type, name, value) \
Q_CLASSINFO(__nut_NAME_PERFIX type #name #value, \ Q_CLASSINFO(__nut_NAME_PERFIX type #name #value, \
@ -73,6 +28,17 @@
private: private:
//Table //Table
#define NUT_FIELD(type, name) \
private: \
NUT_INFO(__nut_FIELD, name, 0) \
public: \
static NUT_WRAP_NAMESPACE(FieldPhrase<type>)& name ## Field(){ \
static NUT_WRAP_NAMESPACE(FieldPhrase<type>) f = \
NUT_WRAP_NAMESPACE(FieldPhrase<type>) \
(staticMetaObject.className(), #name); \
return f; \
}
#define NUT_DECLARE_FIELD(type, name, read, write) \ #define NUT_DECLARE_FIELD(type, name, read, write) \
Q_PROPERTY(type name READ read WRITE write) \ Q_PROPERTY(type name READ read WRITE write) \
NUT_INFO(__nut_FIELD, name, 0) \ NUT_INFO(__nut_FIELD, name, 0) \
@ -89,59 +55,59 @@ public: \
} \ } \
void write(type name){ \ void write(type name){ \
m_##name = name; \ m_##name = name; \
propertyChanged(#name); \ propertyChanged(QString::fromUtf8(#name)); \
} }
#define NUT_FOREIGN_KEY(type, keytype, name, read, write) \ #define NUT_FOREIGN_KEY(type, keytype, name, read, write) \
Q_PROPERTY(Nut::Row<type> name READ read WRITE write) \ Q_PROPERTY(Nut::Row<type> name READ read WRITE write) \
NUT_DECLARE_FIELD(keytype, name##Id, read##Id, write##Id) \ NUT_DECLARE_FIELD(keytype, name##Id, read##Id, write##Id) \
NUT_INFO(__nut_FOREIGN_KEY, name, type) \ NUT_INFO(__nut_FOREIGN_KEY, name, type) \
Nut::Row<type> m_##name; \ Nut::Row<type> m_##name; \
public slots: \ public Q_SLOTS: \
Nut::Row<type> read() const { return m_##name ; } \ Nut::Row<type> read() const { return m_##name ; } \
Q_INVOKABLE void write(Nut::Row<type> name){ \ Q_INVOKABLE void write(Nut::Row<type> name){ \
m_##name = name; \ m_##name = name; \
} }
#define NUT_FOREIGN_KEY_DECLARE(type, keytype, name, read, write) \ #define NUT_FOREIGN_KEY_DECLARE(type, keytype, name, read, write) \
NUT_INFO(__nut_FIELD, name##Id, 0) \ NUT_INFO(__nut_FIELD, name##Id, 0) \
NUT_INFO(__nut_FOREIGN_KEY, name, type) \ NUT_INFO(__nut_FOREIGN_KEY, name, type) \
Nut::Row<type> m_##name; \ Nut::Row<type> m_##name; \
keytype m_##name##Id; \ keytype m_##name##Id; \
Q_PROPERTY(Nut::Row<type> name READ read WRITE write) \ Q_PROPERTY(Nut::Row<type> name READ read WRITE write) \
Q_PROPERTY(keytype name##Id READ read##Id WRITE write##Id) \ Q_PROPERTY(keytype name##Id READ read##Id WRITE write##Id) \
public: \ public: \
Nut::Row<type> read() const; \ Nut::Row<type> read() const; \
keytype read##Id() const; \ keytype read##Id() const; \
static NUT_WRAP_NAMESPACE(FieldPhrase<keytype>)& name##Id ## Field(){ \ static NUT_WRAP_NAMESPACE(FieldPhrase<keytype>)& name##Id ## Field(){ \
static NUT_WRAP_NAMESPACE(FieldPhrase<keytype>) f = \ static NUT_WRAP_NAMESPACE(FieldPhrase<keytype>) f = \
NUT_WRAP_NAMESPACE(FieldPhrase<keytype>) \ NUT_WRAP_NAMESPACE(FieldPhrase<keytype>) \
(staticMetaObject.className(), #name); \ (staticMetaObject.className(), #name "Id"); \
return f; \ return f; \
} \ } \
public slots: \ public : \
void write(Nut::Row<type> name); \ Q_INVOKABLE void write(Nut::Row<type> name); \
Q_INVOKABLE void write(Nut::Row<Nut::Table> name); \
void write##Id(keytype name##Id); void write##Id(keytype name##Id);
#define NUT_FOREIGN_KEY_IMPLEMENT(class, type, keytype, name, read, write) \ #define NUT_FOREIGN_KEY_IMPLEMENT(class, type, keytype, name, read, write) \
\ Nut::Row<type> class::read() const { return m_##name ; } \
Nut::Row<type> class::read() const { return m_##name ; } \ void class::write(Nut::Row<type> name){ \
void class::write(Nut::Row<type> name){ \ propertyChanged(QStringLiteral(QT_STRINGIFY2(name##Id))); \
propertyChanged(QT_STRINGIFY2(name##Id)); \
m_##name = name; \ m_##name = name; \
m_##name##Id = name->primaryValue().value<keytype>(); \ m_##name##Id = name->primaryValue().value<keytype>(); \
} \
\
keytype class::read##Id() const{ \
if (m_##name) \
return m_##name->primaryValue().value<keytype>(); \
return m_##name##Id; \
} \ } \
void class::write##Id(keytype name##Id){ \ void class::write(Nut::Row<Nut::Table> name){ \
propertyChanged(QT_STRINGIFY2(name##Id)); \ write(qSharedPointerDynamicCast<type>(name)); \
m_##name##Id = name##Id; \ } keytype class::read##Id() const{ \
m_##name = nullptr; \ if (m_##name) \
propertyChanged(QT_STRINGIFY2(name##Id)); \ return m_##name->primaryValue().value<keytype>(); \
return m_##name##Id; \
} \
void class::write##Id(keytype name##Id){ \
m_##name##Id = name##Id; \
m_##name = nullptr; \
propertyChanged(QStringLiteral(QT_STRINGIFY2(name##Id))); \
} }
@ -154,22 +120,22 @@ public slots: \
#define NUT_IMPLEMENT_CHILD_TABLE(class, type, n) \ #define NUT_IMPLEMENT_CHILD_TABLE(class, type, n) \
type *class::n##Table(){ \ type *class::n##Table(){ \
static auto f = new type(); \ static auto f = new type(); \
return f; \ return f; \
} \ } \
NUT_WRAP_NAMESPACE(TableSet)<type> *class::n(){ \ NUT_WRAP_NAMESPACE(TableSet)<type> *class::n(){ \
return m_##n; \ return m_##n; \
} }
#define NUT_FIELD(name) NUT_INFO(__nut_FIELD, name, 0) //#define NUT_FIELD(name) NUT_INFO(__nut_FIELD, name, 0)
#define NUT_PRIMARY_KEY(x) NUT_INFO(__nut_PRIMARY_KEY, x, 0) \ #define NUT_PRIMARY_KEY(x) NUT_INFO(__nut_PRIMARY_KEY, x, 0) \
public: \ public: \
QVariant primaryValue() const override { \ QVariant primaryValue() const override { \
return property(#x); \ return property(#x); \
} \ } \
void setPrimaryValue(const QVariant &value) override { \ void setPrimaryValue(const QVariant &value) override { \
setProperty(#x, value); \ setProperty(#x, value); \
} \ } \
private: private:
@ -183,132 +149,4 @@ public slots: \
#define NUT_NOT_NULL(x) NUT_INFO(__nut_NOT_NULL, x, 1) #define NUT_NOT_NULL(x) NUT_INFO(__nut_NOT_NULL, x, 1)
#define NUT_INDEX(name, field, order) #define NUT_INDEX(name, field, order)
NUT_BEGIN_NAMESPACE #endif // NUT_MACROS_H
inline bool nutClassInfo(const QMetaClassInfo &classInfo,
QString &type, QString &name, QVariant &value)
{
if (!QString(classInfo.name()).startsWith(__nut_NAME_PERFIX))
return false;
QStringList parts = QString(classInfo.value()).split("\n");
if (parts.count() != 3)
return false;
type = parts[0];
name = parts[1];
value = QVariant::fromValue(parts[2]);
return true;
}
inline bool nutClassInfoString(const QMetaClassInfo &classInfo,
QString &type, QString &name, QString &value)
{
if (!QString(classInfo.name()).startsWith(__nut_NAME_PERFIX))
return false;
QStringList parts = QString(classInfo.value()).split("\n");
if (parts.count() != 3)
return false;
type = parts[0];
name = parts[1];
value = parts[2];
return true;
}
inline bool nutClassInfoBool(const QMetaClassInfo &classInfo,
QString &type, QString &name, bool &value)
{
if (!QString(classInfo.name()).startsWith(__nut_NAME_PERFIX))
return false;
QStringList parts = QString(classInfo.value()).split("\n");
if (parts.count() != 3)
return false;
QString buffer = parts[2].toLower();
if (buffer != "true" && buffer != "false")
return false;
type = parts[0];
name = parts[1];
value = (buffer == "true");
return true;
}
inline bool nutClassInfoInt(const QMetaClassInfo &classInfo,
QString &type, QString &name, bool &value)
{
if (!QString(classInfo.name()).startsWith(__nut_NAME_PERFIX))
return false;
QStringList parts = QString(classInfo.value()).split("\n");
if (parts.count() != 3)
return false;
bool ok;
type = parts[0];
name = parts[1];
value = parts[2].toInt(&ok);
return ok;
}
#ifdef NUT_SHARED_POINTER
template <class T>
using RowList = QList<QSharedPointer<T>>;
template <class T>
using RowSet = QSet<QSharedPointer<T>>;
template <typename T>
using Row = QSharedPointer<T>;
template<class T>
inline Row<T> create() {
return QSharedPointer<T>(new T);
}
template<class T>
inline Row<T> create(QObject *parent) {
return QSharedPointer<T>(new T(parent));
}
template<class T>
inline Row<T> createFrom(T *row) {
return QSharedPointer<T>(row);
}
template<class T>
inline Row<T> createFrom(const QSharedPointer<T> row) {
return row;
}
#else
template <typename T>
using RowList = QList<T*>;
template <typename T>
using RowSet = QSet<T*>;
template <typename T>
using Row = T*;
template<class T>
inline Row<T> create() {
return new T;
}
template<class T>
inline T *get(const Row<T> row) {
return row;
}
template<class T>
inline T *get(const QSharedPointer<T> row) {
return row.data();
}
#endif
NUT_END_NAMESPACE
#endif // SYNTAX_DEFINES_H

View File

@ -0,0 +1,142 @@
#ifndef NUT_NAMESPACE_H
#define NUT_NAMESPACE_H
#ifndef NUT_GLOBAL_H
# error "Do not include nut_namespace.h header directly!"
#endif
//avoid ide warnings
#include <QtNut/nut_global.h>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <QtCore/QMetaClassInfo>
NUT_BEGIN_NAMESPACE
inline bool nutClassInfo(const QMetaClassInfo &classInfo,
QString &type, QString &name, QVariant &value)
{
if (!QString::fromUtf8(classInfo.name()).startsWith(QStringLiteral(__nut_NAME_PERFIX)))
return false;
QStringList parts = QString::fromUtf8(classInfo.value()).split(QStringLiteral("\n"));
if (parts.count() != 3)
return false;
type = parts[0];
name = parts[1];
value = QVariant::fromValue(parts[2]);
return true;
}
inline bool nutClassInfoString(const QMetaClassInfo &classInfo,
QString &type, QString &name, QString &value)
{
if (!QString::fromUtf8(classInfo.name()).startsWith(QStringLiteral(__nut_NAME_PERFIX)))
return false;
QStringList parts = QString::fromUtf8(classInfo.value()).split(QStringLiteral("\n"));
if (parts.count() != 3)
return false;
type = parts[0];
name = parts[1];
value = parts[2];
return true;
}
inline bool nutClassInfoBool(const QMetaClassInfo &classInfo,
QString &type, QString &name, bool &value)
{
if (!QString::fromUtf8(classInfo.name()).startsWith(QStringLiteral(__nut_NAME_PERFIX)))
return false;
QStringList parts = QString::fromUtf8(classInfo.value()).split(QStringLiteral("\n"));
if (parts.count() != 3)
return false;
QString buffer = parts[2].toLower();
if (buffer != QStringLiteral("true") && buffer != QStringLiteral("false"))
return false;
type = parts[0];
name = parts[1];
value = (buffer == QStringLiteral("true"));
return true;
}
inline bool nutClassInfoInt(const QMetaClassInfo &classInfo,
QString &type, QString &name, bool &value)
{
if (!QString::fromUtf8(classInfo.name()).startsWith(QStringLiteral(__nut_NAME_PERFIX)))
return false;
QStringList parts = QString::fromUtf8(classInfo.value()).split(QStringLiteral("\n"));
if (parts.count() != 3)
return false;
bool ok;
type = parts[0];
name = parts[1];
value = parts[2].toInt(&ok);
return ok;
}
#ifdef NUT_RAW_POINTER
template <typename T>
using RowList = QList<T*>;
template <typename T>
using RowSet = QSet<T*>;
template <typename T>
using Row = T*;
template<class T>
inline Row<T> create() {
return new T;
}
template<class T>
inline T *get(const Row<T> row) {
return row;
}
template<class T>
inline T *get(const QSharedPointer<T> row) {
return row.data();
}
#else
template <class T>
using RowList = QList<QSharedPointer<T>>;
template <class T>
using RowSet = QSet<QSharedPointer<T>>;
template <typename T>
using Row = QSharedPointer<T>;
template<class T>
inline Row<T> create() {
return QSharedPointer<T>(new T);
}
template<class T>
inline Row<T> create(QObject *parent) {
return QSharedPointer<T>(new T(parent));
}
template<class T>
inline Row<T> createFrom(T *row) {
return QSharedPointer<T>(row);
}
template<class T>
inline Row<T> createFrom(const QSharedPointer<T> row) {
return row;
}
#endif
NUT_END_NAMESPACE
#endif // NUT_NAMESPACE_H

View File

@ -20,53 +20,53 @@
#include "table.h" #include "table.h"
#include "database.h" #include "database.h"
#include "tablesetbase_p.h" #include "abstracttableset.h"
#include "databasemodel.h" #include "databasemodel.h"
#include "tablesetbasedata.h" #include "abstracttablesetdata.h"
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
TableSetBase::TableSetBase(Database *parent) : QObject(parent), AbstractTableSet::AbstractTableSet(Database *parent) : QObject(parent),
data(new TableSetBaseData(parent)) data(new AbstractTableSetData(parent))
{ {
parent->add(this); parent->add(this);
} }
TableSetBase::TableSetBase(Table *parent) : QObject(parent), AbstractTableSet::AbstractTableSet(Table *parent) : QObject(parent),
data(new TableSetBaseData(parent)) data(new AbstractTableSetData(parent))
{ {
parent->add(this); parent->add(this);
} }
TableSetBase::~TableSetBase() AbstractTableSet::~AbstractTableSet()
{ {
foreach (Row<Table> t, data->childs) Q_FOREACH (Row<Table> t, data->childs)
if (t) if (t)
t->setParentTableSet(nullptr); t->setParentTableSet(nullptr);
} }
int TableSetBase::save(Database *db, bool cleanUp) int AbstractTableSet::save(Database *db, bool cleanUp)
{ {
int rowsAffected = 0; int rowsAffected = 0;
TableModel *masterModel = nullptr; TableModel *masterModel = nullptr;
if (data->table) if (data->table)
masterModel = db->model().tableByClassName(data->table->metaObject()->className()); masterModel = db->model().tableByClassName(QString::fromUtf8(data->table->metaObject()->className()));
foreach (Row<Table> t, data->childs) { Q_FOREACH (Row<Table> t, data->childs) {
if (data->table) if (data->table)
t->setParentTable(data->table, t->setParentTable(data->table,
masterModel, masterModel,
db->model().tableByClassName(t->metaObject()->className())); db->model().tableByClassName(QString::fromUtf8(t->metaObject()->className())));
if (t->status() == Table::Added if (t->status() == Table::Added
|| t->status() == Table::Modified || t->status() == Table::Modified
|| t->status() == Table::Deleted) { || t->status() == Table::Deleted) {
rowsAffected += t->save(db); rowsAffected += t->save(db);
if (cleanUp) if (cleanUp)
#ifdef NUT_SHARED_POINTER #ifdef NUT_RAW_POINTER
remove(t);
#else
t->deleteLater(); t->deleteLater();
#else
remove(t);
#endif #endif
} }
} }
@ -77,42 +77,47 @@ int TableSetBase::save(Database *db, bool cleanUp)
return rowsAffected; return rowsAffected;
} }
void TableSetBase::clearChilds() void AbstractTableSet::clearChilds()
{ {
#ifndef NUT_SHARED_POINTER #ifdef NUT_RAW_POINTER
foreach (Table *t, data->childs) Q_FOREACH (Table *t, data->childs)
t->deleteLater(); t->deleteLater();
#endif #endif
data->childs.clear(); data->childs.clear();
} }
void TableSetBase::add(Row<Table> t) void AbstractTableSet::add(Row<Table> t)
{ {
data.detach(); data.detach();
data->childs.append(t); data->childs.append(t);
t->setParentTableSet(this); t->setParentTableSet(this);
} }
void TableSetBase::remove(Row<Table> t) void AbstractTableSet::remove(Row<Table> t)
{ {
data.detach(); data.detach();
data->childs.removeAll(t); data->childs.removeAll(t);
} }
QString TableSetBase::childClassName() const QString AbstractTableSet::childClassName() const
{ {
return data->childClassName; return data->childClassName;
} }
Database *TableSetBase::database() const Database *AbstractTableSet::database() const
{ {
return data->database; return data->database;
} }
void TableSetBase::setDatabase(Database *database) void AbstractTableSet::setDatabase(Database *database)
{ {
data.detach(); data.detach();
data->database = database; data->database = database;
} }
int AbstractTableSet::size() const
{
return data->childs.size();
}
NUT_END_NAMESPACE NUT_END_NAMESPACE

View File

@ -18,28 +18,28 @@
** **
**************************************************************************/ **************************************************************************/
#ifndef TABLESETBASE_H #ifndef NUT_ABSTRACTTABLESET_H
#define TABLESETBASE_H #define NUT_ABSTRACTTABLESET_H
#include <QtCore/QObject> #include <QtCore/QObject>
#include <QtCore/qglobal.h> #include <QtCore/qglobal.h>
#include <QtCore/QSet> #include <QtCore/QSet>
#include <QExplicitlySharedDataPointer> #include <QtCore/QExplicitlySharedDataPointer>
#include "defines.h" #include <QtNut/nut_global.h>
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
class Table; class Table;
class Database; class Database;
class TableSetBaseData; class AbstractTableSetData;
class NUT_EXPORT TableSetBase : public QObject class NUT_EXPORT AbstractTableSet : public QObject
{ {
public: public:
explicit TableSetBase(Database *parent); explicit AbstractTableSet(Database *parent);
explicit TableSetBase(Table *parent); explicit AbstractTableSet(Table *parent);
virtual ~TableSetBase(); virtual ~AbstractTableSet();
virtual int save(Database *db, bool cleanUp = false); virtual int save(Database *db, bool cleanUp = false);
void clearChilds(); void clearChilds();
@ -48,8 +48,10 @@ public:
Database *database() const; Database *database() const;
void setDatabase(Database *database); void setDatabase(Database *database);
int size() const;
protected: protected:
QExplicitlySharedDataPointer<TableSetBaseData> data; QExplicitlySharedDataPointer<AbstractTableSetData> data;
public://TODO: change this to private public://TODO: change this to private
// void add(Table* t); // void add(Table* t);
@ -64,4 +66,4 @@ public://TODO: change this to private
NUT_END_NAMESPACE NUT_END_NAMESPACE
#endif // TABLESETBASE_H #endif // NUT_ABSTRACTTABLESET_H

View File

@ -18,24 +18,25 @@
** **
**************************************************************************/ **************************************************************************/
#ifndef TABLESETBASEDATA_H #ifndef NUT_ABSTRACTTABLESETDATA_H
#define TABLESETBASEDATA_H #define NUT_ABSTRACTTABLESETDATA_H
#include <QSharedData> #include <QtCore/QSharedData>
#include "defines.h"
#include <QtNut/nut_global.h>
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
class Table; class Table;
class Database; class Database;
class TableSetBaseData : public QSharedData class AbstractTableSetData : public QSharedData
{ {
public: public:
TableSetBaseData(Database *parent) : AbstractTableSetData(Database *parent) :
database(parent), table(nullptr) database(parent), table(nullptr)
{ } { }
TableSetBaseData(Table *parent) : AbstractTableSetData(Table *parent) :
database(nullptr), table(parent) database(nullptr), table(parent)
{ } { }
@ -50,4 +51,4 @@ public:
NUT_END_NAMESPACE NUT_END_NAMESPACE
#endif // TABLESETBASEDATA_H #endif // NUT_ABSTRACTTABLESETDATA_H

View File

@ -0,0 +1,73 @@
#include "bulkinserter.h"
#include "bulkinserter_p.h"
#include "phrases/phraselist.h"
#include "database.h"
#include "abstractsqlgenerator.h"
#include "databasemodel.h"
#include <QtCore/QDebug>
NUT_BEGIN_NAMESPACE
BulkInserterPrivate::BulkInserterPrivate(Database *db)
: database(db), fieldCount(0)
{
}
BulkInserter::BulkInserter(Database *db, QString &className)
: d_ptr(new BulkInserterPrivate(db))
{
Q_D(BulkInserter);
Q_FOREACH (TableModel *m, db->model())
if (m->className() == className)
d->className = m->name();
}
BulkInserter::BulkInserter(const BulkInserter &other)
{
d_ptr = other.d_ptr;
}
BulkInserter::BulkInserter(BulkInserter &&other)
{
d_ptr = other.d_ptr;
other.d_ptr = nullptr;
}
void BulkInserter::setFields(const PhraseList &ph)
{
Q_D(BulkInserter);
d->fields = ph;
d->fieldCount = static_cast<size_t>(ph.data.count());
}
void BulkInserter::insert(std::initializer_list<QVariant> vars)
{
Q_D(BulkInserter);
if (vars.size() != d->fieldCount) {
qInfo("Number of rows mistake");
return;
}
QVariantList list;
std::initializer_list<QVariant>::iterator it;
for (it = vars.begin(); it != vars.end(); ++it)
list.append(*it);
d->variants.append(list);
}
int BulkInserter::apply()
{
Q_D(BulkInserter);
auto sql = d->database->sqlGenerator()->insertBulk(d->className,
d->fields,
d->variants);
QSqlQuery q = d->database->exec(sql);
return q.numRowsAffected();
}
NUT_END_NAMESPACE

View File

@ -2,25 +2,26 @@
#define BULKINSERTER_H #define BULKINSERTER_H
#include <initializer_list> #include <initializer_list>
#include <QDebug> #include <QtCore/QDebug>
#include "defines.h" #include <QtNut/phraselist.h>
#include "phrases/phraselist.h" #include <QtNut/fieldphrase.h>
#include "phrases/fieldphrase.h"
#include <QtNut/nut_global.h>
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
class PhraseList; class PhraseList;
class Database; class Database;
class BulkInserterPrivate;
class NUT_EXPORT BulkInserter class NUT_EXPORT BulkInserter
{ {
Database *_database; Q_DECLARE_PRIVATE(BulkInserter);
QString _className;
Nut::PhraseList _fields;
QList<QVariantList> variants;
size_t _fieldCount;
public: public:
BulkInserter(Database *db, QString &className); BulkInserter(Database *db, QString &className);
BulkInserter(const BulkInserter &other);
BulkInserter(BulkInserter &&other);
void setFields(const PhraseList &ph); void setFields(const PhraseList &ph);
void insert(std::initializer_list<QVariant> vars); void insert(std::initializer_list<QVariant> vars);
@ -29,6 +30,9 @@ public:
insert({args...}); insert({args...});
} }
int apply(); int apply();
private:
BulkInserterPrivate *d_ptr;
}; };
NUT_END_NAMESPACE NUT_END_NAMESPACE

View File

@ -0,0 +1,23 @@
#ifndef BULKINSERTER_P_H
#define BULKINSERTER_P_H
#include <QtNut/phraselist.h>
NUT_BEGIN_NAMESPACE
class Database;
class BulkInserterPrivate
{
public:
BulkInserterPrivate(Database *db);
Database *database;
QString className;
PhraseList fields;
QList<QVariantList> variants;
size_t fieldCount;
};
NUT_END_NAMESPACE
#endif // BULKINSERTER_P_H

View File

@ -22,7 +22,7 @@
#define CHANGELOGTABLE_H #define CHANGELOGTABLE_H
#include <QtCore/qglobal.h> #include <QtCore/qglobal.h>
#include "table.h" #include <QtNut/table.h>
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE

29
src/nut/core/core.pri Normal file
View File

@ -0,0 +1,29 @@
INCLUDEPATH += $$PWD
HEADERS += \
$$PWD/abstracttableset.h \
$$PWD/abstracttablesetdata.h \
$$PWD/bulkinserter.h \
$$PWD/bulkinserter_p.h \
$$PWD/changelogtable.h \
$$PWD/database.h \
$$PWD/database_p.h \
$$PWD/foreigncontainer.h \
$$PWD/propertysignalmapper.h \
$$PWD/query.h \
$$PWD/table.h \
$$PWD/table_p.h \
$$PWD/tableset.h
SOURCES += \
$$PWD/abstracttableset.cpp \
$$PWD/bulkinserter.cpp \
$$PWD/changelogtable.cpp \
$$PWD/database.cpp \
$$PWD/foreigncontainer.cpp \
$$PWD/propertysignalmapper.cpp \
$$PWD/query.cpp \
$$PWD/table.cpp \
$$PWD/tableset.cpp

View File

@ -33,12 +33,12 @@
#include "table.h" #include "table.h"
#include "tableset.h" #include "tableset.h"
#include "database_p.h" #include "database_p.h"
#include "defines.h" #include "config/nut_global.h"
#include "tablemodel.h" #include "tablemodel.h"
#include "generators/postgresqlgenerator.h" #include "postgresqlgenerator.h"
#include "generators/mysqlgenerator.h" #include "mysqlgenerator.h"
#include "generators/sqlitegenerator.h" #include "sqlitegenerator.h"
#include "generators/sqlservergenerator.h" #include "sqlservergenerator.h"
#include "query.h" #include "query.h"
#include "changelogtable.h" #include "changelogtable.h"
@ -66,7 +66,7 @@ bool DatabasePrivate::open(bool update)
return true; return true;
Q_Q(Database); Q_Q(Database);
// if (update) // if (update)
connectionName = q->metaObject()->className() connectionName = QString::fromUtf8(q->metaObject()->className())
+ QString::number(DatabasePrivate::lastId); + QString::number(DatabasePrivate::lastId);
db = QSqlDatabase::addDatabase(driver, connectionName); db = QSqlDatabase::addDatabase(driver, connectionName);
@ -77,7 +77,7 @@ bool DatabasePrivate::open(bool update)
db.setUserName(userName); db.setUserName(userName);
db.setPassword(password); db.setPassword(password);
if (driver.startsWith("qsqlite", Qt::CaseInsensitive) if (driver.startsWith(QStringLiteral("qsqlite"), Qt::CaseInsensitive)
&& !QFile::exists(databaseName)) { && !QFile::exists(databaseName)) {
//Force to execute update database //Force to execute update database
isDatabaseNew = true; isDatabaseNew = true;
@ -89,18 +89,20 @@ bool DatabasePrivate::open(bool update)
qWarning("Could not connect to database, error = %s", qWarning("Could not connect to database, error = %s",
db.lastError().text().toLocal8Bit().data()); db.lastError().text().toLocal8Bit().data());
if (db.lastError().text().contains("database \"" + databaseName if (db.lastError().text().contains(QStringLiteral("database \"")
+ "\" does not exist") + databaseName
|| db.lastError().text().contains("Cannot open database") + QStringLiteral("\" does not exist"))
|| db.lastError().text().contains("Unknown database '" || db.lastError().text().contains(QStringLiteral("Cannot open database"))
+ databaseName + "'")) { || db.lastError().text().contains(QStringLiteral("Unknown database '")
+ databaseName
+ QStringLiteral("'"))) {
db.close(); db.close();
db.setDatabaseName(sqlGenerator->masterDatabaseName(databaseName)); db.setDatabaseName(sqlGenerator->masterDatabaseName(databaseName));
ok = db.open(); ok = db.open();
qDebug("Creating database"); qDebug("Creating database");
if (ok) { if (ok) {
db.exec("CREATE DATABASE " + databaseName); db.exec(QStringLiteral("CREATE DATABASE ") + databaseName);
db.close(); db.close();
if (db.lastError().type() != QSqlError::NoError) { if (db.lastError().type() != QSqlError::NoError) {
@ -142,8 +144,8 @@ bool DatabasePrivate::updateDatabase()
return true; return true;
} }
foreach (TableModel *tm, current) { Q_FOREACH (TableModel *tm, current) {
foreach (FieldModel *fm, tm->fields()) { Q_FOREACH (FieldModel *fm, tm->fields()) {
if (sqlGenerator->fieldType(fm).isEmpty()) { if (sqlGenerator->fieldType(fm).isEmpty()) {
qWarning("The type (%s) is not supported for field %s::%s", qWarning("The type (%s) is not supported for field %s::%s",
QMetaType::typeName(fm->type), QMetaType::typeName(fm->type),
@ -161,7 +163,7 @@ bool DatabasePrivate::updateDatabase()
QStringList sql = sqlGenerator->diff(last, current); QStringList sql = sqlGenerator->diff(last, current);
db.transaction(); db.transaction();
foreach (QString s, sql) { Q_FOREACH (QString s, sql) {
db.exec(s); db.exec(s);
if (db.lastError().type() != QSqlError::NoError) { if (db.lastError().type() != QSqlError::NoError) {
@ -193,8 +195,8 @@ bool DatabasePrivate::getCurrectSchema()
Q_Q(Database); Q_Q(Database);
//is not first instanicate of this class //is not first instanicate of this class
if (allTableMaps.contains(q->metaObject()->className())) { if (allTableMaps.contains(QString::fromUtf8(q->metaObject()->className()))) {
currentModel = allTableMaps[q->metaObject()->className()]; currentModel = allTableMaps[QString::fromUtf8(q->metaObject()->className())];
return false; return false;
} }
@ -205,9 +207,9 @@ bool DatabasePrivate::getCurrectSchema()
int changeLogTypeId = qRegisterMetaType<ChangeLogTable*>(); int changeLogTypeId = qRegisterMetaType<ChangeLogTable*>();
currentModel.append( currentModel.append(
new TableModel(changeLogTypeId, __CHANGE_LOG_TABLE_NAME)); new TableModel(changeLogTypeId, QStringLiteral(__CHANGE_LOG_TABLE_NAME)));
tables.insert(ChangeLogTable::staticMetaObject.className(), tables.insert(QString::fromUtf8(ChangeLogTable::staticMetaObject.className()),
__CHANGE_LOG_TABLE_NAME); QStringLiteral(__CHANGE_LOG_TABLE_NAME));
changeLogs = new TableSet<ChangeLogTable>(q); changeLogs = new TableSet<ChangeLogTable>(q);
@ -219,11 +221,11 @@ bool DatabasePrivate::getCurrectSchema()
if (!nutClassInfoString(q->metaObject()->classInfo(i), if (!nutClassInfoString(q->metaObject()->classInfo(i),
type, name, value)) { type, name, value)) {
errorMessage = QString("No valid table in %1") errorMessage = QStringLiteral("No valid table in ")
.arg(q->metaObject()->classInfo(i).value()); + QString::fromUtf8(q->metaObject()->classInfo(i).value());
continue; continue;
} }
if (type == __nut_TABLE) { if (type == QStringLiteral(__nut_TABLE)) {
//name: table class name //name: table class name
//value: table variable name (table name in db) //value: table variable name (table name in db)
tables.insert(name, value); tables.insert(name, value);
@ -237,7 +239,7 @@ bool DatabasePrivate::getCurrectSchema()
currentModel.append(sch); currentModel.append(sch);
} }
if (type == __nut_DB_VERSION) { if (type == QStringLiteral(__nut_DB_VERSION)) {
bool ok; bool ok;
int version = value.toInt(&ok); int version = value.toInt(&ok);
if (!ok) if (!ok)
@ -250,15 +252,15 @@ bool DatabasePrivate::getCurrectSchema()
QMetaProperty tableProperty = q->metaObject()->property(i); QMetaProperty tableProperty = q->metaObject()->property(i);
int typeId = QMetaType::type(tableProperty.typeName()); int typeId = QMetaType::type(tableProperty.typeName());
if (tables.values().contains(tableProperty.name()) if (tables.values().contains(QString::fromUtf8(tableProperty.name()))
&& (unsigned)typeId >= QVariant::UserType) { && (unsigned)typeId >= QVariant::UserType) {
TableModel *sch = new TableModel(typeId, tableProperty.name()); TableModel *sch = new TableModel(typeId, QString::fromUtf8(tableProperty.name()));
currentModel.append(sch); currentModel.append(sch);
} }
} }
foreach (TableModel *table, currentModel) { Q_FOREACH (TableModel *table, currentModel) {
foreach (FieldModel *f, table->fields()) { Q_FOREACH (FieldModel *f, table->fields()) {
if (f->isPrimaryKey && ! sqlGenerator->supportPrimaryKey(f->type)) if (f->isPrimaryKey && ! sqlGenerator->supportPrimaryKey(f->type))
qFatal("The field of type %s does not support as primary key", qFatal("The field of type %s does not support as primary key",
qPrintable(f->typeName)); qPrintable(f->typeName));
@ -268,31 +270,33 @@ bool DatabasePrivate::getCurrectSchema()
qPrintable(f->typeName)); qPrintable(f->typeName));
} }
foreach (RelationModel *fk, table->foreignKeys()) Q_FOREACH (RelationModel *fk, table->foreignKeys())
fk->masterTable = currentModel.tableByClassName(fk->masterClassName); fk->masterTable = currentModel.tableByClassName(fk->masterClassName);
} }
allTableMaps.insert(q->metaObject()->className(), currentModel); allTableMaps.insert(QString::fromUtf8(q->metaObject()->className()), currentModel);
return true; return true;
} }
DatabaseModel DatabasePrivate::getLastSchema() DatabaseModel DatabasePrivate::getLastSchema()
{ {
Row<ChangeLogTable> u = changeLogs->query() Row<ChangeLogTable> u = changeLogs->query()
->orderBy(!ChangeLogTable::idField()) .orderBy(!ChangeLogTable::idField())
->first(); .first();
// DatabaseModel ret(q->metaObject()->className());
if (u) { if (u) {
QJsonParseError e; QJsonParseError e;
QJsonObject json QJsonObject json = QJsonDocument::fromJson(u->data()
= QJsonDocument::fromJson(u->data().replace("\\\"", "\"").toUtf8(), &e).object(); .replace(QStringLiteral("\\\""),
QStringLiteral("\""))
.toUtf8(),
&e)
.object();
DatabaseModel ret = json; DatabaseModel ret = json;
return ret; return ret;
/* /*
foreach (QString key, json.keys()) { Q_FOREACH (QString key, json.keys()) {
TableModel *sch = new TableModel(json.value(key).toObject(), key); TableModel *sch = new TableModel(json.value(key).toObject(), key);
ret.append(sch); ret.append(sch);
}*/ }*/
@ -306,7 +310,7 @@ DatabaseModel DatabasePrivate::getLastSchema()
// QJsonObject json = // QJsonObject json =
// QJsonDocument::fromJson(query.value("data").toByteArray()).object(); // QJsonDocument::fromJson(query.value("data").toByteArray()).object();
// foreach (QString key, json.keys()) { // Q_FOREACH (QString key, json.keys()) {
// TableModel *sch = new TableModel(json.value(key).toObject(), // TableModel *sch = new TableModel(json.value(key).toObject(),
// key); // key);
// ret.append(sch); // ret.append(sch);
@ -322,7 +326,7 @@ bool DatabasePrivate::putModelToDatabase()
/*current.remove(__CHANGE_LOG_TABLE_NAME)*/; /*current.remove(__CHANGE_LOG_TABLE_NAME)*/;
auto changeLog = create<ChangeLogTable>(); auto changeLog = create<ChangeLogTable>();
changeLog->setData(QJsonDocument(current.toJson()).toJson(QJsonDocument::Compact)); changeLog->setData(QString::fromUtf8(QJsonDocument(current.toJson()).toJson(QJsonDocument::Compact)));
changeLog->setVersion(current.version()); changeLog->setVersion(current.version());
changeLogs->append(changeLog); changeLogs->append(changeLog);
q->saveChanges(true); q->saveChanges(true);
@ -344,9 +348,11 @@ bool DatabasePrivate::putModelToDatabase()
void DatabasePrivate::createChangeLogs() void DatabasePrivate::createChangeLogs()
{ {
// currentModel.model("change_log") // currentModel.model("change_log")
QStringList diff = sqlGenerator->diff(nullptr, currentModel.tableByName("__change_log")); QStringList diff = sqlGenerator->diff(nullptr,
currentModel.tableByName(
QStringLiteral("__change_log")));
foreach (QString s, diff) Q_FOREACH (QString s, diff)
db.exec(s); db.exec(s);
} }
@ -358,7 +364,6 @@ void DatabasePrivate::createChangeLogs()
Database::Database(QObject *parent) Database::Database(QObject *parent)
: QObject(parent), d_ptr(new DatabasePrivate(this)) : QObject(parent), d_ptr(new DatabasePrivate(this))
{ {
// _d = new QSharedDataPointer<DatabasePrivate>(new DatabasePrivate(this));
DatabasePrivate::lastId++; DatabasePrivate::lastId++;
} }
@ -366,7 +371,6 @@ Database::Database(const Database &other)
: QObject(other.parent()), d_ptr(new DatabasePrivate(this)) : QObject(other.parent()), d_ptr(new DatabasePrivate(this))
{ {
DatabasePrivate::lastId++; DatabasePrivate::lastId++;
// _d = other._d;
setDriver(other.driver()); setDriver(other.driver());
setHostName(other.hostName()); setHostName(other.hostName());
@ -381,7 +385,7 @@ Database::Database(const QSqlDatabase &other)
//TODO: make a polish here //TODO: make a polish here
DatabasePrivate::lastId++; DatabasePrivate::lastId++;
// setDriver(other.driver()); setDriver(other.driverName());
setHostName(other.hostName()); setHostName(other.hostName());
setPort(other.port()); setPort(other.port());
setDatabaseName(other.databaseName()); setDatabaseName(other.databaseName());
@ -390,6 +394,12 @@ Database::Database(const QSqlDatabase &other)
qRegisterMetaType<ChangeLogTable*>(); qRegisterMetaType<ChangeLogTable*>();
} }
Database::Database(Database &&other)
{
d_ptr = other.d_ptr;
other.d_ptr = nullptr;
}
Database::~Database() Database::~Database()
{ {
Q_D(Database); Q_D(Database);
@ -506,7 +516,7 @@ void Database::setDriver(QString driver)
d->driver = driver.toUpper(); d->driver = driver.toUpper();
} }
SqlGeneratorBase *Database::sqlGenerator() const AbstractSqlGenerator *Database::sqlGenerator() const
{ {
Q_D(const Database); Q_D(const Database);
return d->sqlGenerator; return d->sqlGenerator;
@ -545,17 +555,17 @@ bool Database::open(bool updateDatabase)
{ {
Q_D(Database); Q_D(Database);
if (d->driver == "QPSQL" || d->driver == "QPSQL7") if (d->driver == QStringLiteral("QPSQL") || d->driver == QStringLiteral("QPSQL7"))
d->sqlGenerator = new PostgreSqlGenerator(this); d->sqlGenerator = new PostgreSqlGenerator(this);
else if (d->driver == "QMYSQL" || d->driver == "QMYSQL3") else if (d->driver == QStringLiteral("QMYSQL") || d->driver == QStringLiteral("QMYSQL3"))
d->sqlGenerator = new MySqlGenerator(this); d->sqlGenerator = new MySqlGenerator(this);
else if (d->driver == "QSQLITE" || d->driver == "QSQLITE3") else if (d->driver == QStringLiteral("QSQLITE") || d->driver == QStringLiteral("QSQLITE3"))
d->sqlGenerator = new SqliteGenerator(this); d->sqlGenerator = new SqliteGenerator(this);
else if (d->driver == "QODBC" || d->driver == "QODBC3") { else if (d->driver == QStringLiteral("QODBC") || d->driver == QStringLiteral("QODBC3")) {
QString driverName = QString(); QString driverName = QString();
QStringList parts = d->databaseName.toLower().split(';'); QStringList parts = d->databaseName.toLower().split(';');
foreach (QString p, parts) Q_FOREACH (QString p, parts)
if (p.trimmed().startsWith("driver=")) if (p.trimmed().startsWith(QStringLiteral("driver=")))
driverName = p.split('=').at(1).toLower().trimmed(); driverName = p.split('=').at(1).toLower().trimmed();
// if (driverName == "{sql server}") // if (driverName == "{sql server}")
@ -589,7 +599,7 @@ QSqlQuery Database::exec(const QString &sql)
return q; return q;
} }
void Database::add(TableSetBase *t) void Database::add(AbstractTableSet *t)
{ {
Q_D(Database); Q_D(Database);
d->tableSets.insert(t); d->tableSets.insert(t);
@ -605,7 +615,7 @@ int Database::saveChanges(bool cleanUp)
} }
int rowsAffected = 0; int rowsAffected = 0;
foreach (TableSetBase *ts, d->tableSets) Q_FOREACH (AbstractTableSet *ts, d->tableSets)
rowsAffected += ts->save(this, cleanUp); rowsAffected += ts->save(this, cleanUp);
return rowsAffected; return rowsAffected;
@ -614,7 +624,7 @@ int Database::saveChanges(bool cleanUp)
void Database::cleanUp() void Database::cleanUp()
{ {
Q_D(Database); Q_D(Database);
foreach (TableSetBase *ts, d->tableSets) Q_FOREACH (AbstractTableSet *ts, d->tableSets)
ts->clearChilds(); ts->clearChilds();
} }

View File

@ -23,18 +23,18 @@
#include <QtCore/qglobal.h> #include <QtCore/qglobal.h>
#include <QtCore/QList> #include <QtCore/QList>
#include <QtCore/QSharedDataPointer>
#include <QtSql/QSqlDatabase> #include <QtSql/QSqlDatabase>
#include <QSharedDataPointer>
#include "defines.h" #include <QtNut/nut_global.h>
#include "tableset.h" #include <QtNut/tableset.h>
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
class DatabaseModel; class DatabaseModel;
class DatabasePrivate; class DatabasePrivate;
class TableSetBase; class AbstractTableSet;
class SqlGeneratorBase; class AbstractSqlGenerator;
class ChangeLogTable; class ChangeLogTable;
class NUT_EXPORT Database : public QObject class NUT_EXPORT Database : public QObject
{ {
@ -48,6 +48,7 @@ public:
explicit Database(QObject *parent = nullptr); explicit Database(QObject *parent = nullptr);
explicit Database(const Database &other); explicit Database(const Database &other);
explicit Database(const QSqlDatabase &other); explicit Database(const QSqlDatabase &other);
explicit Database(Database &&other);
~Database(); ~Database();
bool open(); bool open();
@ -70,7 +71,7 @@ public:
DatabaseModel model() const; DatabaseModel model() const;
QString tableName(QString className); QString tableName(QString className);
SqlGeneratorBase *sqlGenerator() const; AbstractSqlGenerator *sqlGenerator() const;
QSqlDatabase database(); QSqlDatabase database();
protected: protected:
@ -78,7 +79,7 @@ protected:
virtual void databaseCreated(); virtual void databaseCreated();
virtual void databaseUpdated(int oldVersion, int newVersion); virtual void databaseUpdated(int oldVersion, int newVersion);
public slots: public Q_SLOTS:
void setDatabaseName(QString databaseName); void setDatabaseName(QString databaseName);
void setHostName(QString hostName); void setHostName(QString hostName);
void setPort(int port); void setPort(int port);
@ -88,9 +89,9 @@ public slots:
void setDriver(QString driver); void setDriver(QString driver);
private: private:
void add(TableSetBase *); void add(AbstractTableSet *);
friend class TableSetBase; friend class AbstractTableSet;
}; };
NUT_END_NAMESPACE NUT_END_NAMESPACE

View File

@ -21,16 +21,16 @@
#ifndef DATABASE_P_H #ifndef DATABASE_P_H
#define DATABASE_P_H #define DATABASE_P_H
#include "database.h" #include <QtCore/QDebug>
#include "databasemodel.h" #include <QtCore/QSharedData>
#include <QDebug> #include <QtNut/database.h>
#include <QSharedData> #include <QtNut/databasemodel.h>
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
class ChangeLogTable; class ChangeLogTable;
class NUT_EXPORT DatabasePrivate //: public QSharedData class NUT_EXPORT DatabasePrivate
{ {
Database *q_ptr; Database *q_ptr;
Q_DECLARE_PUBLIC(Database) Q_DECLARE_PUBLIC(Database)
@ -56,7 +56,7 @@ public:
QString connectionName; QString connectionName;
QString driver; QString driver;
SqlGeneratorBase *sqlGenerator; AbstractSqlGenerator *sqlGenerator;
DatabaseModel currentModel; DatabaseModel currentModel;
TableSet<ChangeLogTable> *changeLogs; TableSet<ChangeLogTable> *changeLogs;
@ -64,7 +64,7 @@ public:
static QMap<QString, DatabaseModel> allTableMaps; static QMap<QString, DatabaseModel> allTableMaps;
static qulonglong lastId; static qulonglong lastId;
QSet<TableSetBase *> tableSets; QSet<AbstractTableSet *> tableSets;
bool isDatabaseNew; bool isDatabaseNew;

View File

@ -0,0 +1,2 @@
#include "foreigncontainer.h"

View File

@ -0,0 +1,58 @@
#ifndef FOREIGNCONTAINER_H
#define FOREIGNCONTAINER_H
template<class _OBJECT, typename _KEY>
class ForeignContainer
{
_OBJECT *_object{nullptr};
_KEY _key;
enum StorageType {
Key,
ClassValue
};
StorageType storageType;
public:
ForeignContainer()
{}
ForeignContainer<_OBJECT, _KEY> operator =(const _KEY &key)
{
this->_key = key;
this->_object = nullptr;
this->storageType = Key;
return *this;
}
ForeignContainer<_OBJECT, _KEY> operator =(const _OBJECT *value)
{
this->_object = value;
this->storageType = ClassValue;
return *this;
}
_KEY key()
{
if (this->storageType == Key)
return _key;
else
return _object->primaryValue().template value<_KEY>();
}
_OBJECT *object()
{
return _object;
}
operator _KEY()
{
return key();
}
operator _OBJECT()
{
return object();
}
};
#endif // FOREIGNCONTAINER_H

View File

@ -0,0 +1,73 @@
/**************************************************************************
**
** This file is part of Nut project.
** https://github.com/HamedMasafi/Nut
**
** Nut is free software: you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Nut is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with Nut. If not, see <http://www.gnu.org/licenses/>.
**
**************************************************************************/
#include "propertysignalmapper.h"
#include "table.h"
NUT_BEGIN_NAMESPACE
QMap<QString, PropertySignalMapper::ClassData*> PropertySignalMapper::_data;
void PropertySignalMapper::map(Table *obj)
{
if (obj->_is_signals_mapped)
return;
ClassData *d;
const QMetaObject *mo = obj->metaObject();
auto className = QString::fromUtf8(mo->className());
if (_data.contains(className)) {
d = _data.value(className);
for (auto &p: d->properties)
QObject::connect(obj, p.notifySignal(), obj, d->propertyChanged);
} else {
d = new ClassData;
d->propertyChanged = mo->method(mo->indexOfSlot("propertyChanged()"));
for (int i = 0; i < mo->propertyCount(); ++i) {
QMetaProperty p = mo->property(i);
if (!strcmp(p.name(), "objectName"))
continue;
if (p.hasNotifySignal()) {
d->signalMaps.insert(QLatin1String(p.notifySignal().name()),
QLatin1String(p.name()));
d->properties.append(p);
QObject::connect(obj, p.notifySignal(), obj, d->propertyChanged);
}
}
_data.insert(className, d);
}
obj->_is_signals_mapped = true;
}
QString PropertySignalMapper::changedProperty(QObject *obj, int senderSignalIndex)
{
return _data.value(QString::fromUtf8(obj->metaObject()->className()))
->signalMaps.value(
QString::fromUtf8(obj->metaObject()->method(senderSignalIndex).name())
);
}
NUT_END_NAMESPACE

View File

@ -18,37 +18,32 @@
** **
**************************************************************************/ **************************************************************************/
#ifndef QUERYBASE_H #ifndef PROPERTYSIGNALMAPPER_H
#define QUERYBASE_H #define PROPERTYSIGNALMAPPER_H
#include <QtCore/QObject> #include <QtNut/nut_global.h>
#include <QtCore/qglobal.h>
#include <QtCore/QExplicitlySharedDataPointer>
#include "defines.h" #include <QMetaMethod>
#include "query_p.h" #include <QMetaProperty>
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
//TODO: remove this class
class Table; class Table;
class TableSetBase; class PropertySignalMapper
class NUT_EXPORT QueryBase : public QObject
{ {
Q_OBJECT struct ClassData
{
protected: QMetaMethod propertyChanged;
QExplicitlySharedDataPointer<QueryPrivate> d; QList<QMetaProperty> properties;
QMap<QString, QString> signalMaps;
};
static QMap<QString, ClassData*> _data;
public: public:
explicit QueryBase(QObject *parent = nullptr); static void map(Table *obj);
static QString changedProperty(QObject *obj, int senderSignalIndex);
protected:
// void addTableToSet(TableSetBase *set, Table *table);
public slots:
}; };
NUT_END_NAMESPACE NUT_END_NAMESPACE
#endif // QUERYBASE_H #endif // PROPERTYSIGNALMAPPER_H

View File

@ -22,17 +22,6 @@
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
QueryPrivate::QueryPrivate(QueryBase *parent) : q_ptr(parent),
database(nullptr), tableSet(nullptr), skip(-1), take(-1)
{
}
QueryPrivate::~QueryPrivate()
{
}
/*! /*!
* \class Query * \class Query
* \brief This class hold a query. A query can be used for getting database rows, editing or deleting without row fetching. * \brief This class hold a query. A query can be used for getting database rows, editing or deleting without row fetching.

View File

@ -18,8 +18,8 @@
** **
**************************************************************************/ **************************************************************************/
#ifndef QUERY_H #ifndef NUT_QUERY_H
#define QUERY_H #define NUT_QUERY_H
#include <QtCore/QVariant> #include <QtCore/QVariant>
#include <QtCore/QDebug> #include <QtCore/QDebug>
@ -31,54 +31,93 @@
#include <QtSql/QSqlQueryModel> #include <QtSql/QSqlQueryModel>
#include <QtSql/QSqlQuery> #include <QtSql/QSqlQuery>
#ifdef NUT_SHARED_POINTER #ifndef NUT_RAW_POINTER
#include <QtCore/QSharedPointer> #include <QtCore/QSharedPointer>
#endif #endif
#include "table.h" #include <QtNut/table.h>
#include "query_p.h" #include <QtNut/database.h>
#include "database.h" #include <QtNut/databasemodel.h>
#include "databasemodel.h" #include <QtNut/abstracttableset.h>
#include "tablesetbase_p.h" #include <QtNut/abstractsqlgenerator.h>
#include "generators/sqlgeneratorbase_p.h" #include <QtNut/phrase.h>
#include "querybase_p.h" #include <QtNut/tablemodel.h>
#include "phrase.h" #include <QtNut/sqlmodel.h>
#include "tablemodel.h"
#include "sqlmodel.h"
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
template <class T> struct NUT_EXPORT QueryData {
class Query : public QueryBase QString sql;
{ QString className;
QueryPrivate *d_ptr; QString tableName;
Q_DECLARE_PRIVATE(Query) QString select;
Database *database;
AbstractTableSet *tableSet;
QStringList joins;
QList<RelationModel*> relations;
int skip;
int take;
PhraseList orderPhrase, fieldPhrase;
ConditionalPhrase wherePhrase;
bool m_autoDelete; QueryData *clone() {
auto r = new QueryData;
r->sql = sql;
r->className = className;
r->tableName = tableName;
r->select = select;
r->database = database;
r->tableSet = tableSet;
r->joins = joins;
r->relations = relations;
r->skip = skip;
r->take = take;
r->orderPhrase = orderPhrase;
r->fieldPhrase = fieldPhrase;
r->wherePhrase = wherePhrase;
return r;
}
QueryData() : skip(0), take(0)
{ }
QueryData(Database *db) : database(db), skip(0), take(0)
{ }
};
template <class T>
class Query
{
QueryData *d;
public: public:
explicit Query(Database *database, TableSetBase *tableSet, bool autoDelete); explicit Query(Database *database, AbstractTableSet *tableSet);
Query (const Query<T> &other);
Query (Query<T> &&other);
~Query(); ~Query();
Query<T>& operator=(const Query<T> &q);
//ddl //ddl
Query<T> *join(const QString &className); Query<T> &join(const QString &className);
Query<T> *join(Table *c); Query<T> &join(Table *c);
template<class TABLE> template<class TABLE>
Query<T> *join() Query<T> &join()
{ {
join(TABLE::staticMetaObject.className()); join(TABLE::staticMetaObject.className());
return this; return *this;
} }
// Query<T> *orderBy(QString fieldName, QString type); // Query<T> &orderBy(QString fieldName, QString type);
Query<T> *skip(int n); Query<T> &skip(int n);
Query<T> *take(int n); Query<T> &take(int n);
Query<T> *fields(const PhraseList &ph); Query<T> &fields(const PhraseList &ph);
Query<T> *orderBy(const PhraseList &ph); Query<T> &orderBy(const PhraseList &ph);
Query<T> *where(const ConditionalPhrase &ph); Query<T> &where(const ConditionalPhrase &ph);
Query<T> *setWhere(const ConditionalPhrase &ph); Query<T> &setWhere(const ConditionalPhrase &ph);
//data selecting //data selecting
Row<T> first(); Row<T> first();
@ -95,11 +134,10 @@ public:
QVariant sum(const FieldPhrase<int> &f); QVariant sum(const FieldPhrase<int> &f);
QVariant average(const FieldPhrase<int> &f); QVariant average(const FieldPhrase<int> &f);
QVariant insert(const AssignmentPhraseList &p);
//data mailpulation //data mailpulation
int update(const AssignmentPhraseList &ph); int update(const AssignmentPhraseList &ph);
// int insert(const AssignmentPhraseList &ph); QVariant insert(const AssignmentPhraseList &p);
int remove(); int remove();
QSqlQueryModel *toModel(); QSqlQueryModel *toModel();
@ -114,16 +152,17 @@ template<typename T>
template<typename O> template<typename O>
Q_OUTOFLINE_TEMPLATE QList<O> Query<T>::select(const std::function<O (const QSqlQuery &)> allocator) Q_OUTOFLINE_TEMPLATE QList<O> Query<T>::select(const std::function<O (const QSqlQuery &)> allocator)
{ {
Q_D(Query); //Q_D(AbstractQuery);
QList<O> ret; QList<O> ret;
d->joins.prepend(d->tableName); d->joins.prepend(d->tableName);
d->sql = d->database->sqlGenerator()->selectCommand( d->sql = d->database->sqlGenerator()->selectCommand(d->tableName,
d->tableName, AbstractSqlGenerator::SingleField,
SqlGeneratorBase::SingleField, "*", QStringLiteral("*"),
d->wherePhrase, d->wherePhrase,
d->relations, d->relations,
d->skip, d->take); d->skip,
d->take);
QSqlQuery q = d->database->exec(d->sql); QSqlQuery q = d->database->exec(d->sql);
@ -132,47 +171,66 @@ Q_OUTOFLINE_TEMPLATE QList<O> Query<T>::select(const std::function<O (const QSql
ret.append(obj); ret.append(obj);
} }
if (m_autoDelete)
deleteLater();
return ret; return ret;
} }
//template <typename T> //template <typename T>
//inline Query<T> *createQuery(TableSet<T> *tableSet) //inline Query<T> &createQuery(TableSet<T> *tableSet)
//{ //{
// return tableSet->query(); // return tableSet->query();
//} //}
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE Query<T>::Query(Database *database, TableSetBase *tableSet, Q_OUTOFLINE_TEMPLATE Query<T>::Query(Database *database, AbstractTableSet *tableSet)
bool autoDelete) : d(new QueryData(database))
: QueryBase(database), d_ptr(new QueryPrivate(this)),
m_autoDelete(autoDelete)
{ {
Q_D(Query); //Q_D(AbstractQuery);
d->database = database; d->database = database;
d->tableSet = tableSet; d->tableSet = tableSet;
d->className = T::staticMetaObject.className(); d->className = QString::fromUtf8(T::staticMetaObject.className());
d->tableName = d->tableName =
d->database->model() d->database->model()
.tableByClassName(d->className) .tableByClassName(d->className)
->name(); ->name();
} }
template<class T>
Q_OUTOFLINE_TEMPLATE Query<T>::Query(const Query<T> &other) {
d = other.d->clone();
}
template<class T>
Q_OUTOFLINE_TEMPLATE Query<T>::Query(Query<T> &&other) {
d = std::move(other.d);
other.d = nullptr;
}
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE Query<T>::~Query() Q_OUTOFLINE_TEMPLATE Query<T>::~Query()
{ {
Q_D(Query); //Q_D(AbstractQuery);
delete d; delete d;
} }
template<class T>
Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::operator=(const Query<T> &q)
{
if (this != &q)
{
QueryData *p = q.d ? q.d->clone() : nullptr;
delete d;
d = p;
}
return *this;
}
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE RowList<T> Query<T>::toList(int count) Q_OUTOFLINE_TEMPLATE RowList<T> Query<T>::toList(int count)
{ {
Q_D(Query); //Q_D(AbstractQuery);
RowList<T> returnList; RowList<T> returnList;
d->select = "*"; d->select = QStringLiteral("*");
d->sql = d->database->sqlGenerator()->selectCommand( d->sql = d->database->sqlGenerator()->selectCommand(
d->tableName, d->fieldPhrase, d->wherePhrase, d->orderPhrase, d->tableName, d->fieldPhrase, d->wherePhrase, d->orderPhrase,
@ -186,7 +244,7 @@ Q_OUTOFLINE_TEMPLATE RowList<T> Query<T>::toList(int count)
QSet<TableModel*> relatedTables; QSet<TableModel*> relatedTables;
relatedTables << d->database->model().tableByName(d->tableName); relatedTables << d->database->model().tableByName(d->tableName);
foreach (RelationModel *rel, d->relations) Q_FOREACH (RelationModel *rel, d->relations)
relatedTables << rel->slaveTable << rel->masterTable; relatedTables << rel->slaveTable << rel->masterTable;
struct LevelData{ struct LevelData{
@ -207,11 +265,13 @@ Q_OUTOFLINE_TEMPLATE RowList<T> Query<T>::toList(int count)
LevelData data; LevelData data;
data.table = table; data.table = table;
data.keyFiledname = data.table->name() + "." + data.table->primaryKey(); data.keyFiledname = data.table->name()
+ QStringLiteral(".")
+ data.table->primaryKey();
data.lastKeyValue = QVariant(); data.lastKeyValue = QVariant();
QHash<QString, QString> masters; QHash<QString, QString> masters;
foreach (RelationModel *rel, d->relations) Q_FOREACH (RelationModel *rel, d->relations)
if (rel->slaveTable->name() == table->name()) if (rel->slaveTable->name() == table->name())
masters.insert(rel->masterTable->name(), rel->localProperty); masters.insert(rel->masterTable->name(), rel->localProperty);
@ -241,7 +301,7 @@ Q_OUTOFLINE_TEMPLATE RowList<T> Query<T>::toList(int count)
if (!importedTables.count()) { if (!importedTables.count()) {
LevelData data; LevelData data;
data.table = d->database->model().tableByName(d->tableName); data.table = d->database->model().tableByName(d->tableName);
data.keyFiledname = d->tableName + "." + data.table->primaryKey(); data.keyFiledname = d->tableName + QStringLiteral(".") + data.table->primaryKey();
data.lastKeyValue = QVariant(); data.lastKeyValue = QVariant();
levels.append(data); levels.append(data);
@ -277,7 +337,7 @@ Q_OUTOFLINE_TEMPLATE RowList<T> Query<T>::toList(int count)
} }
// check if master if current table has processed // check if master if current table has processed
foreach (int m, data.masters) Q_FOREACH (int m, data.masters)
if (!checked[m]) { if (!checked[m]) {
// qDebug() << "row is checked"; // qDebug() << "row is checked";
continue; continue;
@ -290,11 +350,14 @@ Q_OUTOFLINE_TEMPLATE RowList<T> Query<T>::toList(int count)
//create table row //create table row
Row<Table> row; Row<Table> row;
if (data.table->className() == d->className) { if (data.table->className() == d->className) {
row = Nut::create<T>(); Row<T> tmpRow = Nut::create<T>();
#ifdef NUT_SHARED_POINTER row = tmpRow.template objectCast<Table>();
returnList.append(row.objectCast<T>());
#else row->init();
#ifdef NUT_RAW_POINTER
returnList.append(dynamic_cast<T*>(table)); returnList.append(dynamic_cast<T*>(table));
#else
returnList.append(tmpRow);
#endif #endif
d->tableSet->add(row); d->tableSet->add(row);
@ -311,21 +374,36 @@ Q_OUTOFLINE_TEMPLATE RowList<T> Query<T>::toList(int count)
} }
QList<FieldModel*> childFields = data.table->fields(); QList<FieldModel*> childFields = data.table->fields();
foreach (FieldModel *field, childFields) Q_FOREACH (FieldModel *field, childFields)
row->setProperty(field->name.toLatin1().data(), row->setProperty(field->name.toLatin1().data(),
d->database->sqlGenerator()->unescapeValue( d->database->sqlGenerator()->unescapeValue(
field->type, field->type,
q.value(data.table->name() + "." + field->name))); q.value(data.table->name() + QStringLiteral(".") + field->name)));
for (int i = 0; i < data.masters.count(); ++i) { for (int i = 0; i < data.masters.count(); ++i) {
int master = data.masters[i]; int master = data.masters[i];
auto tableset = levels[master].lastRow.data()->childTableSet( auto tableset = levels[master].lastRow.data()->childTableSet(
data.table->className()); data.table->className());
tableset->add(row); if (tableset)
tableset->add(row);
//set key
{
QString setterName = data.masterFields[master];
setterName[0] = setterName[0].toUpper();
setterName.prepend(QStringLiteral("set"));
bool ok = row->metaObject()->invokeMethod(row.data(),
setterName.toStdString().c_str(),
Qt::DirectConnection,
Q_ARG(Nut::Row<Nut::Table>,
levels[master].lastRow));
}
} }
row->setStatus(Table::FetchedFromDB); row->setStatus(Table::FetchedFromDB);
row->setParent(this); // row->setParent(this);
row->clear(); row->clear();
//set last created row //set last created row
@ -333,10 +411,6 @@ Q_OUTOFLINE_TEMPLATE RowList<T> Query<T>::toList(int count)
} //while } //while
} // while } // while
#ifndef NUT_SHARED_POINTER
if (m_autoDelete)
deleteLater();
#endif
return returnList; return returnList;
} }
@ -345,13 +419,13 @@ template <typename T>
template <typename F> template <typename F>
Q_OUTOFLINE_TEMPLATE QList<F> Query<T>::select(const FieldPhrase<F> f) Q_OUTOFLINE_TEMPLATE QList<F> Query<T>::select(const FieldPhrase<F> f)
{ {
Q_D(Query); //Q_D(AbstractQuery);
QList<F> ret; QList<F> ret;
d->joins.prepend(d->tableName); d->joins.prepend(d->tableName);
d->sql = d->database->sqlGenerator()->selectCommand( d->sql = d->database->sqlGenerator()->selectCommand(
d->tableName, d->tableName,
SqlGeneratorBase::SingleField, f.data->toString(), AbstractSqlGenerator::SingleField, f.data->toString(),
d->wherePhrase, d->wherePhrase,
d->relations, d->relations,
d->skip, d->take); d->skip, d->take);
@ -363,8 +437,6 @@ Q_OUTOFLINE_TEMPLATE QList<F> Query<T>::select(const FieldPhrase<F> f)
ret.append(v.value<F>()); ret.append(v.value<F>());
} }
if (m_autoDelete)
deleteLater();
return ret; return ret;
} }
@ -383,13 +455,13 @@ Q_OUTOFLINE_TEMPLATE Row<T> Query<T>::first()
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE int Query<T>::count() Q_OUTOFLINE_TEMPLATE int Query<T>::count()
{ {
Q_D(Query); //Q_D(AbstractQuery);
d->joins.prepend(d->tableName); d->joins.prepend(d->tableName);
d->select = "COUNT(*)"; d->select = QStringLiteral("COUNT(*)");
d->sql = d->database->sqlGenerator()->selectCommand( d->sql = d->database->sqlGenerator()->selectCommand(
d->tableName, d->tableName,
SqlGeneratorBase::Count, AbstractSqlGenerator::Count,
QStringLiteral("*"), QStringLiteral("*"),
d->wherePhrase, d->wherePhrase,
d->relations); d->relations);
@ -403,12 +475,12 @@ Q_OUTOFLINE_TEMPLATE int Query<T>::count()
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::max(const FieldPhrase<int> &f) Q_OUTOFLINE_TEMPLATE QVariant Query<T>::max(const FieldPhrase<int> &f)
{ {
Q_D(Query); //Q_D(AbstractQuery);
d->joins.prepend(d->tableName); d->joins.prepend(d->tableName);
d->sql = d->database->sqlGenerator()->selectCommand( d->sql = d->database->sqlGenerator()->selectCommand(
d->tableName, d->tableName,
SqlGeneratorBase::Max, f.data->toString(), AbstractSqlGenerator::Max, f.data->toString(),
d->wherePhrase, d->wherePhrase,
d->relations); d->relations);
QSqlQuery q = d->database->exec(d->sql); QSqlQuery q = d->database->exec(d->sql);
@ -421,12 +493,12 @@ Q_OUTOFLINE_TEMPLATE QVariant Query<T>::max(const FieldPhrase<int> &f)
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::min(const FieldPhrase<int> &f) Q_OUTOFLINE_TEMPLATE QVariant Query<T>::min(const FieldPhrase<int> &f)
{ {
Q_D(Query); //Q_D(AbstractQuery);
d->joins.prepend(d->tableName); d->joins.prepend(d->tableName);
d->sql = d->database->sqlGenerator()->selectCommand( d->sql = d->database->sqlGenerator()->selectCommand(
d->tableName, d->tableName,
SqlGeneratorBase::Min, f.data->toString(), AbstractSqlGenerator::Min, f.data->toString(),
d->wherePhrase, d->wherePhrase,
d->relations); d->relations);
QSqlQuery q = d->database->exec(d->sql); QSqlQuery q = d->database->exec(d->sql);
@ -439,12 +511,12 @@ Q_OUTOFLINE_TEMPLATE QVariant Query<T>::min(const FieldPhrase<int> &f)
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::sum(const FieldPhrase<int> &f) Q_OUTOFLINE_TEMPLATE QVariant Query<T>::sum(const FieldPhrase<int> &f)
{ {
Q_D(Query); //Q_D(AbstractQuery);
d->joins.prepend(d->tableName); d->joins.prepend(d->tableName);
d->sql = d->database->sqlGenerator()->selectCommand( d->sql = d->database->sqlGenerator()->selectCommand(
d->tableName, d->tableName,
SqlGeneratorBase::Sum, f.data->toString(), AbstractSqlGenerator::Sum, f.data->toString(),
d->wherePhrase, d->wherePhrase,
d->relations); d->relations);
QSqlQuery q = d->database->exec(d->sql); QSqlQuery q = d->database->exec(d->sql);
@ -457,12 +529,12 @@ Q_OUTOFLINE_TEMPLATE QVariant Query<T>::sum(const FieldPhrase<int> &f)
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::average(const FieldPhrase<int> &f) Q_OUTOFLINE_TEMPLATE QVariant Query<T>::average(const FieldPhrase<int> &f)
{ {
Q_D(Query); //Q_D(AbstractQuery);
d->joins.prepend(d->tableName); d->joins.prepend(d->tableName);
d->sql = d->database->sqlGenerator()->selectCommand( d->sql = d->database->sqlGenerator()->selectCommand(
d->tableName, d->tableName,
SqlGeneratorBase::Average, f.data->toString(), AbstractSqlGenerator::Average, f.data->toString(),
d->wherePhrase, d->wherePhrase,
d->relations); d->relations);
QSqlQuery q = d->database->exec(d->sql); QSqlQuery q = d->database->exec(d->sql);
@ -475,7 +547,7 @@ Q_OUTOFLINE_TEMPLATE QVariant Query<T>::average(const FieldPhrase<int> &f)
template<class T> template<class T>
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::insert(const AssignmentPhraseList &p) Q_OUTOFLINE_TEMPLATE QVariant Query<T>::insert(const AssignmentPhraseList &p)
{ {
Q_D(Query); //Q_D(AbstractQuery);
d->sql = d->database->sqlGenerator() d->sql = d->database->sqlGenerator()
->insertCommand(d->tableName, p); ->insertCommand(d->tableName, p);
QSqlQuery q = d->database->exec(d->sql); QSqlQuery q = d->database->exec(d->sql);
@ -484,9 +556,9 @@ Q_OUTOFLINE_TEMPLATE QVariant Query<T>::insert(const AssignmentPhraseList &p)
} }
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::join(const QString &className) Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::join(const QString &className)
{ {
Q_D(Query); //Q_D(AbstractQuery);
RelationModel *rel = d->database->model() RelationModel *rel = d->database->model()
.relationByClassNames(d->className, className); .relationByClassNames(d->className, className);
@ -497,85 +569,85 @@ Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::join(const QString &className)
if (!rel) { if (!rel) {
qDebug() << "No relation between" << d->className qDebug() << "No relation between" << d->className
<< "and" << className; << "and" << className;
return this; return *this;
} }
d->relations.append(rel); d->relations.append(rel);
d->joins.append(className); d->joins.append(className);
return this; return *this;
} }
template<class T> template<class T>
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::join(Table *c) Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::join(Table *c)
{ {
join(c->metaObject()->className()); join(c->metaObject()->className());
return this; return *this;
} }
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::where(const ConditionalPhrase &ph) Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::where(const ConditionalPhrase &ph)
{ {
Q_D(Query); //Q_D(AbstractQuery);
if (d->wherePhrase.data) if (d->wherePhrase.data)
d->wherePhrase = d->wherePhrase && ph; d->wherePhrase = d->wherePhrase && ph;
else else
d->wherePhrase = ph; d->wherePhrase = ph;
return this; return *this;
} }
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::setWhere(const ConditionalPhrase &ph) Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::setWhere(const ConditionalPhrase &ph)
{ {
Q_D(Query); //Q_D(AbstractQuery);
d->wherePhrase = ph; d->wherePhrase = ph;
return this; return *this;
} }
template<class T> template<class T>
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::skip(int n) Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::skip(int n)
{ {
Q_D(Query); //Q_D(AbstractQuery);
d->skip = n; d->skip = n;
return this; return *this;
} }
template<class T> template<class T>
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::take(int n) Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::take(int n)
{ {
Q_D(Query); //Q_D(AbstractQuery);
d->take = n; d->take = n;
return this; return *this;
} }
template<class T> template<class T>
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::fields(const PhraseList &ph) Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::fields(const PhraseList &ph)
{ {
Q_D(Query); //Q_D(AbstractQuery);
d->fieldPhrase = ph; d->fieldPhrase = ph;
return this; return *this;
} }
//template <class T> //template <class T>
//Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::orderBy(QString fieldName, //Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::orderBy(QString fieldName,
// QString type) // QString type)
//{ //{
// Q_D(Query); // //Q_D(AbstractQuery);
// d->orderPhrases.append(fieldName, type); // d->orderPhrases.append(fieldName, type);
// return this; // return *this;
//} //}
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::orderBy(const PhraseList &ph) Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::orderBy(const PhraseList &ph)
{ {
Q_D(Query); //Q_D(AbstractQuery);
d->orderPhrase = ph; d->orderPhrase = ph;
return this; return *this;
} }
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE int Query<T>::update(const AssignmentPhraseList &ph) Q_OUTOFLINE_TEMPLATE int Query<T>::update(const AssignmentPhraseList &ph)
{ {
Q_D(Query); //Q_D(AbstractQuery);
d->sql = d->database->sqlGenerator()->updateCommand( d->sql = d->database->sqlGenerator()->updateCommand(
d->tableName, d->tableName,
@ -584,22 +656,18 @@ Q_OUTOFLINE_TEMPLATE int Query<T>::update(const AssignmentPhraseList &ph)
QSqlQuery q = d->database->exec(d->sql); QSqlQuery q = d->database->exec(d->sql);
if (m_autoDelete)
deleteLater();
return q.numRowsAffected(); return q.numRowsAffected();
} }
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE int Query<T>::remove() Q_OUTOFLINE_TEMPLATE int Query<T>::remove()
{ {
Q_D(Query); //Q_D(AbstractQuery);
d->sql = d->database->sqlGenerator()->deleteCommand( d->sql = d->database->sqlGenerator()->deleteCommand(
d->tableName, d->wherePhrase); d->tableName, d->wherePhrase);
QSqlQuery q = d->database->exec(d->sql); QSqlQuery q = d->database->exec(d->sql);
if (m_autoDelete)
deleteLater();
return q.numRowsAffected(); return q.numRowsAffected();
} }
@ -614,7 +682,7 @@ Q_OUTOFLINE_TEMPLATE QSqlQueryModel *Query<T>::toModel()
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE void Query<T>::toModel(QSqlQueryModel *model) Q_OUTOFLINE_TEMPLATE void Query<T>::toModel(QSqlQueryModel *model)
{ {
Q_D(Query); //Q_D(AbstractQuery);
d->sql = d->database->sqlGenerator()->selectCommand( d->sql = d->database->sqlGenerator()->selectCommand(
d->tableName, d->tableName,
@ -628,9 +696,11 @@ Q_OUTOFLINE_TEMPLATE void Query<T>::toModel(QSqlQueryModel *model)
int fieldIndex = 0; int fieldIndex = 0;
if (d->fieldPhrase.data.count()) { if (d->fieldPhrase.data.count()) {
foreach (const PhraseData *pd, d->fieldPhrase.data) { Q_FOREACH (const PhraseData *pd, d->fieldPhrase.data) {
QString displayName = dbModel.tableByClassName(pd->className) QString displayName = dbModel
->field(pd->fieldName)->displayName; .tableByClassName(QString::fromUtf8(pd->className))
->field(QString::fromUtf8(pd->fieldName))
->displayName;
model->setHeaderData(fieldIndex++, model->setHeaderData(fieldIndex++,
Qt::Horizontal, Qt::Horizontal,
@ -638,7 +708,7 @@ Q_OUTOFLINE_TEMPLATE void Query<T>::toModel(QSqlQueryModel *model)
} }
} else { } else {
TableModel *tbl = d->database->model().tableByName(d->tableName); TableModel *tbl = d->database->model().tableByName(d->tableName);
foreach (FieldModel *f, tbl->fields()) { Q_FOREACH (FieldModel *f, tbl->fields()) {
model->setHeaderData(fieldIndex++, model->setHeaderData(fieldIndex++,
Qt::Horizontal, Qt::Horizontal,
f->displayName); f->displayName);
@ -649,7 +719,7 @@ Q_OUTOFLINE_TEMPLATE void Query<T>::toModel(QSqlQueryModel *model)
template<class T> template<class T>
Q_OUTOFLINE_TEMPLATE void Query<T>::toModel(SqlModel *model) Q_OUTOFLINE_TEMPLATE void Query<T>::toModel(SqlModel *model)
{ {
Q_D(Query); //Q_D(AbstractQuery);
d->sql = d->database->sqlGenerator()->selectCommand( d->sql = d->database->sqlGenerator()->selectCommand(
d->tableName, d->tableName,
@ -665,7 +735,7 @@ Q_OUTOFLINE_TEMPLATE void Query<T>::toModel(SqlModel *model)
int fieldIndex = 0; int fieldIndex = 0;
if (d->fieldPhrase.data.count()) { if (d->fieldPhrase.data.count()) {
foreach (const PhraseData *pd, d->fieldPhrase.data) { Q_FOREACH (const PhraseData *pd, d->fieldPhrase.data) {
QString displayName = dbModel.tableByClassName(pd->className) QString displayName = dbModel.tableByClassName(pd->className)
->field(pd->fieldName)->displayName; ->field(pd->fieldName)->displayName;
@ -675,7 +745,7 @@ Q_OUTOFLINE_TEMPLATE void Query<T>::toModel(SqlModel *model)
} }
} else { } else {
TableModel *tbl = d->database->model().tableByName(d->tableName); TableModel *tbl = d->database->model().tableByName(d->tableName);
foreach (FieldModel *f, tbl->fields()) { Q_FOREACH (FieldModel *f, tbl->fields()) {
model->setHeaderData(fieldIndex++, model->setHeaderData(fieldIndex++,
Qt::Horizontal, Qt::Horizontal,
f->displayName); f->displayName);
@ -686,7 +756,7 @@ Q_OUTOFLINE_TEMPLATE void Query<T>::toModel(SqlModel *model)
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE QString Query<T>::sqlCommand() const Q_OUTOFLINE_TEMPLATE QString Query<T>::sqlCommand() const
{ {
Q_D(const Query); //Q_D(const AbstractQuery);
return d->sql; return d->sql;
} }
@ -701,4 +771,4 @@ Q_OUTOFLINE_TEMPLATE QString Query<T>::sqlCommand() const
NUT_END_NAMESPACE NUT_END_NAMESPACE
#endif // QUERY_H #endif // NUT_QUERY_H

View File

@ -18,16 +18,17 @@
** **
**************************************************************************/ **************************************************************************/
#include <QMetaMethod> #include <QtCore/QMetaMethod>
#include <QVariant> #include <QtCore/QVariant>
#include <QSqlQuery> #include <QtSql/QSqlQuery>
#include "table.h" #include "table.h"
#include "table_p.h" #include "table_p.h"
#include "database.h" #include "database.h"
#include "databasemodel.h" #include "databasemodel.h"
#include "generators/sqlgeneratorbase_p.h" #include "abstractsqlgenerator.h"
#include "tablesetbase_p.h" #include "abstracttableset.h"
#include "propertysignalmapper.h"
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
@ -43,6 +44,10 @@ NUT_BEGIN_NAMESPACE
* This should be fixed to v1.2 * This should be fixed to v1.2
*/ */
/*!
* \class Table
* \brief Base class for all tables
*/
Table::Table(QObject *parent) : QObject(parent), Table::Table(QObject *parent) : QObject(parent),
d(new TablePrivate) d(new TablePrivate)
{ } { }
@ -55,7 +60,7 @@ Table::~Table()
// d->parentTableSet->remove(this); // d->parentTableSet->remove(this);
} }
void Table::add(TableSetBase *t) void Table::add(AbstractTableSet *t)
{ {
//Q_D(Table); //Q_D(Table);
d->childTableSets.insert(t); d->childTableSets.insert(t);
@ -91,7 +96,7 @@ void Table::propertyChanged(const QString &propName)
// if (!d->model) // if (!d->model)
// qFatal ("model for class '%s' not found", qPrintable(metaObject()->className())); // qFatal ("model for class '%s' not found", qPrintable(metaObject()->className()));
// foreach (FieldModel *f, d->model->fields()) // Q_FOREACH (FieldModel *f, d->model->fields())
// if(f->isPrimaryKey && propName == f->name && f->isAutoIncrement) // if(f->isPrimaryKey && propName == f->name && f->isAutoIncrement)
// return; // return;
@ -127,13 +132,13 @@ bool Table::setParentTable(Table *master, TableModel *masterModel, TableModel *m
//Q_D(Table); //Q_D(Table);
d.detach(); d.detach();
QString masterClassName = master->metaObject()->className(); QString masterClassName = QString::fromUtf8(master->metaObject()->className());
d->refreshModel(); d->refreshModel();
// if (!d->model) // if (!d->model)
// d->model = TableModel::findByClassName(metaObject()->className()); // d->model = TableModel::findByClassName(metaObject()->className());
foreach (RelationModel *r, model->foreignKeys()) Q_FOREACH (RelationModel *r, model->foreignKeys())
if(r->masterClassName == masterClassName) if(r->masterClassName == masterClassName)
{ {
setProperty(QString(r->localColumn).toLatin1().data(), setProperty(QString(r->localColumn).toLatin1().data(),
@ -145,13 +150,24 @@ bool Table::setParentTable(Table *master, TableModel *masterModel, TableModel *m
return false; return false;
} }
TableSetBase *Table::parentTableSet() const void Table::propertyChanged()
{
auto pname = PropertySignalMapper::changedProperty(this, senderSignalIndex());
propertyChanged(pname);
}
void Table::init()
{
PropertySignalMapper::map(this);
}
AbstractTableSet *Table::parentTableSet() const
{ {
//Q_D(const Table); //Q_D(const Table);
return d->parentTableSet; return d->parentTableSet;
} }
void Table::setParentTableSet(TableSetBase *parent) void Table::setParentTableSet(AbstractTableSet *parent)
{ {
//Q_D(Table); //Q_D(Table);
d->parentTableSet = parent; d->parentTableSet = parent;
@ -160,10 +176,10 @@ void Table::setParentTableSet(TableSetBase *parent)
// d->parentTableSet->add(this); // d->parentTableSet->add(this);
} }
TableSetBase *Table::childTableSet(const QString &name) const AbstractTableSet *Table::childTableSet(const QString &name) const
{ {
//Q_D(const Table); //Q_D(const Table);
foreach (TableSetBase *t, d->childTableSets) Q_FOREACH (AbstractTableSet *t, d->childTableSets)
if (t->childClassName() == name) if (t->childClassName() == name)
return t; return t;
return Q_NULLPTR; return Q_NULLPTR;
@ -173,13 +189,13 @@ int Table::save(Database *db)
{ {
//Q_D(Table); //Q_D(Table);
QSqlQuery q = db->exec(db->sqlGenerator()->saveRecord(this, db->tableName(metaObject()->className()))); QSqlQuery q = db->exec(db->sqlGenerator()->saveRecord(this, db->tableName(QString::fromUtf8(metaObject()->className()))));
auto model = db->model().tableByClassName(metaObject()->className()); auto model = db->model().tableByClassName(QString::fromUtf8(metaObject()->className()));
if(status() == Added && model->isPrimaryKeyAutoIncrement()) if(status() == Added && model->isPrimaryKeyAutoIncrement())
setProperty(model->primaryKey().toLatin1().data(), q.lastInsertId()); setProperty(model->primaryKey().toLatin1().data(), q.lastInsertId());
foreach(TableSetBase *ts, d->childTableSets) foreach(AbstractTableSet *ts, d->childTableSets)
ts->save(db); ts->save(db);
setStatus(FetchedFromDB); setStatus(FetchedFromDB);

View File

@ -25,14 +25,14 @@
#include <QtCore/qglobal.h> #include <QtCore/qglobal.h>
#include <QtCore/QSet> #include <QtCore/QSet>
#include "tablemodel.h" #include <QtNut/nut_global.h>
#include "defines.h" #include <QtNut/tablemodel.h>
#include "phrase.h" #include <QtNut/phrase.h>
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
class Database; class Database;
class TableSetBase; class AbstractTableSet;
class TableModel; class TableModel;
class TablePrivate; class TablePrivate;
class NUT_EXPORT Table : public QObject class NUT_EXPORT Table : public QObject
@ -61,39 +61,44 @@ public:
Status status() const; Status status() const;
void setStatus(const Status &status); void setStatus(const Status &status);
TableSetBase *parentTableSet() const; AbstractTableSet *parentTableSet() const;
void setParentTableSet(TableSetBase *parentTableSet); void setParentTableSet(AbstractTableSet *parentTableSet);
TableSetBase *childTableSet(const QString &name) const; AbstractTableSet *childTableSet(const QString &name) const;
QSet<QString> changedProperties() const; QSet<QString> changedProperties() const;
bool setParentTable(Table *master, TableModel *masterModel, TableModel *model); bool setParentTable(Table *master, TableModel *masterModel, TableModel *model);
signals: Q_SIGNALS:
public slots: public Q_SLOTS:
void propertyChanged();
protected: protected:
void init();
void propertyChanged(const QString &propName); void propertyChanged(const QString &propName);
private: private:
bool _is_signals_mapped{false};
void setModel(TableModel *model); void setModel(TableModel *model);
// TableModel *myModel; // TableModel *myModel;
// Status _status; // Status _status;
// QSet<QString> _changedProperties; // QSet<QString> _changedProperties;
//TODO: is this removable? //TODO: is this removable?
// TableSetBase *_parentTableSet; // AbstractTableSet *_parentTableSet;
// QSet<TableSetBase*> childTableSets; // QSet<AbstractTableSet*> childTableSets;
void clear(); void clear();
void add(TableSetBase *); void add(AbstractTableSet *);
template<class T> template<class T>
friend class Query; friend class Query;
template<class T> template<class T>
friend class TableSet; friend class TableSet;
friend class TableSetBase; friend class AbstractTableSet;
friend class PropertySignalMapper;
}; };
NUT_END_NAMESPACE NUT_END_NAMESPACE

View File

@ -1,16 +1,17 @@
#ifndef TABLEPRIVATE_H #ifndef TABLEPRIVATE_H
#define TABLEPRIVATE_H #define TABLEPRIVATE_H
#include "defines.h"
#include <QtCore/QSet> #include <QtCore/QSet>
#include <QSharedData> #include <QtCore/QSharedData>
#include <QtNut/nut_global.h>
#include <QtNut/table.h>
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
class TableModel; class TableModel;
class Table; class Table;
class TableSetBase; class AbstractTableSet;
class TablePrivate : public QSharedData { class TablePrivate : public QSharedData {
Table *q_ptr; Table *q_ptr;
Q_DECLARE_PUBLIC(Table) Q_DECLARE_PUBLIC(Table)
@ -22,8 +23,8 @@ public:
TableModel *model; TableModel *model;
Table::Status status; Table::Status status;
QSet<QString> changedProperties; QSet<QString> changedProperties;
TableSetBase *parentTableSet; AbstractTableSet *parentTableSet;
QSet<TableSetBase*> childTableSets; QSet<AbstractTableSet*> childTableSets;
void refreshModel(); void refreshModel();
}; };

View File

@ -25,14 +25,15 @@
#include <QtCore/QMetaMethod> #include <QtCore/QMetaMethod>
#include <QtCore/QMetaType> #include <QtCore/QMetaType>
#include <QtCore/QVariant> #include <QtCore/QVariant>
#include <QtSql/QSqlQuery> #include <QtCore/QSharedPointer>
#include <QSharedPointer>
#include "tablesetbase_p.h" #include <QtSql/QSqlQuery>
#include "table.h"
#include "bulkinserter.h" #include <QtNut/abstracttableset.h>
#include "databasemodel.h" #include <QtNut/table.h>
#include "tablesetbasedata.h" #include <QtNut/bulkinserter.h>
#include <QtNut/databasemodel.h>
#include <QtNut/abstracttablesetdata.h>
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
@ -43,7 +44,7 @@ class BulkInserter;
class Database; class Database;
template<class T> template<class T>
class TableSet : public TableSetBase class TableSet : public AbstractTableSet
{ {
public: public:
typedef T value_type; typedef T value_type;
@ -53,6 +54,10 @@ public:
explicit TableSet(Database *parent); explicit TableSet(Database *parent);
explicit TableSet(Table *parent); explicit TableSet(Table *parent);
#ifndef NUT_RAW_POINTER
void append(T *t);
void append(QList<T*> t);
#endif
void append(Row<T> t); void append(Row<T> t);
void append(RowList<T> t); void append(RowList<T> t);
void remove(Row<T> t); void remove(Row<T> t);
@ -62,35 +67,32 @@ public:
Row<T> at(int i) const; Row<T> at(int i) const;
Row<T> operator[](int i) const; Row<T> operator[](int i) const;
Query<T> *query(bool autoDelete = true); Query<T> query();
BulkInserter *bulkInserter(); BulkInserter bulkInserter();
}; };
template<class T> template<class T>
Q_OUTOFLINE_TEMPLATE TableSet<T>::TableSet(Database *parent) : TableSetBase(parent) Q_OUTOFLINE_TEMPLATE TableSet<T>::TableSet(Database *parent) : AbstractTableSet(parent)
{ {
data->childClassName = T::staticMetaObject.className(); data->childClassName = QString::fromUtf8(T::staticMetaObject.className());
} }
template<class T> template<class T>
Q_OUTOFLINE_TEMPLATE TableSet<T>::TableSet(Table *parent) : TableSetBase(parent) Q_OUTOFLINE_TEMPLATE TableSet<T>::TableSet(Table *parent) : AbstractTableSet(parent)
{ {
data->childClassName = T::staticMetaObject.className(); data->childClassName = QString::fromUtf8(T::staticMetaObject.className());
} }
template<class T> template<class T>
Q_OUTOFLINE_TEMPLATE Query<T> *TableSet<T>::query(bool autoDelete) Q_OUTOFLINE_TEMPLATE Query<T> TableSet<T>::query()
{ {
Query<T> *q = new Query<T>(data->database, this, autoDelete); return Query<T>(data->database, this);
return q;
} }
template<class T> template<class T>
Q_OUTOFLINE_TEMPLATE BulkInserter *TableSet<T>::bulkInserter() Q_OUTOFLINE_TEMPLATE BulkInserter TableSet<T>::bulkInserter()
{ {
BulkInserter *bi = new BulkInserter(data->database, data->childClassName); return BulkInserter(data->database, data->childClassName);
return bi;
} }
template<class T> template<class T>
@ -102,10 +104,10 @@ Q_OUTOFLINE_TEMPLATE int TableSet<T>::length() const
template<class T> template<class T>
Q_OUTOFLINE_TEMPLATE Row<T> TableSet<T>::at(int i) const Q_OUTOFLINE_TEMPLATE Row<T> TableSet<T>::at(int i) const
{ {
#ifdef NUT_SHARED_POINTER #ifdef NUT_RAW_POINTER
return data->childs.at(i).template objectCast<T>();
#else
return reinterpret_cast<T*>(data->childs.at(i)); return reinterpret_cast<T*>(data->childs.at(i));
#else
return data->childs.at(i).template objectCast<T>();
#endif #endif
} }
@ -115,6 +117,21 @@ Q_OUTOFLINE_TEMPLATE Row<T> TableSet<T>::operator[](int i) const
return at(i); return at(i);
} }
#ifndef NUT_RAW_POINTER
template<class T>
Q_OUTOFLINE_TEMPLATE void TableSet<T>::append(T *t)
{
append(QSharedPointer<T>(t));
}
template<class T>
Q_OUTOFLINE_TEMPLATE void TableSet<T>::append(QList<T*> t)
{
for (auto &table: t)
append(table);
}
#endif
template<class T> template<class T>
Q_OUTOFLINE_TEMPLATE void TableSet<T>::append(Row<T> t) Q_OUTOFLINE_TEMPLATE void TableSet<T>::append(Row<T> t)
{ {
@ -134,7 +151,7 @@ Q_OUTOFLINE_TEMPLATE void TableSet<T>::append(Row<T> t)
template<class T> template<class T>
Q_OUTOFLINE_TEMPLATE void TableSet<T>::append(RowList<T> t) Q_OUTOFLINE_TEMPLATE void TableSet<T>::append(RowList<T> t)
{ {
foreach (Row<T> i, t) Q_FOREACH (Row<T> i, t)
append(i); append(i);
} }
@ -151,7 +168,7 @@ Q_OUTOFLINE_TEMPLATE void TableSet<T>::remove(Row<T> t)
template<class T> template<class T>
Q_OUTOFLINE_TEMPLATE void TableSet<T>::remove(RowList<T> t) Q_OUTOFLINE_TEMPLATE void TableSet<T>::remove(RowList<T> t)
{ {
foreach (Row<T> i, t) Q_FOREACH (Row<T> i, t)
remove(i); remove(i);
} }

View File

@ -18,14 +18,14 @@
** **
**************************************************************************/ **************************************************************************/
#ifndef SQLGENERATORBASE_H #ifndef NUT_ABSTRACTSQLGENERATOR_H
#define SQLGENERATORBASE_H #define NUT_ABSTRACTSQLGENERATOR_H
#include <QtCore/qglobal.h> #include <QtCore/qglobal.h>
#include <QtCore/QObject> #include <QtCore/QObject>
#include <QtCore/QStringList> #include <QtCore/QStringList>
#include "../phrase.h"
//#include "../wherephrase.h" #include <QtNut/phrase.h>
class SqlSerializer; class SqlSerializer;
@ -37,7 +37,7 @@ class DatabaseModel;
class TableModel; class TableModel;
class Database; class Database;
struct RelationModel; struct RelationModel;
class NUT_EXPORT SqlGeneratorBase : public QObject class NUT_EXPORT AbstractSqlGenerator : public QObject
{ {
// Q_OBJECT // Q_OBJECT
@ -65,8 +65,8 @@ public:
Sum Sum
}; };
explicit SqlGeneratorBase(Database *parent); explicit AbstractSqlGenerator(Database *parent);
virtual ~SqlGeneratorBase() = default; virtual ~AbstractSqlGenerator() = default;
virtual bool supportPrimaryKey(const QMetaType::Type &type) { virtual bool supportPrimaryKey(const QMetaType::Type &type) {
Q_UNUSED(type) Q_UNUSED(type)
@ -168,4 +168,4 @@ protected:
NUT_END_NAMESPACE NUT_END_NAMESPACE
#endif // SQLGENERATORBASE_H #endif // NUT_ABSTRACTSQLGENERATOR_H

View File

@ -0,0 +1,15 @@
INCLUDEPATH += $$PWD
HEADERS += \
$$PWD/abstractsqlgenerator.h \
$$PWD/postgresqlgenerator.h \
$$PWD/mysqlgenerator.h \
$$PWD/sqlitegenerator.h \
$$PWD/sqlservergenerator.h
SOURCES += \
$$PWD/abstractsqlgenerator.cpp \
$$PWD/postgresqlgenerator.cpp \
$$PWD/mysqlgenerator.cpp \
$$PWD/sqlitegenerator.cpp \
$$PWD/sqlservergenerator.cpp

View File

@ -19,23 +19,23 @@
**************************************************************************/ **************************************************************************/
#include "mysqlgenerator.h" #include "mysqlgenerator.h"
#include "../tablemodel.h" #include "tablemodel.h"
#include <QPoint> #include <QtCore/QPoint>
#include <QPointF> #include <QtCore/QPointF>
#include <QTime> #include <QtCore/QTime>
#include <QDate> #include <QtCore/QDate>
#include <QDateTime> #include <QtCore/QDateTime>
#ifdef QT_GUI_LIB #ifdef QT_GUI_LIB
#include <QPolygon> # include <QtGui/QPolygon>
#include <QPolygonF> # include <QtGui/QPolygonF>
#endif #endif
#include "sqlserializer.h" #include "sqlserializer.h"
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
MySqlGenerator::MySqlGenerator(Database *parent) : SqlGeneratorBase(parent) MySqlGenerator::MySqlGenerator(Database *parent) : AbstractSqlGenerator(parent)
{ {
} }
@ -45,42 +45,42 @@ QString MySqlGenerator::fieldType(FieldModel *field)
QString dbType; QString dbType;
switch (field->type) { switch (field->type) {
case QMetaType::Bool: return "BOOLEAN"; case QMetaType::Bool: return QStringLiteral("BOOLEAN");
case QMetaType::Char: case QMetaType::Char:
case QMetaType::QChar: return "CHAR(1)"; case QMetaType::QChar: return QStringLiteral("CHAR(1)");
case QMetaType::SChar: case QMetaType::SChar:
case QMetaType::UChar: return "TINYINT"; case QMetaType::UChar: return QStringLiteral("TINYINT");
case QMetaType::Short: case QMetaType::Short:
case QMetaType::UShort: return "SMALLINT"; case QMetaType::UShort: return QStringLiteral("SMALLINT");
case QMetaType::UInt: case QMetaType::UInt:
case QMetaType::Int: case QMetaType::Int:
dbType = "INT"; dbType = QStringLiteral("INT");
if(field->isAutoIncrement) if(field->isAutoIncrement)
dbType += " AUTO_INCREMENT"; dbType += QStringLiteral(" AUTO_INCREMENT");
break; break;
case QMetaType::Long: case QMetaType::Long:
case QMetaType::ULong: case QMetaType::ULong:
case QMetaType::LongLong: case QMetaType::LongLong:
case QMetaType::ULongLong: case QMetaType::ULongLong:
return "BIGINT"; return QStringLiteral("BIGINT");
case QMetaType::Float: case QMetaType::Float:
return "FLOAT"; return QStringLiteral("FLOAT");
case QMetaType::Double: case QMetaType::Double:
return "REAL"; return QStringLiteral("REAL");
case QMetaType::QBitArray: return "VARBINARY"; case QMetaType::QBitArray: return QStringLiteral("VARBINARY");
case QMetaType::QByteArray: return "BLOB"; case QMetaType::QByteArray: return QStringLiteral("BLOB");
case QMetaType::QDate: return "DATE"; case QMetaType::QDate: return QStringLiteral("DATE");
case QMetaType::QTime: return "TIME"; case QMetaType::QTime: return QStringLiteral("TIME");
case QMetaType::QDateTime: return "DATETIME"; case QMetaType::QDateTime: return QStringLiteral("DATETIME");
case QMetaType::QString: case QMetaType::QString:
if(field->length) if(field->length)
dbType = QString("VARCHAR(%1)").arg(field->length); dbType = QStringLiteral("VARCHAR(%1)").arg(field->length);
else else
dbType = "TEXT"; dbType = QStringLiteral("TEXT");
break; break;
@ -109,7 +109,7 @@ QString MySqlGenerator::fieldType(FieldModel *field)
case QMetaType::QJsonValue: case QMetaType::QJsonValue:
case QMetaType::QJsonObject: case QMetaType::QJsonObject:
case QMetaType::QJsonDocument: case QMetaType::QJsonDocument:
case QMetaType::QStringList: return "TEXT"; case QMetaType::QStringList: return QStringLiteral("TEXT");
default: default:
qWarning("Type %s::%s(%d) is not supported", qWarning("Type %s::%s(%d) is not supported",
@ -128,16 +128,16 @@ QString MySqlGenerator::fieldType(FieldModel *field)
QString MySqlGenerator::escapeValue(const QVariant &v) const QString MySqlGenerator::escapeValue(const QVariant &v) const
{ {
if (v.type() == QVariant::Bool) if (v.type() == QVariant::Bool)
return v.toBool() ? "1" : "0"; return v.toBool() ? QStringLiteral("1") : QStringLiteral("0");
if (v.type() == QVariant::Time) if (v.type() == QVariant::Time)
return "'" + v.toTime().toString("HH:mm:ss") + "'"; return v.toTime().toString(QStringLiteral("''HH:mm:ss''"));
if (v.type() == QVariant::Date) if (v.type() == QVariant::Date)
return "'" + v.toDate().toString("yyyy-MM-dd") + "'"; return v.toDate().toString(QStringLiteral("''yyyy-MM-dd''"));
if (v.type() == QVariant::DateTime) if (v.type() == QVariant::DateTime)
return "'" + v.toDateTime().toString("yyyy-MM-dd HH:mm:ss") + "'"; return v.toDateTime().toString(QStringLiteral("''yyyy-MM-dd HH:mm:ss''"));
//#ifdef QT_GUI_LIB //#ifdef QT_GUI_LIB
// if (v.type() == QVariant::Polygon) { // if (v.type() == QVariant::Polygon) {
@ -178,7 +178,7 @@ QString MySqlGenerator::escapeValue(const QVariant &v) const
// } // }
// default: // default:
return SqlGeneratorBase::escapeValue(v); return AbstractSqlGenerator::escapeValue(v);
// } // }
} }
@ -194,7 +194,7 @@ QVariant MySqlGenerator::unescapeValue(const QMetaType::Type &type, const QVaria
// if (!readInsideParentese(ref, p)) // if (!readInsideParentese(ref, p))
// return pol; // return pol;
// QStringList parts = p.split(","); // QStringList parts = p.split(",");
// foreach (QString v, parts) { // Q_FOREACH (QString v, parts) {
// QList<int> l = _serializer->toListInt(p.trimmed(), " "); // QList<int> l = _serializer->toListInt(p.trimmed(), " ");
// if (l.count() != 2) // if (l.count() != 2)
// return QPolygon(); // return QPolygon();
@ -210,7 +210,7 @@ QVariant MySqlGenerator::unescapeValue(const QMetaType::Type &type, const QVaria
// return pol; // return pol;
// QStringList parts = p.split(","); // QStringList parts = p.split(",");
// foreach (QString v, parts) { // Q_FOREACH (QString v, parts) {
// QList<qreal> l = _serializer->toListReal(p.trimmed(), " "); // QList<qreal> l = _serializer->toListReal(p.trimmed(), " ");
// if (l.count() != 2) // if (l.count() != 2)
// return QPolygonF(); // return QPolygonF();
@ -229,7 +229,7 @@ QVariant MySqlGenerator::unescapeValue(const QMetaType::Type &type, const QVaria
if (type == QMetaType::QDate) if (type == QMetaType::QDate)
return dbValue.toDate(); return dbValue.toDate();
return SqlGeneratorBase::unescapeValue(type, dbValue); return AbstractSqlGenerator::unescapeValue(type, dbValue);
} }
bool MySqlGenerator::readInsideParentese(QString &text, QString &out) bool MySqlGenerator::readInsideParentese(QString &text, QString &out)
@ -316,10 +316,10 @@ QString MySqlGenerator::createConditionalPhrase(const PhraseData *d) const
case PhraseData::AddMinutesDateTime: case PhraseData::AddMinutesDateTime:
case PhraseData::AddSeconds: case PhraseData::AddSeconds:
case PhraseData::AddSecondsDateTime: case PhraseData::AddSecondsDateTime:
return QString("DATE_ADD(%1, INTERVAL %2 %3)") return QStringLiteral("DATE_ADD(%1, INTERVAL %2 %3)")
.arg(createConditionalPhrase(d->left), .arg(createConditionalPhrase(d->left),
d->operand.toString(), d->operand.toString(),
SqlGeneratorBase::dateTimePartName(op)); AbstractSqlGenerator::dateTimePartName(op));
default: default:
break; break;
@ -333,26 +333,26 @@ QString MySqlGenerator::createConditionalPhrase(const PhraseData *d) const
case PhraseData::DatePartHour: case PhraseData::DatePartHour:
case PhraseData::DatePartMinute: case PhraseData::DatePartMinute:
case PhraseData::DatePartSecond: case PhraseData::DatePartSecond:
return QString("%2(%1)") return QStringLiteral("%2(%1)")
.arg(createConditionalPhrase(d->left), .arg(createConditionalPhrase(d->left),
SqlGeneratorBase::dateTimePartName(op)); AbstractSqlGenerator::dateTimePartName(op));
default: default:
break; break;
} }
} }
return SqlGeneratorBase::createConditionalPhrase(d); return AbstractSqlGenerator::createConditionalPhrase(d);
} }
void MySqlGenerator::appendSkipTake(QString &sql, int skip, int take) void MySqlGenerator::appendSkipTake(QString &sql, int skip, int take)
{ {
if (take > 0 && skip > 0) { if (take > 0 && skip > 0) {
sql.append(QString(" LIMIT %1 OFFSET %2") sql.append(QStringLiteral(" LIMIT %1 OFFSET %2")
.arg(take) .arg(take)
.arg(skip)); .arg(skip));
} else if (take > 0) { } else if (take > 0) {
sql.append(QString(" LIMIT %1").arg(take)); sql.append(QStringLiteral(" LIMIT %1").arg(take));
} }
} }

View File

@ -22,11 +22,12 @@
#define MYSQLGENERATOR_H #define MYSQLGENERATOR_H
#include <QtCore/qglobal.h> #include <QtCore/qglobal.h>
#include "sqlgeneratorbase_p.h"
#include <QtNut/abstractsqlgenerator.h>
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
class NUT_EXPORT MySqlGenerator : public SqlGeneratorBase class NUT_EXPORT MySqlGenerator : public AbstractSqlGenerator
{ {
public: public:
explicit MySqlGenerator(Database *parent = nullptr); explicit MySqlGenerator(Database *parent = nullptr);

View File

@ -18,18 +18,19 @@
** **
**************************************************************************/ **************************************************************************/
#include <QDateTime> #include <QtCore/QDateTime>
#include <QPoint> #include <QtCore/QPoint>
#ifdef QT_GUI_LIB #ifdef QT_GUI_LIB
#include <QPolygon> # include <QtGui/QPolygon>
#include <QPolygonF> # include <QtGui/QPolygonF>
#endif #endif
#include <QVariant> #include <QtCore/QVariant>
#include <QJsonDocument> #include <QtCore/QJsonDocument>
#include "postgresqlgenerator.h" #include "postgresqlgenerator.h"
#include "../table.h" #include "table.h"
#include "../tablemodel.h" #include "tablemodel.h"
#include "sqlserializer.h" #include "sqlserializer.h"
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
@ -72,7 +73,7 @@ bool PostgreSqlGenerator::isPostGisType(const QVariant::Type &t) const
|| t == QVariant::PolygonF; || t == QVariant::PolygonF;
} }
PostgreSqlGenerator::PostgreSqlGenerator(Database *parent) : SqlGeneratorBase (parent) PostgreSqlGenerator::PostgreSqlGenerator(Database *parent) : AbstractSqlGenerator (parent)
{ {
} }
@ -83,44 +84,44 @@ QString PostgreSqlGenerator::fieldType(FieldModel *field)
switch (field->type) { switch (field->type) {
case QMetaType::Bool: case QMetaType::Bool:
dbType = "BOOLEAN"; dbType = QStringLiteral("BOOLEAN");
break; break;
case QMetaType::QBitArray: case QMetaType::QBitArray:
case QMetaType::QByteArray: case QMetaType::QByteArray:
dbType = "BYTEA"; dbType = QStringLiteral("BYTEA");
break; break;
case QMetaType::QDate: case QMetaType::QDate:
dbType = "DATE"; dbType = QStringLiteral("DATE");
break; break;
case QMetaType::QDateTime: case QMetaType::QDateTime:
dbType = "TIMESTAMP"; dbType = QStringLiteral("TIMESTAMP");
break; break;
case QMetaType::QTime: case QMetaType::QTime:
dbType = "TIME"; dbType = QStringLiteral("TIME");
break; break;
case QMetaType::SChar: case QMetaType::SChar:
case QMetaType::UChar: case QMetaType::UChar:
case QMetaType::Short: case QMetaType::Short:
case QMetaType::UShort: case QMetaType::UShort:
dbType = "SMALLINT"; dbType = QStringLiteral("SMALLINT");
break; break;
case QMetaType::Float: case QMetaType::Float:
dbType = "FLOAT"; dbType = QStringLiteral("FLOAT");
break; break;
case QMetaType::Double: case QMetaType::Double:
dbType = "REAL"; dbType = QStringLiteral("REAL");
break; break;
case QMetaType::Int: case QMetaType::Int:
case QMetaType::UInt: case QMetaType::UInt:
if(field->isAutoIncrement) if(field->isAutoIncrement)
dbType = "SERIAL"; dbType = QStringLiteral("SERIAL");
else else
dbType = "INTEGER"; dbType = QStringLiteral("INTEGER");
break; break;
case QMetaType::Long: case QMetaType::Long:
@ -128,58 +129,58 @@ QString PostgreSqlGenerator::fieldType(FieldModel *field)
case QMetaType::LongLong: case QMetaType::LongLong:
case QMetaType::ULongLong: case QMetaType::ULongLong:
if(field->isAutoIncrement) if(field->isAutoIncrement)
dbType = "BIGSERIAL"; dbType = QStringLiteral("BIGSERIAL");
else else
dbType = "BIGINT"; dbType = QStringLiteral("BIGINT");
break; break;
case QMetaType::Char: case QMetaType::Char:
case QMetaType::QChar: case QMetaType::QChar:
return "CHAR(1)"; return QStringLiteral("CHAR(1)");
case QMetaType::QString: case QMetaType::QString:
if(field->length) if(field->length)
dbType = QString("VARCHAR(%1)").arg(field->length); dbType = QStringLiteral("VARCHAR(%1)").arg(field->length);
else else
dbType = "TEXT"; dbType = QStringLiteral("TEXT");
break; break;
case QMetaType::QPoint: case QMetaType::QPoint:
case QMetaType::QPointF: case QMetaType::QPointF:
dbType="POINT"; dbType = QStringLiteral("POINT");
break; break;
case QMetaType::QUuid: case QMetaType::QUuid:
dbType = "UUID"; dbType = QStringLiteral("UUID");
break; break;
case QMetaType::QPolygon: case QMetaType::QPolygon:
case QMetaType::QPolygonF: case QMetaType::QPolygonF:
dbType = "POLYGON"; dbType = QStringLiteral("POLYGON");
break; break;
case QMetaType::QLine: case QMetaType::QLine:
case QMetaType::QLineF: case QMetaType::QLineF:
return "LINE"; return QStringLiteral("LINE");
case QMetaType::QRect: case QMetaType::QRect:
case QMetaType::QRectF: case QMetaType::QRectF:
return "BOX"; return QStringLiteral("BOX");
case QMetaType::QJsonArray: case QMetaType::QJsonArray:
case QMetaType::QJsonValue: case QMetaType::QJsonValue:
case QMetaType::QJsonObject: case QMetaType::QJsonObject:
case QMetaType::QJsonDocument: case QMetaType::QJsonDocument:
return "JSONB"; return QStringLiteral("JSONB");
case QMetaType::QStringList: case QMetaType::QStringList:
return "TEXT[]"; return QStringLiteral("TEXT[]");
case QMetaType::QSize: case QMetaType::QSize:
case QMetaType::QSizeF: case QMetaType::QSizeF:
case QMetaType::QUrl: case QMetaType::QUrl:
case QMetaType::QColor: case QMetaType::QColor:
return "TEXT"; return QStringLiteral("TEXT");
default: default:
dbType = QString(); dbType = QString();
@ -196,13 +197,13 @@ QString PostgreSqlGenerator::diff(FieldModel *oldField, FieldModel *newField)
return QString(); return QString();
if(!newField){ if(!newField){
sql = "DROP COLUMN " + oldField->name; sql = QStringLiteral("DROP COLUMN ") + oldField->name;
}else{ }else{
if(oldField){ if(oldField){
sql = "ALTER COLUMN "; sql = QStringLiteral("ALTER COLUMN ");
sql.append(newField->name + " TYPE " + fieldType(newField)); sql.append(newField->name + QStringLiteral(" TYPE ") + fieldType(newField));
} else { } else {
sql = "ADD COLUMN "; sql = QStringLiteral("ADD COLUMN ");
sql.append(fieldDeclare(newField)); sql.append(fieldDeclare(newField));
} }
} }
@ -212,27 +213,31 @@ QString PostgreSqlGenerator::diff(FieldModel *oldField, FieldModel *newField)
QString PostgreSqlGenerator::escapeValue(const QVariant &v) const QString PostgreSqlGenerator::escapeValue(const QVariant &v) const
{ {
if (v.type() == QVariant::Time) if (v.type() == QVariant::Time)
return "'" + v.toTime().toString("HH:mm:ss") + "'"; return v.toTime().toString(QStringLiteral("''HH:mm:ss''"));
if (v.type() == QVariant::Date) if (v.type() == QVariant::Date)
return "'" + v.toDate().toString("yyyy-MM-dd") + "'"; return v.toDate().toString(QStringLiteral("''yyyy-MM-dd''"));
if (v.type() == QVariant::DateTime) if (v.type() == QVariant::DateTime)
return "'" + v.toDateTime().toString("yyyy-MM-dd HH:mm:ss") + "'"; return v.toDateTime().toString(QStringLiteral("''yyyy-MM-dd HH:mm:ss''"));
if (v.type() == QVariant::StringList) if (v.type() == QVariant::StringList)
return "'{" + v.toStringList().join(",") + "}'"; return QStringLiteral("'{")
+ v.toStringList().join(QStringLiteral(","))
+ QStringLiteral("}'");
if (v.type() == QVariant::Point) { if (v.type() == QVariant::Point) {
QPoint pt = v.toPoint(); QPoint pt = v.toPoint();
return QString("point(%1, %2)").arg(pt.x()).arg(pt.y()); return QStringLiteral("point(%1, %2)").arg(pt.x()).arg(pt.y());
} }
if (v.type() == QVariant::PointF) { if (v.type() == QVariant::PointF) {
QPointF pt = v.toPointF(); QPointF pt = v.toPointF();
return QString("point(%1, %2)").arg(pt.x()).arg(pt.y()); return QStringLiteral("point(%1, %2)").arg(pt.x()).arg(pt.y());
} }
if (v.userType() == QMetaType::QJsonDocument) { if (v.userType() == QMetaType::QJsonDocument) {
return "'" + QString(v.toJsonDocument().toJson(QJsonDocument::Compact)) + "'"; return QStringLiteral("'")
+ QString::fromUtf8(v.toJsonDocument().toJson(QJsonDocument::Compact))
+ QStringLiteral("'");
} }
#ifdef QT_GUI_LIB #ifdef QT_GUI_LIB
@ -243,10 +248,11 @@ QString PostgreSqlGenerator::escapeValue(const QVariant &v) const
for (int i = 0; i < pol.size(); ++i) { for (int i = 0; i < pol.size(); ++i) {
pt = pol.at(i); pt = pol.at(i);
if (!ret.isEmpty()) if (!ret.isEmpty())
ret.append("),("); ret.append(QStringLiteral("),("));
ret.append(QString::number(pt.x()) + ", " + QString::number(pt.y())); ret.append(QString::number(pt.x())
+ QStringLiteral(", ") + QString::number(pt.y()));
} }
return "'((" + ret + "))'"; return QStringLiteral("'((") + ret + QStringLiteral("))'");
} }
if (v.type() == QVariant::PolygonF) { if (v.type() == QVariant::PolygonF) {
QString ret; QString ret;
@ -255,14 +261,15 @@ QString PostgreSqlGenerator::escapeValue(const QVariant &v) const
for (int i = 0; i < pol.size(); ++i) { for (int i = 0; i < pol.size(); ++i) {
pt = pol.at(i); pt = pol.at(i);
if (!ret.isEmpty()) if (!ret.isEmpty())
ret.append("),("); ret.append(QStringLiteral("),("));
ret.append(QString::number(pt.x()) + ", " + QString::number(pt.y())); ret.append(QString::number(pt.x())
+ QStringLiteral(", ") + QString::number(pt.y()));
} }
return "'((" + ret + "))'"; return QStringLiteral("'((") + ret + QStringLiteral("))'");
} }
#endif #endif
return SqlGeneratorBase::escapeValue(v); return AbstractSqlGenerator::escapeValue(v);
} }
QVariant PostgreSqlGenerator::unescapeValue(const QMetaType::Type &type, const QVariant &dbValue) QVariant PostgreSqlGenerator::unescapeValue(const QMetaType::Type &type, const QVariant &dbValue)
@ -277,14 +284,24 @@ QVariant PostgreSqlGenerator::unescapeValue(const QMetaType::Type &type, const Q
return dbValue.toDate(); return dbValue.toDate();
if (type == QMetaType::QPoint) if (type == QMetaType::QPoint)
return SqlGeneratorBase::unescapeValue(QMetaType::QPoint, dbValue.toString() return AbstractSqlGenerator::unescapeValue(QMetaType::QPoint,
.replace("(", "").replace(")", "")); dbValue.toString()
.replace(QStringLiteral("("),
QStringLiteral(""))
.replace(QStringLiteral(")"),
QStringLiteral("")));
if (type == QMetaType::QPointF) if (type == QMetaType::QPointF)
return SqlGeneratorBase::unescapeValue(QMetaType::QPointF, dbValue.toString() return AbstractSqlGenerator::unescapeValue(QMetaType::QPointF,
.replace("(", "").replace(")", "")); dbValue.toString()
.replace(QStringLiteral("("),
QStringLiteral(""))
.replace(QStringLiteral(")"),
QStringLiteral("")));
if (type == QMetaType::QStringList) if (type == QMetaType::QStringList)
return dbValue.toString().replace("{", "").replace("}", "") return dbValue.toString()
.split(","); .replace(QStringLiteral("{"), QStringLiteral(""))
.replace(QStringLiteral("}"), QStringLiteral(""))
.split(QStringLiteral(","));
#ifdef QT_GUI_LIB #ifdef QT_GUI_LIB
if (type == QMetaType::QPolygon) { if (type == QMetaType::QPolygon) {
@ -320,7 +337,7 @@ QVariant PostgreSqlGenerator::unescapeValue(const QMetaType::Type &type, const Q
return pol; return pol;
} }
#endif #endif
return SqlGeneratorBase::unescapeValue(type, dbValue); return AbstractSqlGenerator::unescapeValue(type, dbValue);
} }
QString PostgreSqlGenerator::createConditionalPhrase(const PhraseData *d) const QString PostgreSqlGenerator::createConditionalPhrase(const PhraseData *d) const
@ -337,8 +354,8 @@ QString PostgreSqlGenerator::createConditionalPhrase(const PhraseData *d) const
if (d->type == PhraseData::WithVariant) { if (d->type == PhraseData::WithVariant) {
if (isPostGisType(d->operand.type()) && d->operatorCond == PhraseData::Equal) { if (isPostGisType(d->operand.type()) && d->operatorCond == PhraseData::Equal) {
return QString("%1 ~= %2") return QStringLiteral("%1 ~= %2")
.arg(SqlGeneratorBase::createConditionalPhrase(d->left), .arg(AbstractSqlGenerator::createConditionalPhrase(d->left),
escapeValue(d->operand)); escapeValue(d->operand));
} }
switch (op) { switch (op) {
@ -354,10 +371,10 @@ QString PostgreSqlGenerator::createConditionalPhrase(const PhraseData *d) const
case PhraseData::AddMinutesDateTime: case PhraseData::AddMinutesDateTime:
case PhraseData::AddSeconds: case PhraseData::AddSeconds:
case PhraseData::AddSecondsDateTime: case PhraseData::AddSecondsDateTime:
return QString("%1 + interval '%2 %3'") return QStringLiteral("%1 + interval '%2 %3'")
.arg(createConditionalPhrase(d->left), .arg(createConditionalPhrase(d->left),
d->operand.toString(), d->operand.toString(),
SqlGeneratorBase::dateTimePartName(op)); AbstractSqlGenerator::dateTimePartName(op));
default: default:
break; break;
@ -372,16 +389,16 @@ QString PostgreSqlGenerator::createConditionalPhrase(const PhraseData *d) const
case PhraseData::DatePartHour: case PhraseData::DatePartHour:
case PhraseData::DatePartMinute: case PhraseData::DatePartMinute:
case PhraseData::DatePartSecond: case PhraseData::DatePartSecond:
return QString("date_part('%2', %1)") return QStringLiteral("date_part('%2', %1)")
.arg(createConditionalPhrase(d->left), .arg(createConditionalPhrase(d->left),
SqlGeneratorBase::dateTimePartName(op)); AbstractSqlGenerator::dateTimePartName(op));
default: default:
break; break;
} }
} }
return SqlGeneratorBase::createConditionalPhrase(d); return AbstractSqlGenerator::createConditionalPhrase(d);
} }
NUT_END_NAMESPACE NUT_END_NAMESPACE

View File

@ -22,11 +22,12 @@
#define POSTGRESQLGENERATOR_H #define POSTGRESQLGENERATOR_H
#include <QtCore/qglobal.h> #include <QtCore/qglobal.h>
#include "sqlgeneratorbase_p.h"
#include <QtNut/abstractsqlgenerator.h>
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
class NUT_EXPORT PostgreSqlGenerator : public SqlGeneratorBase class NUT_EXPORT PostgreSqlGenerator : public AbstractSqlGenerator
{ {
private: private:
bool readInsideParentese(QString &text, QString &out); bool readInsideParentese(QString &text, QString &out);

View File

@ -19,12 +19,12 @@
**************************************************************************/ **************************************************************************/
#include "sqlitegenerator.h" #include "sqlitegenerator.h"
#include "../table.h" #include "table.h"
#include "../tablemodel.h" #include "tablemodel.h"
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
SqliteGenerator::SqliteGenerator(Database *parent) : SqlGeneratorBase(parent) SqliteGenerator::SqliteGenerator(Database *parent) : AbstractSqlGenerator(parent)
{ {
} }
@ -32,28 +32,28 @@ SqliteGenerator::SqliteGenerator(Database *parent) : SqlGeneratorBase(parent)
QString SqliteGenerator::fieldType(FieldModel *field) QString SqliteGenerator::fieldType(FieldModel *field)
{ {
switch (field->type) { switch (field->type) {
case QMetaType::Bool: return "BOOLEAN"; case QMetaType::Bool: return QStringLiteral("BOOLEAN");
case QMetaType::QBitArray: case QMetaType::QBitArray:
case QMetaType::QByteArray: return "BLOB"; case QMetaType::QByteArray: return QStringLiteral("BLOB");
case QMetaType::QDate: return "DATE"; case QMetaType::QDate: return QStringLiteral("DATE");
case QMetaType::QDateTime: return "DATETIME"; case QMetaType::QDateTime: return QStringLiteral("DATETIME");
case QMetaType::QTime: return "TIME"; case QMetaType::QTime: return QStringLiteral("TIME");
case QMetaType::Double: return "DOUBLE"; case QMetaType::Double: return QStringLiteral("DOUBLE");
case QMetaType::Float: return "FLOAT"; case QMetaType::Float: return QStringLiteral("FLOAT");
case QMetaType::SChar: case QMetaType::SChar:
case QMetaType::Char: return "TINYINT"; case QMetaType::Char: return QStringLiteral("TINYINT");
case QMetaType::UChar: return "TINYINT UNSIGNED"; case QMetaType::UChar: return QStringLiteral("TINYINT UNSIGNED");
case QMetaType::Short: return "SMALLINT"; case QMetaType::Short: return QStringLiteral("SMALLINT");
case QMetaType::UShort: return "SMALLINT UNSIGNED"; case QMetaType::UShort: return QStringLiteral("SMALLINT UNSIGNED");
case QMetaType::Int: return "INT"; case QMetaType::Int: return QStringLiteral("INT");
case QMetaType::UInt: return "INT UNSIGNED"; case QMetaType::UInt: return QStringLiteral("INT UNSIGNED");
case QMetaType::Long: return "MEDIUMINT"; case QMetaType::Long: return QStringLiteral("MEDIUMINT");
case QMetaType::ULong: return "MEDIUMINT UNSIGNED"; case QMetaType::ULong: return QStringLiteral("MEDIUMINT UNSIGNED");
case QMetaType::LongLong: return "BIGINT"; case QMetaType::LongLong: return QStringLiteral("BIGINT");
case QMetaType::ULongLong: return "BIGINT UNSIGNED"; case QMetaType::ULongLong: return QStringLiteral("BIGINT UNSIGNED");
case QMetaType::QChar: return "NCHAR(1)"; case QMetaType::QChar: return QStringLiteral("NCHAR(1)");
case QMetaType::QUrl: case QMetaType::QUrl:
case QMetaType::QJsonArray: case QMetaType::QJsonArray:
@ -72,16 +72,16 @@ QString SqliteGenerator::fieldType(FieldModel *field)
case QMetaType::QPolygonF: case QMetaType::QPolygonF:
case QMetaType::QStringList: case QMetaType::QStringList:
case QMetaType::QColor: case QMetaType::QColor:
case QMetaType::QUuid: return "TEXT"; case QMetaType::QUuid: return QStringLiteral("TEXT");
// if (field->isAutoIncrement) // if (field->isAutoIncrement)
// dbType.append(" PRIMARY KEY AUTOINCREMENT"); // dbType.append(" PRIMARY KEY AUTOINCREMENT");
case QMetaType::QString: case QMetaType::QString:
if(field->length) if(field->length)
return QString("VARCHAR(%1)").arg(field->length); return QStringLiteral("VARCHAR(%1)").arg(field->length);
else else
return "TEXT"; return QStringLiteral("TEXT");
default: default:
// qWarning("The type (%s) does not supported", // qWarning("The type (%s) does not supported",
// QMetaType::typeName(field->type)); // QMetaType::typeName(field->type));
@ -96,18 +96,18 @@ QString SqliteGenerator::fieldDeclare(FieldModel *field)
return type; return type;
if (isNumeric(field->type) && field->isPrimaryKey) { if (isNumeric(field->type) && field->isPrimaryKey) {
type = "INTEGER PRIMARY KEY"; type = QStringLiteral("INTEGER PRIMARY KEY");
if (field->isAutoIncrement) if (field->isAutoIncrement)
type.append(" AUTOINCREMENT"); type.append(QStringLiteral(" AUTOINCREMENT"));
} }
if (field->notNull) if (field->notNull)
type.append(" NOT NULL"); type.append(QStringLiteral(" NOT NULL"));
if (field->isUnique) if (field->isUnique)
type.append(" UNIQUE"); type.append(QStringLiteral(" UNIQUE"));
return field->name + " " + type; return field->name + QStringLiteral(" ") + type;
} }
bool SqliteGenerator::supportAutoIncrement(const QMetaType::Type &type) bool SqliteGenerator::supportAutoIncrement(const QMetaType::Type &type)
@ -124,10 +124,10 @@ QStringList SqliteGenerator::diff(TableModel *oldTable, TableModel *newTable)
if (*oldTable == *newTable) if (*oldTable == *newTable)
return ret; return ret;
QStringList newTableSql = SqlGeneratorBase::diff(nullptr, newTable); QStringList newTableSql = AbstractSqlGenerator::diff(nullptr, newTable);
if (!newTable) if (!newTable)
return QStringList() << "DROP TABLE " + oldTable->name(); return QStringList() << QStringLiteral("DROP TABLE ") + oldTable->name();
if (!oldTable) if (!oldTable)
return newTableSql; return newTableSql;
@ -135,27 +135,27 @@ QStringList SqliteGenerator::diff(TableModel *oldTable, TableModel *newTable)
QList<QString> fieldNames; QList<QString> fieldNames;
QList<QString> relations; QList<QString> relations;
foreach (FieldModel *f, oldTable->fields()) Q_FOREACH (FieldModel *f, oldTable->fields())
if (!fieldNames.contains(f->name)) if (!fieldNames.contains(f->name))
fieldNames.append(f->name); fieldNames.append(f->name);
foreach (RelationModel *r, oldTable->foreignKeys()) Q_FOREACH (RelationModel *r, oldTable->foreignKeys())
if (!relations.contains(r->localColumn)) if (!relations.contains(r->localColumn))
relations.append(r->localColumn); relations.append(r->localColumn);
foreach (FieldModel *f, newTable->fields()) Q_FOREACH (FieldModel *f, newTable->fields())
if (!fieldNames.contains(f->name)) if (!fieldNames.contains(f->name))
fieldNames.append(f->name); fieldNames.append(f->name);
foreach (RelationModel *r, newTable->foreignKeys()) Q_FOREACH (RelationModel *r, newTable->foreignKeys())
if (!relations.contains(r->localColumn)) if (!relations.contains(r->localColumn))
relations.append(r->localColumn); relations.append(r->localColumn);
QString columns; QString columns;
foreach (FieldModel *f, oldTable->fields()) { Q_FOREACH (FieldModel *f, oldTable->fields()) {
if (!newTable->field(f->name)) if (!newTable->field(f->name))
continue; continue;
if (!columns.isEmpty()) if (!columns.isEmpty())
columns.append(", "); columns.append(QStringLiteral(", "));
columns.append(f->name); columns.append(f->name);
} }
@ -176,26 +176,33 @@ QStringList SqliteGenerator::diff(TableModel *oldTable, TableModel *newTable)
SELECT id, SELECT id,
t, t,
m m
FROM sqlitestudio_temp_table; FROM nut_orm_temp_table;
DROP TABLE sqlitestudio_temp_table; DROP TABLE sqlitestudio_temp_table;
*/ */
ret.append("ALTER TABLE " + newTable->name() + " RENAME TO sqlitestudio_temp_table;"); QString foreignKeys;
for (auto &f: newTable->foreignKeys()) {
if (!foreignKeys.isEmpty())
foreignKeys.append(QStringLiteral(", "));
foreignKeys.append(QStringLiteral("FOREIGN KEY(%1) REFERENCES %2(id)")
.arg(f->localColumn, f->masterTable->name()));
}
ret.append(QStringLiteral("ALTER TABLE ") + newTable->name() + QStringLiteral(" RENAME TO nut_orm_temp_table;"));
ret.append(newTableSql); ret.append(newTableSql);
ret.append(QString("INSERT INTO %1 ( %2 ) SELECT %2 FROM sqlitestudio_temp_table;") ret.append(QStringLiteral("INSERT INTO %1 ( %2 ) SELECT %2 FROM nut_orm_temp_table;")
.arg(newTable->name(), columns)); .arg(newTable->name(), columns));
ret.append("DROP TABLE sqlitestudio_temp_table;"); ret.append(QStringLiteral("DROP TABLE nut_orm_temp_table;"));
return ret; return ret;
} }
void SqliteGenerator::appendSkipTake(QString &sql, int skip, int take) void SqliteGenerator::appendSkipTake(QString &sql, int skip, int take)
{ {
if (take > 0 && skip > 0) { if (take > 0 && skip > 0) {
sql.append(QString(" LIMIT %1 OFFSET %2") sql.append(QStringLiteral(" LIMIT %1 OFFSET %2")
.arg(take) .arg(take)
.arg(skip)); .arg(skip));
} else if (take > 0) { } else if (take > 0) {
sql.append(QString(" LIMIT %1").arg(take)); sql.append(QStringLiteral(" LIMIT %1").arg(take));
} }
} }
@ -229,20 +236,20 @@ QString SqliteGenerator::createConditionalPhrase(const PhraseData *d) const
case PhraseData::AddMonths: case PhraseData::AddMonths:
case PhraseData::AddDays: { case PhraseData::AddDays: {
int i = d->operand.toInt(); int i = d->operand.toInt();
return QString("DATE(%1,'%2 %3')") return QStringLiteral("DATE(%1,'%2 %3')")
.arg(createConditionalPhrase(d->left), .arg(createConditionalPhrase(d->left),
(i < 0 ? "" : "+") + QString::number(i), (i < 0 ? QStringLiteral("") : QStringLiteral("+")) + QString::number(i),
dateTimePartName(op)); dateTimePartName(op));
break; break;
} }
case PhraseData::AddHours: case PhraseData::AddHours:
case PhraseData::AddMinutes: case PhraseData::AddMinutes:
case PhraseData::AddSeconds: { case PhraseData::AddSeconds: {
int i = d->operand.toInt(); int i = d->operand.toInt();
return QString("TIME(%1,'%2 %3')") return QStringLiteral("TIME(%1,'%2 %3')")
.arg(createConditionalPhrase(d->left), .arg(createConditionalPhrase(d->left),
(i < 0 ? "" : "+") + QString::number(i), (i < 0 ? QStringLiteral("") : QStringLiteral("+")) + QString::number(i),
dateTimePartName(op)); dateTimePartName(op));
break; break;
} }
case PhraseData::AddYearsDateTime: case PhraseData::AddYearsDateTime:
@ -252,9 +259,9 @@ QString SqliteGenerator::createConditionalPhrase(const PhraseData *d) const
case PhraseData::AddMinutesDateTime: case PhraseData::AddMinutesDateTime:
case PhraseData::AddSecondsDateTime: { case PhraseData::AddSecondsDateTime: {
int i = d->operand.toInt(); int i = d->operand.toInt();
return QString("DATETIME(%1,'%2 %3')") return QStringLiteral("DATETIME(%1,'%2 %3')")
.arg(createConditionalPhrase(d->left), .arg(createConditionalPhrase(d->left),
(i < 0 ? "" : "+") + QString::number(i), (i < 0 ? QStringLiteral("") : QStringLiteral("+")) + QString::number(i),
dateTimePartName(op)); dateTimePartName(op));
break; break;
} }
@ -265,27 +272,27 @@ QString SqliteGenerator::createConditionalPhrase(const PhraseData *d) const
if (d->type == PhraseData::WithoutOperand) { if (d->type == PhraseData::WithoutOperand) {
switch (op) { switch (op) {
case PhraseData::DatePartYear: case PhraseData::DatePartYear:
return QString("CAST(strftime('%Y', %1) AS INT)") return QStringLiteral("CAST(strftime('%Y', %1) AS INT)")
.arg(createConditionalPhrase(d->left)); .arg(createConditionalPhrase(d->left));
case PhraseData::DatePartMonth: case PhraseData::DatePartMonth:
return QString("CAST(strftime('%m', %1) AS INT)") return QStringLiteral("CAST(strftime('%m', %1) AS INT)")
.arg(createConditionalPhrase(d->left)); .arg(createConditionalPhrase(d->left));
case PhraseData::DatePartDay: case PhraseData::DatePartDay:
return QString("CAST(strftime('%d', %1) AS INT)") return QStringLiteral("CAST(strftime('%d', %1) AS INT)")
.arg(createConditionalPhrase(d->left)); .arg(createConditionalPhrase(d->left));
case PhraseData::DatePartHour: case PhraseData::DatePartHour:
return QString("CAST(strftime('%H', %1) AS INT)") return QStringLiteral("CAST(strftime('%H', %1) AS INT)")
.arg(createConditionalPhrase(d->left)); .arg(createConditionalPhrase(d->left));
case PhraseData::DatePartMinute: case PhraseData::DatePartMinute:
return QString("CAST(strftime('%M', %1) AS INT)") return QStringLiteral("CAST(strftime('%M', %1) AS INT)")
.arg(createConditionalPhrase(d->left)); .arg(createConditionalPhrase(d->left));
case PhraseData::DatePartSecond: case PhraseData::DatePartSecond:
return QString("CAST(strftime('%S', %1) AS INT)") return QStringLiteral("CAST(strftime('%S', %1) AS INT)")
.arg(createConditionalPhrase(d->left)); .arg(createConditionalPhrase(d->left));
// case PhraseData::DatePartMilisecond: // case PhraseData::DatePartMilisecond:
@ -296,21 +303,21 @@ QString SqliteGenerator::createConditionalPhrase(const PhraseData *d) const
} }
} }
return SqlGeneratorBase::createConditionalPhrase(d); return AbstractSqlGenerator::createConditionalPhrase(d);
} }
QString SqliteGenerator::escapeValue(const QVariant &v) const QString SqliteGenerator::escapeValue(const QVariant &v) const
{ {
if (v.type() == QVariant::Time) if (v.type() == QVariant::Time)
return "'" + v.toTime().toString("HH:mm:ss") + "'"; return v.toTime().toString(QStringLiteral("''HH:mm:ss''"));
if (v.type() == QVariant::Date) if (v.type() == QVariant::Date)
return "'" + v.toDate().toString("yyyy-MM-dd") + "'"; return v.toDate().toString(QStringLiteral("''yyyy-MM-dd''"));
if (v.type() == QVariant::DateTime) if (v.type() == QVariant::DateTime)
return "'" + v.toDateTime().toString("yyyy-MM-dd HH:mm:ss") + "'"; return v.toDateTime().toString(QStringLiteral("''yyyy-MM-dd HH:mm:ss''"));
return SqlGeneratorBase::escapeValue(v); return AbstractSqlGenerator::escapeValue(v);
} }
QVariant SqliteGenerator::unescapeValue(const QMetaType::Type &type, const QVariant &dbValue) QVariant SqliteGenerator::unescapeValue(const QMetaType::Type &type, const QVariant &dbValue)
@ -324,7 +331,7 @@ QVariant SqliteGenerator::unescapeValue(const QMetaType::Type &type, const QVari
if (type == QMetaType::QDate) if (type == QMetaType::QDate)
return dbValue.toDate(); return dbValue.toDate();
return SqlGeneratorBase::unescapeValue(type, dbValue); return AbstractSqlGenerator::unescapeValue(type, dbValue);
} }
NUT_END_NAMESPACE NUT_END_NAMESPACE

View File

@ -22,11 +22,12 @@
#define SQLITEGENERATOR_H #define SQLITEGENERATOR_H
#include <QtCore/qglobal.h> #include <QtCore/qglobal.h>
#include "sqlgeneratorbase_p.h"
#include <QtNut/abstractsqlgenerator.h>
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
class NUT_EXPORT SqliteGenerator : public SqlGeneratorBase class NUT_EXPORT SqliteGenerator : public AbstractSqlGenerator
{ {
public: public:
explicit SqliteGenerator(Database *parent = nullptr); explicit SqliteGenerator(Database *parent = nullptr);

View File

@ -19,102 +19,93 @@
**************************************************************************/ **************************************************************************/
#include "sqlservergenerator.h" #include "sqlservergenerator.h"
#include "../table.h" #include "table.h"
#include "../tablemodel.h" #include "tablemodel.h"
#include <QPoint> #include <QtCore/QPoint>
#include <QRegularExpression> #include <QtCore/QRegularExpression>
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
SqlServerGenerator::SqlServerGenerator(Database *parent) SqlServerGenerator::SqlServerGenerator(Database *parent)
: SqlGeneratorBase(parent) : AbstractSqlGenerator(parent)
{ {
} }
QString SqlServerGenerator::masterDatabaseName(QString databaseName) QString SqlServerGenerator::masterDatabaseName(QString databaseName)
{ {
return databaseName.replace( return databaseName.replace(
QRegularExpression("DATABASE\\=(\\w+)", QRegularExpression(QStringLiteral("DATABASE\\=(\\w+)"),
QRegularExpression::CaseInsensitiveOption), QRegularExpression::CaseInsensitiveOption),
"DATABASE="); QStringLiteral("DATABASE="));
} }
QString SqlServerGenerator::fieldType(FieldModel *field) QString SqlServerGenerator::fieldType(FieldModel *field)
{ {
QString dbType;
switch (field->type) { switch (field->type) {
case QMetaType::Bool: case QMetaType::Bool:
dbType = "BIT"; return QStringLiteral("BIT");
break;
case QMetaType::Char: case QMetaType::Char:
case QMetaType::QChar: case QMetaType::QChar:
dbType = "CHAR(1)"; return QStringLiteral("CHAR(1)");
break;
case QMetaType::SChar: case QMetaType::SChar:
case QMetaType::UChar: case QMetaType::UChar:
return "tinyint"; return QStringLiteral("tinyint");
case QMetaType::Short: case QMetaType::Short:
case QMetaType::UShort: case QMetaType::UShort:
return "smallint"; return QStringLiteral("smallint");
case QMetaType::UInt: case QMetaType::UInt:
case QMetaType::Int: case QMetaType::Int:
dbType = "INT";
if (field->isAutoIncrement) if (field->isAutoIncrement)
dbType += " IDENTITY(1,1)"; return QStringLiteral("INT IDENTITY(1,1)");
break; else
return QStringLiteral("INT");
case QMetaType::Long: case QMetaType::Long:
case QMetaType::ULong: case QMetaType::ULong:
case QMetaType::LongLong: case QMetaType::LongLong:
case QMetaType::ULongLong: case QMetaType::ULongLong:
return "bigint"; return QStringLiteral("bigint");
case QMetaType::Float: case QMetaType::Float:
return "FLOAT(24)"; return QStringLiteral("FLOAT(24)");
case QMetaType::Double: case QMetaType::Double:
return "REAL"; return QStringLiteral("REAL");
case QMetaType::QBitArray: case QMetaType::QBitArray:
case QMetaType::QByteArray: case QMetaType::QByteArray:
dbType = "VARBINARY";
if (field->length) if (field->length)
dbType.append(" (" + QString::number(field->length) + ")"); return QStringLiteral("VARBINARY (") + QString::number(field->length) + QStringLiteral(")");
else else
dbType.append(" (MAX)"); return QStringLiteral("VARBINARY (MAX)");
break; break;
case QMetaType::QDate: case QMetaType::QDate:
dbType = "DATE"; return QStringLiteral("DATE");
break;
case QMetaType::QDateTime: case QMetaType::QDateTime:
dbType = "DATETIME"; return QStringLiteral("DATETIME");
break;
case QMetaType::QTime: case QMetaType::QTime:
dbType = "TIME"; return QStringLiteral("TIME");
break;
case QMetaType::QPoint: case QMetaType::QPoint:
case QMetaType::QPointF: case QMetaType::QPointF:
dbType = "TEXT"; return QStringLiteral("TEXT");
break;
case QMetaType::QString: case QMetaType::QString:
if (field->length) if (field->length)
dbType = QString("NVARCHAR(%1)").arg(field->length); return QStringLiteral("NVARCHAR(%1)").arg(field->length);
else else
dbType = "NVARCHAR(MAX)"; return QStringLiteral("NVARCHAR(MAX)");
break;
case QMetaType::QUuid: case QMetaType::QUuid:
dbType = "UNIQUEIDENTIFIER"; return QStringLiteral("UNIQUEIDENTIFIER");
break;
case QMetaType::QPolygon: case QMetaType::QPolygon:
case QMetaType::QPolygonF: case QMetaType::QPolygonF:
@ -131,14 +122,12 @@ QString SqlServerGenerator::fieldType(FieldModel *field)
case QMetaType::QJsonObject: case QMetaType::QJsonObject:
case QMetaType::QJsonDocument: case QMetaType::QJsonDocument:
case QMetaType::QUrl: case QMetaType::QUrl:
return "TEXT"; return QStringLiteral("TEXT");
default: default:
// Q_UNREACHABLE(); // Q_UNREACHABLE();
dbType = QString(); return QString();
} }
return dbType;
} }
QString SqlServerGenerator::diff(FieldModel *oldField, FieldModel *newField) QString SqlServerGenerator::diff(FieldModel *oldField, FieldModel *newField)
@ -149,12 +138,12 @@ QString SqlServerGenerator::diff(FieldModel *oldField, FieldModel *newField)
return sql; return sql;
if (!newField) { if (!newField) {
sql = "DROP COLUMN " + oldField->name; sql = QStringLiteral("DROP COLUMN ") + oldField->name;
} else { } else {
if (oldField) if (oldField)
sql = "MODIFY COLUMN "; sql = QStringLiteral("MODIFY COLUMN ");
else else
sql = "ADD "; sql = QStringLiteral("ADD ");
sql.append(fieldDeclare(newField)); sql.append(fieldDeclare(newField));
} }
@ -181,7 +170,7 @@ QString SqlServerGenerator::escapeValue(const QVariant &v) const
// case QVariant::JsonObject: // case QVariant::JsonObject:
// case QVariant::JsonDocument: // case QVariant::JsonDocument:
case QVariant::Url: case QVariant::Url:
return "N" + SqlGeneratorBase::escapeValue(v); return QStringLiteral("N") + AbstractSqlGenerator::escapeValue(v);
// case QVariant::Point: { // case QVariant::Point: {
// QPoint pt = v.toPoint(); // QPoint pt = v.toPoint();
@ -195,18 +184,17 @@ QString SqlServerGenerator::escapeValue(const QVariant &v) const
// } // }
case QVariant::Time: case QVariant::Time:
return "'" + v.toTime().toString("HH:mm:ss") + "'"; return v.toTime().toString(QStringLiteral("''HH:mm:ss''"));
case QVariant::Date: case QVariant::Date:
return "'" + v.toDate().toString("yyyy-MM-dd") + "'"; return v.toDate().toString(QStringLiteral("''yyyy-MM-dd''"));
case QVariant::DateTime: case QVariant::DateTime:
return "'" + v.toDateTime().toString("yyyy-MM-dd HH:mm:ss") + "'"; return v.toDateTime().toString(QStringLiteral("''yyyy-MM-dd HH:mm:ss''"));
default: default:
break; return AbstractSqlGenerator::escapeValue(v);
} }
return SqlGeneratorBase::escapeValue(v);
} }
QVariant SqlServerGenerator::unescapeValue(const QMetaType::Type &type, const QVariant &dbValue) QVariant SqlServerGenerator::unescapeValue(const QMetaType::Type &type, const QVariant &dbValue)
@ -220,18 +208,18 @@ QVariant SqlServerGenerator::unescapeValue(const QMetaType::Type &type, const QV
if (type == QMetaType::QDate) if (type == QMetaType::QDate)
return dbValue.toDate(); return dbValue.toDate();
return SqlGeneratorBase::unescapeValue(type, dbValue); return AbstractSqlGenerator::unescapeValue(type, dbValue);
} }
void SqlServerGenerator::appendSkipTake(QString &sql, int skip, int take) void SqlServerGenerator::appendSkipTake(QString &sql, int skip, int take)
{ {
if (skip != -1) if (skip != -1)
sql.append(QString(" OFFSET %1 ROWS") sql.append(QStringLiteral(" OFFSET %1 ROWS")
.arg(skip)); .arg(skip));
if (take > 0) if (take > 0)
sql.append(QString(" FETCH %2 %1 ROWS ONLY") sql.append(QStringLiteral(" FETCH %2 %1 ROWS ONLY")
.arg(take) .arg(take)
.arg(skip > 1 ? "NEXT" : "FIRST")); .arg(skip > 1 ? QStringLiteral("NEXT") : QStringLiteral("FIRST")));
} }
QString SqlServerGenerator::createConditionalPhrase(const PhraseData *d) const QString SqlServerGenerator::createConditionalPhrase(const PhraseData *d) const
@ -260,10 +248,10 @@ QString SqlServerGenerator::createConditionalPhrase(const PhraseData *d) const
case PhraseData::AddMinutesDateTime: case PhraseData::AddMinutesDateTime:
case PhraseData::AddSeconds: case PhraseData::AddSeconds:
case PhraseData::AddSecondsDateTime: case PhraseData::AddSecondsDateTime:
return QString("DATEADD(%3, %2, %1)") return QStringLiteral("DATEADD(%3, %2, %1)")
.arg(createConditionalPhrase(d->left), .arg(createConditionalPhrase(d->left),
d->operand.toString(), d->operand.toString(),
SqlGeneratorBase::dateTimePartName(op)); AbstractSqlGenerator::dateTimePartName(op));
default: default:
break; break;
@ -278,16 +266,16 @@ QString SqlServerGenerator::createConditionalPhrase(const PhraseData *d) const
case PhraseData::DatePartHour: case PhraseData::DatePartHour:
case PhraseData::DatePartMinute: case PhraseData::DatePartMinute:
case PhraseData::DatePartSecond: case PhraseData::DatePartSecond:
return QString("DATEPART(%2, %1)") return QStringLiteral("DATEPART(%2, %1)")
.arg(createConditionalPhrase(d->left), .arg(createConditionalPhrase(d->left),
SqlGeneratorBase::dateTimePartName(op)); AbstractSqlGenerator::dateTimePartName(op));
default: default:
break; break;
} }
} }
return SqlGeneratorBase::createConditionalPhrase(d); return AbstractSqlGenerator::createConditionalPhrase(d);
} }
NUT_END_NAMESPACE NUT_END_NAMESPACE

View File

@ -22,11 +22,12 @@
#define SQLSERVERGENERATOR_H #define SQLSERVERGENERATOR_H
#include <QtCore/qglobal.h> #include <QtCore/qglobal.h>
#include "sqlgeneratorbase_p.h"
#include <QtNut/abstractsqlgenerator.h>
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
class NUT_EXPORT SqlServerGenerator : public SqlGeneratorBase class NUT_EXPORT SqlServerGenerator : public AbstractSqlGenerator
{ {
public: public:
explicit SqlServerGenerator(Database *parent = nullptr); explicit SqlServerGenerator(Database *parent = nullptr);

View File

@ -21,15 +21,15 @@
#include "databasemodel.h" #include "databasemodel.h"
#include "tablemodel.h" #include "tablemodel.h"
#include <QJsonArray> #include <QtCore/QJsonArray>
#include <QJsonObject> #include <QtCore/QJsonObject>
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
QMap<QString, DatabaseModel*> DatabaseModel::_models; QMap<QString, DatabaseModel*> DatabaseModel::_models;
#define NODE_VERSION "version" #define NODE_VERSION QStringLiteral("version")
#define NODE_TABLES "tables" #define NODE_TABLES QStringLiteral("tables")
DatabaseModel::DatabaseModel(const QString &name) : DatabaseModel::DatabaseModel(const QString &name) :
QList<TableModel*>(), _databaseClassName(name), _version(0) QList<TableModel*>(), _databaseClassName(name), _version(0)
{ {
@ -48,7 +48,7 @@ DatabaseModel::DatabaseModel(const QJsonObject &json) :
setVersion(json.value(NODE_VERSION).toInt()); setVersion(json.value(NODE_VERSION).toInt());
QJsonObject tables = json.value(NODE_TABLES).toObject(); QJsonObject tables = json.value(NODE_TABLES).toObject();
foreach (QString key, tables.keys()) { Q_FOREACH (QString key, tables.keys()) {
if(!tables.value(key).isObject()) if(!tables.value(key).isObject())
continue; continue;
@ -146,7 +146,7 @@ RelationModel *DatabaseModel::relationByClassNames(const QString &masterClassNam
if(!childTable) if(!childTable)
return nullptr; return nullptr;
foreach (RelationModel *rel, childTable->foreignKeys()) Q_FOREACH (RelationModel *rel, childTable->foreignKeys())
if(rel->masterClassName == masterClassName) if(rel->masterClassName == masterClassName)
return rel; return rel;
@ -160,7 +160,7 @@ RelationModel *DatabaseModel::relationByTableNames(const QString &masterTableNam
if(!childTable) if(!childTable)
return nullptr; return nullptr;
foreach (RelationModel *rel, childTable->foreignKeys()) Q_FOREACH (RelationModel *rel, childTable->foreignKeys())
if(rel->masterTable->name() == masterTableName) if(rel->masterTable->name() == masterTableName)
return rel; return rel;
@ -174,7 +174,7 @@ DatabaseModel DatabaseModel::fromJson(QJsonObject &json)
model.setVersion(json.value(NODE_VERSION).toInt()); model.setVersion(json.value(NODE_VERSION).toInt());
QJsonObject tables = json.value(NODE_TABLES).toObject(); QJsonObject tables = json.value(NODE_TABLES).toObject();
foreach (QString key, tables.keys()) { Q_FOREACH (QString key, tables.keys()) {
if(!json.value(key).isObject()) if(!json.value(key).isObject())
continue; continue;
@ -209,8 +209,8 @@ bool DatabaseModel::remove(const QString &tableName)
void DatabaseModel::fixRelations() void DatabaseModel::fixRelations()
{ {
/*TODO: fixme /*TODO: fixme
foreach (TableModel *table, currentModel) Q_FOREACH (TableModel *table, currentModel)
foreach (RelationModel *fk, table->foreignKeys()) Q_FOREACH (RelationModel *fk, table->foreignKeys())
fk->masterTable = currentModel.tableByClassName(fk->masterClassName); fk->masterTable = currentModel.tableByClassName(fk->masterClassName);
*/ */
} }

View File

@ -25,7 +25,7 @@
#include <QtCore/QMap> #include <QtCore/QMap>
#include <QtCore/QString> #include <QtCore/QString>
#include "defines.h" #include <QtNut/nut_global.h>
class QJsonObject; class QJsonObject;

14
src/nut/models/models.pri Normal file
View File

@ -0,0 +1,14 @@
INCLUDEPATH += $$PWD
HEADERS += \
$$PWD/databasemodel.h \
$$PWD/sqlmodel.h \
$$PWD/sqlmodel_p.h \
$$PWD/tablemodel.h
SOURCES += \
$$PWD/databasemodel.cpp \
$$PWD/sqlmodel.cpp \
$$PWD/tablemodel.cpp

View File

@ -19,7 +19,7 @@
**************************************************************************/ **************************************************************************/
#include "database.h" #include "database.h"
#include "tablesetbase_p.h" #include "abstracttableset.h"
#include "databasemodel.h" #include "databasemodel.h"
#include "tablemodel.h" #include "tablemodel.h"
#include "table.h" #include "table.h"
@ -29,55 +29,58 @@
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
//SqlModel::SqlModel(Query *q) : QAbstractItemModel(q.) SqlModelPrivate::SqlModelPrivate(SqlModel *parent) : q_ptr(parent)
//{ , renderer(nullptr)
{
//} Q_UNUSED(parent)
}
void SqlModel::setRenderer(const std::function<QVariant (int, QVariant)> &renderer) void SqlModel::setRenderer(const std::function<QVariant (int, QVariant)> &renderer)
{ {
_renderer = renderer; Q_D(SqlModel);
d->renderer = renderer;
} }
SqlModel::SqlModel(Database *database, TableSetBase *tableSet, QObject *parent) SqlModel::SqlModel(Database *database, AbstractTableSet *tableSet, QObject *parent)
: QAbstractTableModel(parent) : QAbstractTableModel(parent)
, _renderer(nullptr) , d_ptr(new SqlModelPrivate(this))
, d(new SqlModelPrivate(this))
{ {
Q_D(SqlModel);
d->model = database->model() d->model = database->model()
.tableByClassName(tableSet->childClassName()); .tableByClassName(tableSet->childClassName());
d->tableName = d->model->name(); d->tableName = d->model->name();
// setQuery("SELECT * FROM " + d->tableName, database->databaseName());
} }
int SqlModel::rowCount(const QModelIndex &parent) const int SqlModel::rowCount(const QModelIndex &parent) const
{ {
Q_D(const SqlModel);
Q_UNUSED(parent) Q_UNUSED(parent)
return d->rows.count(); return d->rows.count();
} }
int SqlModel::columnCount(const QModelIndex &parent) const int SqlModel::columnCount(const QModelIndex &parent) const
{ {
Q_D(const SqlModel);
Q_UNUSED(parent) Q_UNUSED(parent)
return d->model->fields().count(); return d->model->fields().count();
} }
QVariant SqlModel::data(const QModelIndex &index, int role) const QVariant SqlModel::data(const QModelIndex &index, int role) const
{ {
Q_D(const SqlModel);
if (!index.isValid()) if (!index.isValid())
return QVariant(); return QVariant();
if (index.row() >= d->rows.count() || index.row() < 0) if (index.row() >= d->rows.count() || index.row() < 0)
return QVariant("-"); return QVariant::fromValue(QStringLiteral("-"));
if (role == Qt::DisplayRole) { if (role == Qt::DisplayRole) {
Row<Table> t = d->rows.at(index.row()); Row<Table> t = d->rows.at(index.row());
QVariant v = t->property(d->model->field(index.column())->name.toLocal8Bit().data()); QVariant v = t->property(d->model->field(index.column())->name.toLocal8Bit().data());
if (_renderer != nullptr) if (d->renderer != nullptr)
v = _renderer(index.column(), v); v = d->renderer(index.column(), v);
return v; return v;
} }
return QVariant(); return QVariant();
@ -85,7 +88,8 @@ QVariant SqlModel::data(const QModelIndex &index, int role) const
void SqlModel::setRows(RowList<Table> rows) void SqlModel::setRows(RowList<Table> rows)
{ {
d.detach(); Q_D(SqlModel);
if (d->rows.count()) { if (d->rows.count()) {
beginRemoveRows(QModelIndex(), 0, d->rows.count()); beginRemoveRows(QModelIndex(), 0, d->rows.count());
d->rows.clear(); d->rows.clear();
@ -98,19 +102,15 @@ void SqlModel::setRows(RowList<Table> rows)
void SqlModel::append(Row<Table> table) void SqlModel::append(Row<Table> table)
{ {
d.detach(); Q_D(SqlModel);
beginInsertRows(QModelIndex(), d->rows.count(), d->rows.count()); beginInsertRows(QModelIndex(), d->rows.count(), d->rows.count());
d->rows.append(table); d->rows.append(table);
endInsertRows(); endInsertRows();
} }
//void SqlModel::append(Table *table)
//{
// append(TableType<Table>::Row(table));
//}
QVariant SqlModel::headerData(int section, Qt::Orientation orientation, int role) const QVariant SqlModel::headerData(int section, Qt::Orientation orientation, int role) const
{ {
Q_D(const SqlModel);
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
return d->model->field(section)->displayName; return d->model->field(section)->displayName;
} }
@ -119,13 +119,8 @@ QVariant SqlModel::headerData(int section, Qt::Orientation orientation, int role
Row<Table> SqlModel::at(const int &i) const Row<Table> SqlModel::at(const int &i) const
{ {
Q_D(const SqlModel);
return d->rows.at(i); return d->rows.at(i);
} }
SqlModelPrivate::SqlModelPrivate(SqlModel *parent)
{
Q_UNUSED(parent)
}
NUT_END_NAMESPACE NUT_END_NAMESPACE

View File

@ -22,28 +22,27 @@
#define SQLMODEL_H #define SQLMODEL_H
#include <QtCore/QAbstractTableModel> #include <QtCore/QAbstractTableModel>
#include "defines.h" #include <QtCore/QExplicitlySharedDataPointer>
#include "sqlmodel_p.h" #include <QtCore/QList>
#include <QExplicitlySharedDataPointer>
#include <QList> #include <QtNut/nut_global.h>
#include <functional>
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
class Database; class Database;
class TableSetBase; class AbstractTableSet;
class Table; class Table;
class TableModel; class TableModel;
class SqlModelPrivate;
class NUT_EXPORT SqlModel : public QAbstractTableModel class NUT_EXPORT SqlModel : public QAbstractTableModel
{ {
Q_OBJECT Q_OBJECT
SqlModelPrivate *d_ptr;
std::function <QVariant(int, QVariant)> _renderer; Q_DECLARE_PRIVATE(SqlModel)
public: public:
// explicit SqlModel(Query *q); // explicit SqlModel(Query *q);
explicit SqlModel(Database *database, TableSetBase *tableSet, QObject *parent = Q_NULLPTR); explicit SqlModel(Database *database, AbstractTableSet *tableSet, QObject *parent = Q_NULLPTR);
int rowCount(const QModelIndex &parent) const; int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const; int columnCount(const QModelIndex &parent) const;
@ -56,14 +55,11 @@ public:
void append(Row<Table> table); void append(Row<Table> table);
// void append(Table *table); // void append(Table *table);
QVariant headerData(int section, Qt::Orientation orientation, int role) const; QVariant headerData(int section, Qt::Orientation orientation, int role) const;
Row<Nut::Table> at(const int &i) const; Row<Table> at(const int &i) const;
void setRenderer(const std::function<QVariant (int, QVariant)> &renderer); void setRenderer(const std::function<QVariant (int, QVariant)> &renderer);
private: Q_SIGNALS:
QExplicitlySharedDataPointer<SqlModelPrivate> d;
signals:
void beforeShowText(int col, QVariant &value); void beforeShowText(int col, QVariant &value);
}; };
@ -71,7 +67,7 @@ template<class T>
Q_OUTOFLINE_TEMPLATE void SqlModel::setTable(RowList<T> rows) Q_OUTOFLINE_TEMPLATE void SqlModel::setTable(RowList<T> rows)
{ {
RowList<Table> tab; RowList<Table> tab;
foreach (auto t, rows) Q_FOREACH (auto t, rows)
tab.append(t); tab.append(t);
setRows(tab); setRows(tab);
} }

View File

@ -1,23 +1,30 @@
#ifndef SQLMODEL_P_H #ifndef SQLMODEL_P_H
#define SQLMODEL_P_H #define SQLMODEL_P_H
#include <QSharedPointer> #include <QtCore/QSharedPointer>
#include <QString> #include <QtCore/QString>
#include "defines.h"
#include <functional>
#include <QtNut/nut_global.h>
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
class SqlModel; class SqlModel;
class Table; class Table;
class TableModel; class TableModel;
class NUT_EXPORT SqlModelPrivate : public QSharedData { class NUT_EXPORT SqlModelPrivate {
public: public:
SqlModel *q_ptr;
Q_DECLARE_PUBLIC(SqlModel);
explicit SqlModelPrivate(SqlModel *parent); explicit SqlModelPrivate(SqlModel *parent);
QString tableName; QString tableName;
RowList<Table> rows; RowList<Table> rows;
TableModel *model; TableModel *model;
std::function <QVariant(int, QVariant)> renderer;
}; };
NUT_END_NAMESPACE NUT_END_NAMESPACE

View File

@ -21,15 +21,19 @@
#include <QtCore/QMetaObject> #include <QtCore/QMetaObject>
#include <QtCore/QMetaProperty> #include <QtCore/QMetaProperty>
#include <QtCore/QDebug> #include <QtCore/QDebug>
#include <QtCore/QJsonArray>
#include <QJsonArray> #include <QtCore/QJsonObject>
#include <QJsonObject>
#include "tablemodel.h" #include "tablemodel.h"
#include "defines.h" #include "nut_global.h"
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
#define REL_LOCAL_COLUMN QStringLiteral("localColumn")
#define REL_LOCAL_PROPERTY QStringLiteral("localProperty")
#define REL_MASTER_CLASS_NAME QStringLiteral("masterClassName")
#define REL_FOREIGIN_COLUMN QStringLiteral("foreignColumn")
QString TableModel::name() const QString TableModel::name() const
{ {
return _name; return _name;
@ -70,7 +74,7 @@ FieldModel *TableModel::field(int n) const
FieldModel *TableModel::field(const QString &name) const FieldModel *TableModel::field(const QString &name) const
{ {
foreach (FieldModel *f, _fields) Q_FOREACH (FieldModel *f, _fields)
if(f->name == name) if(f->name == name)
return f; return f;
@ -90,7 +94,7 @@ QList<RelationModel *> TableModel::foreignKeys() const
QStringList TableModel::fieldsNames() const QStringList TableModel::fieldsNames() const
{ {
QStringList ret; QStringList ret;
foreach (FieldModel *f, _fields) Q_FOREACH (FieldModel *f, _fields)
ret.append(f->name); ret.append(f->name);
return ret; return ret;
} }
@ -102,7 +106,7 @@ bool TableModel::operator ==(const TableModel &t) const{
if(fields().count() != t.fields().count()) if(fields().count() != t.fields().count())
return false; return false;
foreach (FieldModel *f, _fields) { Q_FOREACH (FieldModel *f, _fields) {
FieldModel *tf = t.field(f->name); FieldModel *tf = t.field(f->name);
if(!tf) if(!tf)
return false; return false;
@ -129,7 +133,7 @@ TableModel::TableModel(int typeId, const QString &tableName)
_typeId = typeId; _typeId = typeId;
_name = tableName; _name = tableName;
_className = tableMetaObject->className(); _className = QString::fromUtf8(tableMetaObject->className());
//#ifdef NUT_NAMESPACE //#ifdef NUT_NAMESPACE
// if(_className.startsWith(QT_STRINGIFY(NUT_NAMESPACE) "::")) // if(_className.startsWith(QT_STRINGIFY(NUT_NAMESPACE) "::"))
@ -147,7 +151,7 @@ TableModel::TableModel(int typeId, const QString &tableName)
continue; continue;
} }
if(type == __nut_FIELD){ if(type == QStringLiteral(__nut_FIELD)) {
auto *f = new FieldModel; auto *f = new FieldModel;
f->name = f->displayName = name; f->name = f->displayName = name;
_fields.append(f); _fields.append(f);
@ -156,15 +160,15 @@ TableModel::TableModel(int typeId, const QString &tableName)
// Browse all fields // Browse all fields
for(int j = 1; j < tableMetaObject->propertyCount(); j++){ for(int j = 1; j < tableMetaObject->propertyCount(); j++){
QMetaProperty fieldProperty = tableMetaObject->property(j); QMetaProperty fieldProperty = tableMetaObject->property(j);
auto name = QString::fromUtf8(fieldProperty.name());
FieldModel *fieldObj = field(fieldProperty.name()); FieldModel *fieldObj = field(name);
foreach (FieldModel *f, _fields) Q_FOREACH (FieldModel *f, _fields)
if(f->name == fieldProperty.name()) if(f->name == name)
f = fieldObj; f = fieldObj;
if(!fieldObj) if(!fieldObj)
continue; continue;
fieldObj->type = static_cast<QMetaType::Type>(fieldProperty.type()); fieldObj->type = static_cast<QMetaType::Type>(fieldProperty.type());
fieldObj->typeName = QString(fieldProperty.typeName()); fieldObj->typeName = QString::fromUtf8(fieldProperty.typeName());
} }
// Browse class infos // Browse class infos
@ -178,17 +182,17 @@ TableModel::TableModel(int typeId, const QString &tableName)
continue; continue;
} }
if(type == __nut_FOREIGN_KEY){ if(type == QStringLiteral(__nut_FOREIGN_KEY)) {
auto *fk = new RelationModel; auto *fk = new RelationModel;
fk->slaveTable = this; fk->slaveTable = this;
fk->localColumn = name + "Id"; fk->localColumn = name + QStringLiteral("Id");
fk->localProperty = name; fk->localProperty = name;
fk->foreignColumn = value; fk->foreignColumn = value;
fk->masterClassName = value; fk->masterClassName = value;
_foreignKeys.append(fk); _foreignKeys.append(fk);
} }
if(type == __nut_FIELD){ if(type == QStringLiteral(__nut_FIELD)) {
} }
@ -197,21 +201,21 @@ TableModel::TableModel(int typeId, const QString &tableName)
if (!f) if (!f)
continue; continue;
if (type == __nut_LEN) if (type == QStringLiteral(__nut_LEN))
f->length = value.toInt(); f->length = value.toInt();
else if (type == __nut_NOT_NULL) else if (type == QStringLiteral(__nut_NOT_NULL))
f->notNull = true; f->notNull = true;
else if (type == __nut_DEFAULT_VALUE) else if (type == QStringLiteral(__nut_DEFAULT_VALUE))
f->defaultValue = value; f->defaultValue = value;
else if (type == __nut_PRIMARY_KEY) else if (type == QStringLiteral(__nut_PRIMARY_KEY))
f->isPrimaryKey = true; f->isPrimaryKey = true;
else if (type == __nut_AUTO_INCREMENT) else if (type == QStringLiteral(__nut_AUTO_INCREMENT))
f->isAutoIncrement = true; f->isAutoIncrement = true;
else if (type == __nut_UNIQUE) else if (type == QStringLiteral(__nut_UNIQUE))
f->isUnique = true; f->isUnique = true;
else if (type == __nut_DISPLAY) else if (type == QStringLiteral(__nut_DISPLAY))
f->displayName = value.mid(1, value.length() - 2); f->displayName = value.mid(1, value.length() - 2);
else if (type == __nut_PRIMARY_KEY_AI) { else if (type == QStringLiteral(__nut_PRIMARY_KEY_AI)) {
f->isPrimaryKey = true; f->isPrimaryKey = true;
f->isAutoIncrement = true; f->isAutoIncrement = true;
} }
@ -238,31 +242,31 @@ TableModel::TableModel(const QJsonObject &json, const QString &tableName) : _typ
{ {
_name = tableName; _name = tableName;
QJsonObject fields = json.value(__FIELDS).toObject(); QJsonObject fields = json.value(QStringLiteral(__FIELDS)).toObject();
QJsonObject relations = json.value(__FOREIGN_KEYS).toObject(); QJsonObject relations = json.value(QStringLiteral(__FOREIGN_KEYS)).toObject();
foreach (QString key, fields.keys()) { Q_FOREACH (QString key, fields.keys()) {
QJsonObject fieldObject = fields.value(key).toObject(); QJsonObject fieldObject = fields.value(key).toObject();
//TODO: use FieldModel(QJsonObject) ctor //TODO: use FieldModel(QJsonObject) ctor
auto *f = new FieldModel; auto *f = new FieldModel;
f->name = fieldObject.value(__NAME).toString(); f->name = fieldObject.value(QStringLiteral(__NAME)).toString();
f->type = static_cast<QMetaType::Type>(QMetaType::type(fieldObject.value(__TYPE).toString().toLatin1().data())); f->type = static_cast<QMetaType::Type>(QMetaType::type(fieldObject.value(QStringLiteral(__TYPE)).toString().toLatin1().data()));
f->typeName = QMetaType::typeName(f->type); f->typeName = QString::fromUtf8(QMetaType::typeName(f->type));
if(fieldObject.contains(__nut_NOT_NULL)) if(fieldObject.contains(QStringLiteral(__nut_NOT_NULL)))
f->notNull = fieldObject.value(__nut_NOT_NULL).toBool(); f->notNull = fieldObject.value(QStringLiteral(__nut_NOT_NULL)).toBool();
if(fieldObject.contains(__nut_UNIQUE)) if(fieldObject.contains(QStringLiteral(__nut_UNIQUE)))
f->isUnique = fieldObject.value(__nut_UNIQUE).toBool(); f->isUnique = fieldObject.value(QStringLiteral(__nut_UNIQUE)).toBool();
if(fieldObject.contains(__nut_LEN)) if(fieldObject.contains(QStringLiteral(__nut_LEN)))
f->length = fieldObject.value(__nut_LEN).toInt(); f->length = fieldObject.value(QStringLiteral(__nut_LEN)).toInt();
if(fieldObject.contains(__nut_DEFAULT_VALUE)) if(fieldObject.contains(QStringLiteral(__nut_DEFAULT_VALUE)))
f->defaultValue = fieldObject.value(__nut_DEFAULT_VALUE).toString(); f->defaultValue = fieldObject.value(QStringLiteral(__nut_DEFAULT_VALUE)).toString();
_fields.append(f); _fields.append(f);
} }
foreach (QString key, relations.keys()) { Q_FOREACH (QString key, relations.keys()) {
QJsonObject relObject = fields.value(key).toObject(); QJsonObject relObject = fields.value(key).toObject();
_foreignKeys.append(new RelationModel(relObject)); _foreignKeys.append(new RelationModel(relObject));
} }
@ -280,43 +284,43 @@ QJsonObject TableModel::toJson() const
QJsonObject fieldsObj; QJsonObject fieldsObj;
QJsonObject foreignKeysObj; QJsonObject foreignKeysObj;
foreach (FieldModel *f, _fields) { Q_FOREACH (FieldModel *f, _fields) {
QJsonObject fieldObj; QJsonObject fieldObj;
fieldObj.insert(__NAME, f->name); fieldObj.insert(QStringLiteral(__NAME), f->name);
fieldObj.insert(__TYPE, QString(QVariant::typeToName(f->type))); fieldObj.insert(QStringLiteral(__TYPE), QString::fromUtf8(QVariant::typeToName(f->type)));
if(f->length) if(f->length)
fieldObj.insert(__nut_LEN, f->length); fieldObj.insert(QStringLiteral(__nut_LEN), f->length);
if(f->notNull) if(f->notNull)
fieldObj.insert(__nut_NOT_NULL, f->notNull); fieldObj.insert(QStringLiteral(__nut_NOT_NULL), f->notNull);
if(f->isUnique) if(f->isUnique)
fieldObj.insert(__nut_UNIQUE, f->isUnique); fieldObj.insert(QStringLiteral(__nut_UNIQUE), f->isUnique);
if(!f->defaultValue.isNull()) if(!f->defaultValue.isNull())
fieldObj.insert(__nut_DEFAULT_VALUE, f->defaultValue); fieldObj.insert(QStringLiteral(__nut_DEFAULT_VALUE), f->defaultValue);
if(f->isAutoIncrement) if(f->isAutoIncrement)
obj.insert(__nut_AUTO_INCREMENT, f->name); obj.insert(QStringLiteral(__nut_AUTO_INCREMENT), f->name);
if(f->isPrimaryKey) if(f->isPrimaryKey)
obj.insert(__nut_PRIMARY_KEY, f->name); obj.insert(QStringLiteral(__nut_PRIMARY_KEY), f->name);
fieldsObj.insert(f->name, fieldObj); fieldsObj.insert(f->name, fieldObj);
} }
foreach (RelationModel *rel, _foreignKeys) Q_FOREACH (RelationModel *rel, _foreignKeys)
foreignKeysObj.insert(rel->localColumn, rel->toJson()); foreignKeysObj.insert(rel->localColumn, rel->toJson());
obj.insert(__FIELDS, fieldsObj); obj.insert(QStringLiteral(__FIELDS), fieldsObj);
obj.insert(__FOREIGN_KEYS, foreignKeysObj); obj.insert(QStringLiteral(__FOREIGN_KEYS), foreignKeysObj);
return obj; return obj;
} }
RelationModel *TableModel::foreignKey(const QString &otherTable) const RelationModel *TableModel::foreignKey(const QString &otherTable) const
{ {
foreach (RelationModel *fk, _foreignKeys) Q_FOREACH (RelationModel *fk, _foreignKeys)
if(fk->masterClassName == otherTable) if(fk->masterClassName == otherTable)
return fk; return fk;
@ -325,7 +329,7 @@ RelationModel *TableModel::foreignKey(const QString &otherTable) const
RelationModel *TableModel::foreignKeyByField(const QString &fieldName) const RelationModel *TableModel::foreignKeyByField(const QString &fieldName) const
{ {
foreach (RelationModel *fk, _foreignKeys) Q_FOREACH (RelationModel *fk, _foreignKeys)
if(fk->localColumn == fieldName) if(fk->localColumn == fieldName)
return fk; return fk;
@ -335,17 +339,18 @@ RelationModel *TableModel::foreignKeyByField(const QString &fieldName) const
QString TableModel::toString() const QString TableModel::toString() const
{ {
QStringList sl; QStringList sl;
foreach (FieldModel *f, _fields) Q_FOREACH (FieldModel *f, _fields)
sl.append(f->name + " " + QVariant::typeToName(f->type)); sl.append(f->name + QStringLiteral(" ")
+ QString::fromUtf8(QVariant::typeToName(f->type)));
QString ret = QString("%1 (%2)") QString ret = QStringLiteral("%1 (%2)")
.arg(_name, sl.join(", ")); .arg(_name, sl.join(QStringLiteral(", ")));
return ret; return ret;
} }
QString TableModel::primaryKey() const QString TableModel::primaryKey() const
{ {
foreach (FieldModel *f, _fields) Q_FOREACH (FieldModel *f, _fields)
if(f->isPrimaryKey) if(f->isPrimaryKey)
return f->name; return f->name;
return QString(); return QString();
@ -361,47 +366,47 @@ bool TableModel::isPrimaryKeyAutoIncrement() const
FieldModel::FieldModel(const QJsonObject &json) FieldModel::FieldModel(const QJsonObject &json)
{ {
name = json.value(__NAME).toString(); name = json.value(QStringLiteral(__NAME)).toString();
type = static_cast<QMetaType::Type>(json.value(__TYPE).toInt()); type = static_cast<QMetaType::Type>(json.value(QStringLiteral(__TYPE)).toInt());
length = json.value(__nut_LEN).toInt(); length = json.value(QStringLiteral(__nut_LEN)).toInt();
notNull = json.value(__nut_NOT_NULL).toBool(); notNull = json.value(QStringLiteral(__nut_NOT_NULL)).toBool();
isUnique = json.value(__nut_UNIQUE).toBool(); isUnique = json.value(QStringLiteral(__nut_UNIQUE)).toBool();
isAutoIncrement = json.value(__nut_AUTO_INCREMENT).toBool(); isAutoIncrement = json.value(QStringLiteral(__nut_AUTO_INCREMENT)).toBool();
isPrimaryKey = json.value(__nut_PRIMARY_KEY).toBool(); isPrimaryKey = json.value(QStringLiteral(__nut_PRIMARY_KEY)).toBool();
defaultValue = json.value(__nut_DEFAULT_VALUE).toString(); defaultValue = json.value(QStringLiteral(__nut_DEFAULT_VALUE)).toString();
isUnique = json.value(__nut_UNIQUE).toBool(); isUnique = json.value(QStringLiteral(__nut_UNIQUE)).toBool();
} }
QJsonObject FieldModel::toJson() const QJsonObject FieldModel::toJson() const
{ {
QJsonObject fieldObj; QJsonObject fieldObj;
fieldObj.insert(__NAME, name); fieldObj.insert(QStringLiteral(__NAME), name);
fieldObj.insert(__TYPE, QString(QVariant::typeToName(type))); fieldObj.insert(QStringLiteral(__TYPE), QString::fromUtf8(QVariant::typeToName(type)));
fieldObj.insert(__nut_LEN, length); fieldObj.insert(QStringLiteral(__nut_LEN), length);
fieldObj.insert(__nut_NOT_NULL, notNull); fieldObj.insert(QStringLiteral(__nut_NOT_NULL), notNull);
fieldObj.insert(__nut_UNIQUE, isUnique); fieldObj.insert(QStringLiteral(__nut_UNIQUE), isUnique);
fieldObj.insert(__nut_AUTO_INCREMENT, isAutoIncrement); fieldObj.insert(QStringLiteral(__nut_AUTO_INCREMENT), isAutoIncrement);
fieldObj.insert(__nut_PRIMARY_KEY, isPrimaryKey); fieldObj.insert(QStringLiteral(__nut_PRIMARY_KEY), isPrimaryKey);
fieldObj.insert(__nut_DEFAULT_VALUE, defaultValue); fieldObj.insert(QStringLiteral(__nut_DEFAULT_VALUE), defaultValue);
return fieldObj; return fieldObj;
} }
RelationModel::RelationModel(const QJsonObject &obj) RelationModel::RelationModel(const QJsonObject &obj)
{ {
localColumn = obj.value("localColumn").toString(); localColumn = obj.value(REL_LOCAL_COLUMN).toString();
localProperty = obj.value("localProperty").toString(); localProperty = obj.value(REL_LOCAL_PROPERTY).toString();
masterClassName = obj.value("masterClassName").toString(); masterClassName = obj.value(REL_MASTER_CLASS_NAME).toString();
foreignColumn = obj.value("foreignColumn").toString(); foreignColumn = obj.value(REL_FOREIGIN_COLUMN).toString();
slaveTable = masterTable = nullptr; slaveTable = masterTable = nullptr;
} }
QJsonObject RelationModel::toJson() const QJsonObject RelationModel::toJson() const
{ {
QJsonObject o; QJsonObject o;
o.insert("localColumn", localColumn); o.insert(REL_LOCAL_COLUMN, localColumn);
o.insert("localProperty", localProperty); o.insert(REL_LOCAL_PROPERTY, localProperty);
o.insert("masterClassName", masterClassName); o.insert(REL_MASTER_CLASS_NAME, masterClassName);
o.insert("foreignColumn", foreignColumn); o.insert(REL_FOREIGIN_COLUMN, foreignColumn);
return o; return o;
} }

View File

@ -22,8 +22,9 @@
#define TABLEMODEL_H #define TABLEMODEL_H
#include <QtCore/QVariant> #include <QtCore/QVariant>
#include <QDebug> #include <QtCore/QDebug>
#include "defines.h"
#include <QtNut/nut_global.h>
class QJsonObject; class QJsonObject;

19
src/nut/nut.pri Normal file
View File

@ -0,0 +1,19 @@
DEFINES += NUT_SHARED_POINTER
QT = core sql gui
INCLUDEPATH += $$PWD
include(config/config.pri)
include(core/core.pri)
include(generators/generators.pri)
include(types/types.pri)
include(phrases/phrases.pri)
include(models/models.pri)
HEADERS += \
$$PWD/phrase.h
SOURCES += \
$$PWD/phrase.cpp
include($$PWD/3rdparty/serializer/src/src.pri)

27
src/nut/nut.pro Normal file
View File

@ -0,0 +1,27 @@
load(qt_build_config)
MODULE = nut
TARGET = QtNut
QT = core sql gui
DEFINES += QT_DEPRECATED_WARNINGS NUT_SHARED NUT_BUILD_LIB
DEFINES += NUT_SHARED_POINTER
include(config/config.pri)
include(core/core.pri)
include(generators/generators.pri)
include(types/types.pri)
include(phrases/phrases.pri)
include(models/models.pri)
HEADERS += \
$$PWD/phrase.h
SOURCES += \
$$PWD/phrase.cpp
load(qt_module)
include($$PWD/3rdparty/serializer/src/src.pri)

View File

@ -18,43 +18,4 @@
** **
**************************************************************************/ **************************************************************************/
#ifndef QUERY_P_H
#define QUERY_P_H
#include "phrase.h" #include "phrase.h"
#include <QtCore/QList>
#include <QtCore/QString>
#include <QtCore/QSharedData>
NUT_BEGIN_NAMESPACE
class Database;
class TableSetBase;
class QueryBase;
struct RelationModel;
class NUT_EXPORT QueryPrivate : public QSharedData {
QueryBase *q_ptr;
Q_DECLARE_PUBLIC(QueryBase)
public:
explicit QueryPrivate(QueryBase *parent);
~QueryPrivate();
QString sql;
QString className;
QString tableName;
QString select;
Database *database;
TableSetBase *tableSet;
QStringList joins;
QList<RelationModel*> relations;
int skip;
int take;
PhraseList orderPhrase, fieldPhrase;
ConditionalPhrase wherePhrase;
};
NUT_END_NAMESPACE
#endif // QUERY_P_H

38
src/nut/phrase.h Normal file
View File

@ -0,0 +1,38 @@
/**************************************************************************
**
** This file is part of Nut project.
** https://github.com/HamedMasafi/Nut
**
** Nut is free software: you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Nut is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with Nut. If not, see <http://www.gnu.org/licenses/>.
**
**************************************************************************/
#ifndef PHRASE_H
#define PHRASE_H
#include <QtNut/nut_global.h>
#include <QtNut/conditionalphrase.h>
#include <QtNut/abstractfieldphrase.h>
#include <QtNut/fieldphrase.h>
#include <QtNut/phraselist.h>
#include <QtNut/assignmentphraselist.h>
#include <QtNut/phrasedatalist.h>
#include <QtNut/phrasedata.h>
#include <QtNut/assignmentphrase.h>
#include <QtNut/numericphrase.h>
#include <QtNut/fieldphrase_date.h>
#include <QtNut/fieldphrase_qstring.h>
#include <QtNut/fieldphrase_bool.h>
#endif // PHRASE_H

View File

@ -19,6 +19,7 @@
**************************************************************************/ **************************************************************************/
#include "abstractfieldphrase.h" #include "abstractfieldphrase.h"
#include <QDebug>
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
@ -34,22 +35,26 @@ AbstractFieldPhrase::AbstractFieldPhrase(const char *className,
AbstractFieldPhrase::AbstractFieldPhrase(const AbstractFieldPhrase &other) AbstractFieldPhrase::AbstractFieldPhrase(const AbstractFieldPhrase &other)
{ {
data = other.data; data = other.data;
data->parents++; data->ref.ref();
} }
AbstractFieldPhrase::AbstractFieldPhrase(AbstractFieldPhrase &&other) AbstractFieldPhrase::AbstractFieldPhrase(AbstractFieldPhrase &&other)
{ {
data = other.data; data = other.data;
data->parents++;
other.data = nullptr; other.data = nullptr;
} }
AbstractFieldPhrase::~AbstractFieldPhrase() AbstractFieldPhrase::~AbstractFieldPhrase()
{ {
if (data) { if (data) {
--data->parents; if (!data->ref.deref()) {
if (data->parents <= 0) // qDebug() << "deleted" << data->className
// << data->fieldName;
delete data; delete data;
}
// else
// qDebug() << "more parents for" << data->className
// << data->fieldName;
} }
} }
@ -87,6 +92,14 @@ AssignmentPhrase AbstractFieldPhrase::operator <<(const QVariant &other)
return AssignmentPhrase(this, other); return AssignmentPhrase(this, other);
} }
void AbstractFieldPhrase::detach()
{
auto clone = data->clone();
if (!data->ref.deref())
delete data;
data = clone;
}
#define AbstractFieldPhraseOperatorVariant(class, op, cond) \ #define AbstractFieldPhraseOperatorVariant(class, op, cond) \
ConditionalPhrase class::operator op(const QVariant &other) \ ConditionalPhrase class::operator op(const QVariant &other) \
{ \ { \
@ -118,7 +131,7 @@ AbstractFieldPhrase AbstractFieldPhrase::operator ~()
AbstractFieldPhrase AbstractFieldPhrase::operator !() AbstractFieldPhrase AbstractFieldPhrase::operator !()
{ {
AbstractFieldPhrase f(data->className, data->fieldName); AbstractFieldPhrase f(data->clone());
f.data->isNot = !data->isNot; f.data->isNot = !data->isNot;
return f; return f;
} }

View File

@ -21,11 +21,10 @@
#ifndef ABSTRACTFIELDPHRASE_H #ifndef ABSTRACTFIELDPHRASE_H
#define ABSTRACTFIELDPHRASE_H #define ABSTRACTFIELDPHRASE_H
#include "../defines.h" #include <QtNut/nut_global.h>
#include <QtNut/assignmentphrase.h>
#include "assignmentphrase.h" #include <QtNut/conditionalphrase.h>
#include "conditionalphrase.h" #include <QtNut/phraselist.h>
#include "phraselist.h"
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
@ -47,7 +46,7 @@ public:
ConditionalPhrase in(QList<T> list) ConditionalPhrase in(QList<T> list)
{ {
QVariantList vlist; QVariantList vlist;
foreach (T t, list) Q_FOREACH (T t, list)
vlist.append(QVariant::fromValue(t)); vlist.append(QVariant::fromValue(t));
return ConditionalPhrase(this, PhraseData::In, vlist); return ConditionalPhrase(this, PhraseData::In, vlist);
@ -81,6 +80,9 @@ public:
AssignmentPhrase operator =(const QVariant &other); AssignmentPhrase operator =(const QVariant &other);
AssignmentPhrase operator =(const ConditionalPhrase &other); AssignmentPhrase operator =(const ConditionalPhrase &other);
AssignmentPhrase operator <<(const QVariant &other); AssignmentPhrase operator <<(const QVariant &other);
protected:
void detach();
}; };
NUT_END_NAMESPACE NUT_END_NAMESPACE

View File

@ -26,7 +26,7 @@ NUT_BEGIN_NAMESPACE
AssignmentPhrase::AssignmentPhrase(PhraseData *d) : data(d) AssignmentPhrase::AssignmentPhrase(PhraseData *d) : data(d)
{ {
d->parents++; d->ref.ref();
} }
AssignmentPhrase::AssignmentPhrase(AbstractFieldPhrase *l, const QVariant r) AssignmentPhrase::AssignmentPhrase(AbstractFieldPhrase *l, const QVariant r)
@ -56,9 +56,8 @@ AssignmentPhrase::AssignmentPhrase(AssignmentPhrase *ph, const QVariant &v)
AssignmentPhrase::~AssignmentPhrase() AssignmentPhrase::~AssignmentPhrase()
{ {
if (data) if (data && data->ref.deref())
if (!--data->parents) delete data;
delete data;
} }
NUT_END_NAMESPACE NUT_END_NAMESPACE

View File

@ -21,9 +21,8 @@
#ifndef ASSIGNMENTPHRASE_H #ifndef ASSIGNMENTPHRASE_H
#define ASSIGNMENTPHRASE_H #define ASSIGNMENTPHRASE_H
#include "../defines.h" #include <QtNut/nut_global.h>
#include <QtNut/assignmentphraselist.h>
#include "assignmentphraselist.h"
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE

View File

@ -68,17 +68,17 @@ AssignmentPhraseList AssignmentPhraseList::operator &(const AssignmentPhrase
AssignmentPhraseList::~AssignmentPhraseList() AssignmentPhraseList::~AssignmentPhraseList()
{ {
foreach (PhraseData *d, data) // Q_FOREACH (PhraseData *d, data)
if (!--d->parents) // if (!d->ref.deref())
delete d; // delete d;
// qDeleteAll(data); // qDeleteAll(data);
// data.clear(); // data.clear();
} }
void AssignmentPhraseList::incAllDataParents() void AssignmentPhraseList::incAllDataParents()
{ {
foreach (PhraseData *d, data) Q_FOREACH (PhraseData *d, data)
d->parents++; d->ref.ref();
} }

View File

@ -21,7 +21,7 @@
#ifndef ASSIGNMENTPHRASELIST_H #ifndef ASSIGNMENTPHRASELIST_H
#define ASSIGNMENTPHRASELIST_H #define ASSIGNMENTPHRASELIST_H
#include "../defines.h" #include <QtNut/nut_global.h>
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE

View File

@ -18,6 +18,8 @@
** **
**************************************************************************/ **************************************************************************/
#include <QDebug>
#include "abstractfieldphrase.h" #include "abstractfieldphrase.h"
#include "conditionalphrase.h" #include "conditionalphrase.h"
#include "phrasedata.h" #include "phrasedata.h"
@ -30,21 +32,21 @@ ConditionalPhrase::ConditionalPhrase() : data(nullptr)
ConditionalPhrase::ConditionalPhrase(const ConditionalPhrase &other) ConditionalPhrase::ConditionalPhrase(const ConditionalPhrase &other)
{ {
data = other.data; data = other.data;
data->parents++; data->ref.ref();
// const_cast<ConditionalPhrase&>(other).data = 0;
} }
#ifdef Q_COMPILER_RVALUE_REFS #ifdef Q_COMPILER_RVALUE_REFS
ConditionalPhrase::ConditionalPhrase(ConditionalPhrase &&other) ConditionalPhrase::ConditionalPhrase(ConditionalPhrase &&other)
{ {
this->data = qMove(other.data); data = other.data;
other.data = nullptr;
} }
#endif #endif
ConditionalPhrase::ConditionalPhrase(const PhraseData *data) ConditionalPhrase::ConditionalPhrase(const PhraseData *data)
{ {
this->data = const_cast<PhraseData*>(data); data = const_cast<PhraseData*>(data);
this->data->parents++; data->ref.ref();
} }
ConditionalPhrase::ConditionalPhrase(AbstractFieldPhrase *l, ConditionalPhrase::ConditionalPhrase(AbstractFieldPhrase *l,
@ -104,8 +106,10 @@ ConditionalPhrase::~ConditionalPhrase()
{ {
if (data) { if (data) {
data->cleanUp(); data->cleanUp();
if (!--data->parents) if (!data->ref.deref()) {
// qDebug() << "deleted for cond";
delete data; delete data;
}
} }
} }
@ -113,7 +117,7 @@ ConditionalPhrase &ConditionalPhrase::operator =(const ConditionalPhrase &other)
{ {
data = other.data; data = other.data;
if (data) if (data)
data->parents++; data->ref.ref();
return *this; return *this;
} }
@ -122,23 +126,6 @@ ConditionalPhrase ConditionalPhrase::operator ==(const QVariant &other)
return ConditionalPhrase(this, PhraseData::Equal, other); return ConditionalPhrase(this, PhraseData::Equal, other);
} }
//ConditionalPhrase ConditionalPhrase::operator ==(const AbstractFieldPhrase &other)
//{
// return ConditionalPhrase(this, PhraseData::Equal, other);
//}
//ConditionalPhrase ConditionalPhrase::operator &&(const ConditionalPhrase &other)
//{
// return ConditionalPhrase(this, PhraseData::And,
// const_cast<ConditionalPhrase&>(other));
//}
//ConditionalPhrase ConditionalPhrase::operator ||(const ConditionalPhrase &other)
//{
// return ConditionalPhrase(this, PhraseData::Or,
// const_cast<ConditionalPhrase&>(other));
//}
#define DECLARE_CONDITIONALPHRASE_OPERATORS_IMPL(op, cond) \ #define DECLARE_CONDITIONALPHRASE_OPERATORS_IMPL(op, cond) \
ConditionalPhrase operator op(const ConditionalPhrase &l, \ ConditionalPhrase operator op(const ConditionalPhrase &l, \
const ConditionalPhrase &r) \ const ConditionalPhrase &r) \
@ -149,8 +136,8 @@ ConditionalPhrase operator op(const ConditionalPhrase &l, \
p.data->operatorCond = cond; \ p.data->operatorCond = cond; \
p.data->left = l.data; \ p.data->left = l.data; \
p.data->right = r.data; \ p.data->right = r.data; \
l.data->parents++; \ l.data->ref.ref(); \
r.data->parents++; \ r.data->ref.ref(); \
return p; \ return p; \
} \ } \
ConditionalPhrase operator op(const ConditionalPhrase &l, \ ConditionalPhrase operator op(const ConditionalPhrase &l, \
@ -162,8 +149,8 @@ ConditionalPhrase operator op(const ConditionalPhrase &l, \
p.data->operatorCond = cond; \ p.data->operatorCond = cond; \
p.data->left = l.data; \ p.data->left = l.data; \
p.data->right = r.data; \ p.data->right = r.data; \
l.data->parents++; \ l.data->ref.ref(); \
r.data->parents++; \ r.data = nullptr; \
return p; \ return p; \
} \ } \
ConditionalPhrase operator op(ConditionalPhrase &&l, \ ConditionalPhrase operator op(ConditionalPhrase &&l, \
@ -175,8 +162,8 @@ ConditionalPhrase operator op(ConditionalPhrase &&l, \
p.data->operatorCond = cond; \ p.data->operatorCond = cond; \
p.data->left = l.data; \ p.data->left = l.data; \
p.data->right = r.data; \ p.data->right = r.data; \
l.data->parents++; \ r.data->ref.ref(); \
r.data->parents++; \ l.data = nullptr; \
return p; \ return p; \
} \ } \
ConditionalPhrase operator op(ConditionalPhrase &&l, ConditionalPhrase &&r) \ ConditionalPhrase operator op(ConditionalPhrase &&l, ConditionalPhrase &&r) \
@ -187,8 +174,8 @@ ConditionalPhrase operator op(ConditionalPhrase &&l, ConditionalPhrase &&r) \
p.data->operatorCond = cond; \ p.data->operatorCond = cond; \
p.data->left = l.data; \ p.data->left = l.data; \
p.data->right = r.data; \ p.data->right = r.data; \
l.data->parents++; \ l.data = nullptr; \
r.data->parents++; \ r.data = nullptr; \
return p; \ return p; \
} }
@ -198,8 +185,9 @@ DECLARE_CONDITIONALPHRASE_OPERATORS_IMPL(&&, PhraseData::And)
ConditionalPhrase ConditionalPhrase::operator !() ConditionalPhrase ConditionalPhrase::operator !()
{ {
ConditionalPhrase f(data); ConditionalPhrase f;
f.data->isNot = !data->isNot; f.data = data->clone();
f.data->isNot = !f.data->isNot;
return f; return f;
} }

View File

@ -21,7 +21,7 @@
#ifndef CONDITIONALPHRASE_H #ifndef CONDITIONALPHRASE_H
#define CONDITIONALPHRASE_H #define CONDITIONALPHRASE_H
#include "phrasedata.h" #include <QtNut/phrasedata.h>
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE

View File

@ -21,9 +21,8 @@
#ifndef FIELDPHRASE_H #ifndef FIELDPHRASE_H
#define FIELDPHRASE_H #define FIELDPHRASE_H
#include "../defines.h" #include <QtNut/nut_global.h>
#include <QtNut/abstractfieldphrase.h>
#include "abstractfieldphrase.h"
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
@ -51,28 +50,6 @@ Q_OUTOFLINE_TEMPLATE ConditionalPhrase FieldPhrase<T>::operator ==(const QVarian
return ConditionalPhrase(this, PhraseData::Equal, other); return ConditionalPhrase(this, PhraseData::Equal, other);
} }
template<>
class FieldPhrase<QString> : public AbstractFieldPhrase
{
public:
FieldPhrase(const char *className, const char *s) :
AbstractFieldPhrase(className, s)
{}
ConditionalPhrase like(const QString &term) {
return ConditionalPhrase(this, PhraseData::Like, term);
}
ConditionalPhrase contains(const QString &term) {
return ConditionalPhrase(this, PhraseData::Like, "%" + term + "%");
}
AssignmentPhrase operator =(const QVariant &v) {
return AssignmentPhrase(this, v);
}
};
//Date and time //Date and time
#define CONDITIONAL_VARIANT_METHOD(name, cond) \ #define CONDITIONAL_VARIANT_METHOD(name, cond) \
ConditionalPhrase name(int val) \ ConditionalPhrase name(int val) \
@ -80,31 +57,6 @@ public:
return ConditionalPhrase(this, cond, val); \ return ConditionalPhrase(this, cond, val); \
} }
template<>
class FieldPhrase<bool> : public AbstractFieldPhrase
{
public:
FieldPhrase(const char *className, const char *s) :
AbstractFieldPhrase(className, s)
{}
AssignmentPhrase operator =(const bool &other) {
return AssignmentPhrase(this, other);
}
FieldPhrase<bool> operator !()
{
FieldPhrase<bool> f(data->className, data->fieldName);
// f.data = new PhraseData(data);
f.data->isNot = !data->isNot;
return f;
}
operator ConditionalPhrase()
{
return ConditionalPhrase(this, PhraseData::Equal, !data->isNot);
}
};
NUT_END_NAMESPACE NUT_END_NAMESPACE

View File

@ -0,0 +1,6 @@
#include "fieldphrase_bool.h"
NUT_BEGIN_NAMESPACE
NUT_END_NAMESPACE

View File

@ -0,0 +1,38 @@
#ifndef NUT_FIELDPHRASE_BOOL_H
#define NUT_FIELDPHRASE_BOOL_H
#include <QtNut/nut_global.h>
#include <QtNut/fieldphrase.h>
#include <QtNut/fieldphrase.h>
NUT_BEGIN_NAMESPACE
template<>
class FieldPhrase<bool> : public AbstractFieldPhrase
{
public:
FieldPhrase(const char *className, const char *s) :
AbstractFieldPhrase(className, s)
{}
AssignmentPhrase operator =(const bool &other) {
return AssignmentPhrase(this, other);
}
FieldPhrase<bool> operator !()
{
FieldPhrase<bool> f(data->className, data->fieldName);
// f.data = new PhraseData(data);
f.data->isNot = !data->isNot;
return f;
}
operator ConditionalPhrase()
{
return ConditionalPhrase(this, PhraseData::Equal, !data->isNot);
}
};
NUT_END_NAMESPACE
#endif // NUT_FIELDPHRASE_BOOL_H

View File

@ -18,7 +18,7 @@
** **
**************************************************************************/ **************************************************************************/
#include "datephrase.h" #include "fieldphrase_date.h"
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE

View File

@ -21,10 +21,11 @@
#ifndef DATEPHRASE_H #ifndef DATEPHRASE_H
#define DATEPHRASE_H #define DATEPHRASE_H
#include "fieldphrase.h" #include <QtCore/QDateTime>
#include <QDateTime>
#include <type_traits> #include <type_traits>
#include <QtNut/fieldphrase.h>
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
#define COMMON_OPERATORS_DECL(T) \ #define COMMON_OPERATORS_DECL(T) \

View File

@ -0,0 +1,2 @@
#include "fieldphrase_qstring.h"

View File

@ -0,0 +1,39 @@
#ifndef NUT_FIELDPHRASE_QSTRING_H
#define NUT_FIELDPHRASE_QSTRING_H
#include <QtNut/nut_global.h>
#include <QtNut/abstractfieldphrase.h>
#include <QtNut/fieldphrase.h>
NUT_BEGIN_NAMESPACE
template<>
class FieldPhrase<QString> : public AbstractFieldPhrase
{
public:
FieldPhrase(const char *className, const char *s)
: AbstractFieldPhrase(className, s)
{}
ConditionalPhrase like(const QString &term)
{
return ConditionalPhrase(this, PhraseData::Like, term);
}
ConditionalPhrase contains(const QString &term)
{
return ConditionalPhrase(this,
PhraseData::Like,
QVariant(QStringLiteral("%") + term
+ QStringLiteral("%")));
}
AssignmentPhrase operator=(const QVariant &v)
{
return AssignmentPhrase(this, v);
}
};
NUT_END_NAMESPACE
#endif // NUT_FIELDPHRASE_QSTRING_H

Some files were not shown because too many files have changed in this diff Show More