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:
version:
- 5.15.0
platform:
- gcc_64
- android
@ -43,8 +44,6 @@ jobs:
os: windows-latest
- platform: clang_64
os: macos-latest
- platform: ios
os: macos-latest
runs-on: ${{matrix.os}}
steps:
@ -62,11 +61,16 @@ jobs:
run: |
qmake CONFIG+=install_ok QT_PLATFORM=${{matrix.platform}} "QT_TOOL_PATH=${{steps.qt.outputs.qtdir}}/Tools" nut.pro
${{steps.qt.outputs.make}} qmake_all
- name: make lib
- name: make module
run: |
${{steps.qt.outputs.make}}
${{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
if: startsWith(github.ref, 'refs/tags/')
with:

1
.gitignore vendored
View File

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

4
.gitmodules vendored
View File

@ -1,3 +1,3 @@
[submodule "3rdparty/serializer"]
path = 3rdparty/serializer
[submodule "src/nut/3rdparty/serializer"]
path = src/nut/3rdparty/serializer
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.
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
```cpp
#ifdef NUT_SHARED_POINTER
template <typename T>
using RowList = QList<QSharedPointer<T>>;
template <typename T>
using Row = QSharedPointer<T>;
#else
#ifdef NUT_RAW_POINTER
template <typename T>
using RowList = QList<T*>;
template <typename T>
using Row = T*;
#else
template <typename T>
using RowList = QList<QSharedPointer<T>>;
template <typename T>
using Row = QSharedPointer<T>;
#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
```cpp
#ifdef NUT_SHARED_POINTER
template<class T>
inline Row<T> create(QObject *parent) {
return QSharedPointer<T>(new T(parent));
}
#else
#ifdef NUT_RAW_POINTER
template<class T>
inline Row<T> create() {
return new T;
}
#else
template<class T>
inline Row<T> create(QObject *parent) {
return QSharedPointer<T>(new T(parent));
}
#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>();
```
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
CONFIG += ordered
SUBDIRS += \
src \
test
load(qt_parts)
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
#define DEFINES_P_H
#ifndef NUT_CONSTS_H
#define NUT_CONSTS_H
#define __NAME "name"
#define __TYPE "type"
@ -41,7 +41,7 @@
#define __nut_DEFAULT_VALUE "def"
#define __nut_NOT_NULL "notnull"
#define __nut_FOREIGN_KEY "foreign_key"
#define __nut_FOREIGN_KEY "foreign_key"
#define __nut_NEW "new"
#define __nut_REMOVE "remove"
#define __nut_CHANGE "change"
@ -56,4 +56,4 @@
# define NUT_WRAP_NAMESPACE(x) x
#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 @@
/**************************************************************************
**
** 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 NUT_MACROS_H
#define NUT_MACROS_H
#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) \
Q_CLASSINFO(__nut_NAME_PERFIX type #name #value, \
@ -73,6 +28,17 @@
private:
//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) \
Q_PROPERTY(type name READ read WRITE write) \
NUT_INFO(__nut_FIELD, name, 0) \
@ -89,59 +55,59 @@ public: \
} \
void write(type 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) \
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; \
public slots: \
public Q_SLOTS: \
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; \
}
#define NUT_FOREIGN_KEY_DECLARE(type, keytype, name, read, write) \
NUT_INFO(__nut_FIELD, name##Id, 0) \
NUT_INFO(__nut_FOREIGN_KEY, name, type) \
Nut::Row<type> m_##name; \
keytype m_##name##Id; \
Q_PROPERTY(Nut::Row<type> name READ read WRITE write) \
Q_PROPERTY(keytype name##Id READ read##Id WRITE write##Id) \
#define NUT_FOREIGN_KEY_DECLARE(type, keytype, name, read, write) \
NUT_INFO(__nut_FIELD, name##Id, 0) \
NUT_INFO(__nut_FOREIGN_KEY, name, type) \
Nut::Row<type> m_##name; \
keytype m_##name##Id; \
Q_PROPERTY(Nut::Row<type> name READ read WRITE write) \
Q_PROPERTY(keytype name##Id READ read##Id WRITE write##Id) \
public: \
Nut::Row<type> read() const; \
keytype read##Id() const; \
static NUT_WRAP_NAMESPACE(FieldPhrase<keytype>)& name##Id ## Field(){ \
static NUT_WRAP_NAMESPACE(FieldPhrase<keytype>) f = \
NUT_WRAP_NAMESPACE(FieldPhrase<keytype>) \
(staticMetaObject.className(), #name); \
Nut::Row<type> read() const; \
keytype read##Id() const; \
static NUT_WRAP_NAMESPACE(FieldPhrase<keytype>)& name##Id ## Field(){ \
static NUT_WRAP_NAMESPACE(FieldPhrase<keytype>) f = \
NUT_WRAP_NAMESPACE(FieldPhrase<keytype>) \
(staticMetaObject.className(), #name "Id"); \
return f; \
} \
public slots: \
void write(Nut::Row<type> name); \
public : \
Q_INVOKABLE void write(Nut::Row<type> name); \
Q_INVOKABLE void write(Nut::Row<Nut::Table> name); \
void write##Id(keytype name##Id);
#define NUT_FOREIGN_KEY_IMPLEMENT(class, type, keytype, name, read, write) \
\
Nut::Row<type> class::read() const { return m_##name ; } \
void class::write(Nut::Row<type> name){ \
propertyChanged(QT_STRINGIFY2(name##Id)); \
#define NUT_FOREIGN_KEY_IMPLEMENT(class, type, keytype, name, read, write) \
Nut::Row<type> class::read() const { return m_##name ; } \
void class::write(Nut::Row<type> name){ \
propertyChanged(QStringLiteral(QT_STRINGIFY2(name##Id))); \
m_##name = name; \
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; \
m_##name##Id = name->primaryValue().value<keytype>(); \
} \
void class::write##Id(keytype name##Id){ \
propertyChanged(QT_STRINGIFY2(name##Id)); \
m_##name##Id = name##Id; \
m_##name = nullptr; \
propertyChanged(QT_STRINGIFY2(name##Id)); \
void class::write(Nut::Row<Nut::Table> name){ \
write(qSharedPointerDynamicCast<type>(name)); \
} 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){ \
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) \
type *class::n##Table(){ \
static auto f = new type(); \
static auto f = new type(); \
return f; \
} \
NUT_WRAP_NAMESPACE(TableSet)<type> *class::n(){ \
return m_##n; \
}
#define NUT_FIELD(name) NUT_INFO(__nut_FIELD, name, 0)
#define NUT_PRIMARY_KEY(x) NUT_INFO(__nut_PRIMARY_KEY, x, 0) \
public: \
QVariant primaryValue() const override { \
return property(#x); \
} \
void setPrimaryValue(const QVariant &value) override { \
setProperty(#x, value); \
} \
//#define NUT_FIELD(name) NUT_INFO(__nut_FIELD, name, 0)
#define NUT_PRIMARY_KEY(x) NUT_INFO(__nut_PRIMARY_KEY, x, 0) \
public: \
QVariant primaryValue() const override { \
return property(#x); \
} \
void setPrimaryValue(const QVariant &value) override { \
setProperty(#x, value); \
} \
private:
@ -183,132 +149,4 @@ public slots: \
#define NUT_NOT_NULL(x) NUT_INFO(__nut_NOT_NULL, x, 1)
#define NUT_INDEX(name, field, order)
NUT_BEGIN_NAMESPACE
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
#endif // NUT_MACROS_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 "database.h"
#include "tablesetbase_p.h"
#include "abstracttableset.h"
#include "databasemodel.h"
#include "tablesetbasedata.h"
#include "abstracttablesetdata.h"
NUT_BEGIN_NAMESPACE
TableSetBase::TableSetBase(Database *parent) : QObject(parent),
data(new TableSetBaseData(parent))
AbstractTableSet::AbstractTableSet(Database *parent) : QObject(parent),
data(new AbstractTableSetData(parent))
{
parent->add(this);
}
TableSetBase::TableSetBase(Table *parent) : QObject(parent),
data(new TableSetBaseData(parent))
AbstractTableSet::AbstractTableSet(Table *parent) : QObject(parent),
data(new AbstractTableSetData(parent))
{
parent->add(this);
}
TableSetBase::~TableSetBase()
AbstractTableSet::~AbstractTableSet()
{
foreach (Row<Table> t, data->childs)
Q_FOREACH (Row<Table> t, data->childs)
if (t)
t->setParentTableSet(nullptr);
}
int TableSetBase::save(Database *db, bool cleanUp)
int AbstractTableSet::save(Database *db, bool cleanUp)
{
int rowsAffected = 0;
TableModel *masterModel = nullptr;
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)
t->setParentTable(data->table,
masterModel,
db->model().tableByClassName(t->metaObject()->className()));
db->model().tableByClassName(QString::fromUtf8(t->metaObject()->className())));
if (t->status() == Table::Added
|| t->status() == Table::Modified
|| t->status() == Table::Deleted) {
rowsAffected += t->save(db);
if (cleanUp)
#ifdef NUT_SHARED_POINTER
remove(t);
#else
#ifdef NUT_RAW_POINTER
t->deleteLater();
#else
remove(t);
#endif
}
}
@ -77,42 +77,47 @@ int TableSetBase::save(Database *db, bool cleanUp)
return rowsAffected;
}
void TableSetBase::clearChilds()
void AbstractTableSet::clearChilds()
{
#ifndef NUT_SHARED_POINTER
foreach (Table *t, data->childs)
#ifdef NUT_RAW_POINTER
Q_FOREACH (Table *t, data->childs)
t->deleteLater();
#endif
data->childs.clear();
}
void TableSetBase::add(Row<Table> t)
void AbstractTableSet::add(Row<Table> t)
{
data.detach();
data->childs.append(t);
t->setParentTableSet(this);
}
void TableSetBase::remove(Row<Table> t)
void AbstractTableSet::remove(Row<Table> t)
{
data.detach();
data->childs.removeAll(t);
}
QString TableSetBase::childClassName() const
QString AbstractTableSet::childClassName() const
{
return data->childClassName;
}
Database *TableSetBase::database() const
Database *AbstractTableSet::database() const
{
return data->database;
}
void TableSetBase::setDatabase(Database *database)
void AbstractTableSet::setDatabase(Database *database)
{
data.detach();
data->database = database;
}
int AbstractTableSet::size() const
{
return data->childs.size();
}
NUT_END_NAMESPACE

View File

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

View File

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

View File

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

View File

@ -21,16 +21,16 @@
#ifndef DATABASE_P_H
#define DATABASE_P_H
#include "database.h"
#include "databasemodel.h"
#include <QtCore/QDebug>
#include <QtCore/QSharedData>
#include <QDebug>
#include <QSharedData>
#include <QtNut/database.h>
#include <QtNut/databasemodel.h>
NUT_BEGIN_NAMESPACE
class ChangeLogTable;
class NUT_EXPORT DatabasePrivate //: public QSharedData
class NUT_EXPORT DatabasePrivate
{
Database *q_ptr;
Q_DECLARE_PUBLIC(Database)
@ -56,7 +56,7 @@ public:
QString connectionName;
QString driver;
SqlGeneratorBase *sqlGenerator;
AbstractSqlGenerator *sqlGenerator;
DatabaseModel currentModel;
TableSet<ChangeLogTable> *changeLogs;
@ -64,7 +64,7 @@ public:
static QMap<QString, DatabaseModel> allTableMaps;
static qulonglong lastId;
QSet<TableSetBase *> tableSets;
QSet<AbstractTableSet *> tableSets;
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
#define QUERYBASE_H
#ifndef PROPERTYSIGNALMAPPER_H
#define PROPERTYSIGNALMAPPER_H
#include <QtCore/QObject>
#include <QtCore/qglobal.h>
#include <QtCore/QExplicitlySharedDataPointer>
#include <QtNut/nut_global.h>
#include "defines.h"
#include "query_p.h"
#include <QMetaMethod>
#include <QMetaProperty>
NUT_BEGIN_NAMESPACE
//TODO: remove this class
class Table;
class TableSetBase;
class NUT_EXPORT QueryBase : public QObject
class PropertySignalMapper
{
Q_OBJECT
protected:
QExplicitlySharedDataPointer<QueryPrivate> d;
struct ClassData
{
QMetaMethod propertyChanged;
QList<QMetaProperty> properties;
QMap<QString, QString> signalMaps;
};
static QMap<QString, ClassData*> _data;
public:
explicit QueryBase(QObject *parent = nullptr);
protected:
// void addTableToSet(TableSetBase *set, Table *table);
public slots:
static void map(Table *obj);
static QString changedProperty(QObject *obj, int senderSignalIndex);
};
NUT_END_NAMESPACE
#endif // QUERYBASE_H
#endif // PROPERTYSIGNALMAPPER_H

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -18,14 +18,14 @@
**
**************************************************************************/
#ifndef SQLGENERATORBASE_H
#define SQLGENERATORBASE_H
#ifndef NUT_ABSTRACTSQLGENERATOR_H
#define NUT_ABSTRACTSQLGENERATOR_H
#include <QtCore/qglobal.h>
#include <QtCore/QObject>
#include <QtCore/QStringList>
#include "../phrase.h"
//#include "../wherephrase.h"
#include <QtNut/phrase.h>
class SqlSerializer;
@ -37,7 +37,7 @@ class DatabaseModel;
class TableModel;
class Database;
struct RelationModel;
class NUT_EXPORT SqlGeneratorBase : public QObject
class NUT_EXPORT AbstractSqlGenerator : public QObject
{
// Q_OBJECT
@ -65,8 +65,8 @@ public:
Sum
};
explicit SqlGeneratorBase(Database *parent);
virtual ~SqlGeneratorBase() = default;
explicit AbstractSqlGenerator(Database *parent);
virtual ~AbstractSqlGenerator() = default;
virtual bool supportPrimaryKey(const QMetaType::Type &type) {
Q_UNUSED(type)
@ -168,4 +168,4 @@ protected:
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 "../tablemodel.h"
#include "tablemodel.h"
#include <QPoint>
#include <QPointF>
#include <QTime>
#include <QDate>
#include <QDateTime>
#include <QtCore/QPoint>
#include <QtCore/QPointF>
#include <QtCore/QTime>
#include <QtCore/QDate>
#include <QtCore/QDateTime>
#ifdef QT_GUI_LIB
#include <QPolygon>
#include <QPolygonF>
# include <QtGui/QPolygon>
# include <QtGui/QPolygonF>
#endif
#include "sqlserializer.h"
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;
switch (field->type) {
case QMetaType::Bool: return "BOOLEAN";
case QMetaType::Bool: return QStringLiteral("BOOLEAN");
case QMetaType::Char:
case QMetaType::QChar: return "CHAR(1)";
case QMetaType::QChar: return QStringLiteral("CHAR(1)");
case QMetaType::SChar:
case QMetaType::UChar: return "TINYINT";
case QMetaType::UChar: return QStringLiteral("TINYINT");
case QMetaType::Short:
case QMetaType::UShort: return "SMALLINT";
case QMetaType::UShort: return QStringLiteral("SMALLINT");
case QMetaType::UInt:
case QMetaType::Int:
dbType = "INT";
dbType = QStringLiteral("INT");
if(field->isAutoIncrement)
dbType += " AUTO_INCREMENT";
dbType += QStringLiteral(" AUTO_INCREMENT");
break;
case QMetaType::Long:
case QMetaType::ULong:
case QMetaType::LongLong:
case QMetaType::ULongLong:
return "BIGINT";
return QStringLiteral("BIGINT");
case QMetaType::Float:
return "FLOAT";
return QStringLiteral("FLOAT");
case QMetaType::Double:
return "REAL";
return QStringLiteral("REAL");
case QMetaType::QBitArray: return "VARBINARY";
case QMetaType::QByteArray: return "BLOB";
case QMetaType::QDate: return "DATE";
case QMetaType::QTime: return "TIME";
case QMetaType::QDateTime: return "DATETIME";
case QMetaType::QBitArray: return QStringLiteral("VARBINARY");
case QMetaType::QByteArray: return QStringLiteral("BLOB");
case QMetaType::QDate: return QStringLiteral("DATE");
case QMetaType::QTime: return QStringLiteral("TIME");
case QMetaType::QDateTime: return QStringLiteral("DATETIME");
case QMetaType::QString:
if(field->length)
dbType = QString("VARCHAR(%1)").arg(field->length);
dbType = QStringLiteral("VARCHAR(%1)").arg(field->length);
else
dbType = "TEXT";
dbType = QStringLiteral("TEXT");
break;
@ -109,7 +109,7 @@ QString MySqlGenerator::fieldType(FieldModel *field)
case QMetaType::QJsonValue:
case QMetaType::QJsonObject:
case QMetaType::QJsonDocument:
case QMetaType::QStringList: return "TEXT";
case QMetaType::QStringList: return QStringLiteral("TEXT");
default:
qWarning("Type %s::%s(%d) is not supported",
@ -128,16 +128,16 @@ QString MySqlGenerator::fieldType(FieldModel *field)
QString MySqlGenerator::escapeValue(const QVariant &v) const
{
if (v.type() == QVariant::Bool)
return v.toBool() ? "1" : "0";
return v.toBool() ? QStringLiteral("1") : QStringLiteral("0");
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)
return "'" + v.toDate().toString("yyyy-MM-dd") + "'";
return v.toDate().toString(QStringLiteral("''yyyy-MM-dd''"));
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
// if (v.type() == QVariant::Polygon) {
@ -178,7 +178,7 @@ QString MySqlGenerator::escapeValue(const QVariant &v) const
// }
// 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))
// return pol;
// QStringList parts = p.split(",");
// foreach (QString v, parts) {
// Q_FOREACH (QString v, parts) {
// QList<int> l = _serializer->toListInt(p.trimmed(), " ");
// if (l.count() != 2)
// return QPolygon();
@ -210,7 +210,7 @@ QVariant MySqlGenerator::unescapeValue(const QMetaType::Type &type, const QVaria
// return pol;
// QStringList parts = p.split(",");
// foreach (QString v, parts) {
// Q_FOREACH (QString v, parts) {
// QList<qreal> l = _serializer->toListReal(p.trimmed(), " ");
// if (l.count() != 2)
// return QPolygonF();
@ -229,7 +229,7 @@ QVariant MySqlGenerator::unescapeValue(const QMetaType::Type &type, const QVaria
if (type == QMetaType::QDate)
return dbValue.toDate();
return SqlGeneratorBase::unescapeValue(type, dbValue);
return AbstractSqlGenerator::unescapeValue(type, dbValue);
}
bool MySqlGenerator::readInsideParentese(QString &text, QString &out)
@ -316,10 +316,10 @@ QString MySqlGenerator::createConditionalPhrase(const PhraseData *d) const
case PhraseData::AddMinutesDateTime:
case PhraseData::AddSeconds:
case PhraseData::AddSecondsDateTime:
return QString("DATE_ADD(%1, INTERVAL %2 %3)")
return QStringLiteral("DATE_ADD(%1, INTERVAL %2 %3)")
.arg(createConditionalPhrase(d->left),
d->operand.toString(),
SqlGeneratorBase::dateTimePartName(op));
AbstractSqlGenerator::dateTimePartName(op));
default:
break;
@ -333,26 +333,26 @@ QString MySqlGenerator::createConditionalPhrase(const PhraseData *d) const
case PhraseData::DatePartHour:
case PhraseData::DatePartMinute:
case PhraseData::DatePartSecond:
return QString("%2(%1)")
return QStringLiteral("%2(%1)")
.arg(createConditionalPhrase(d->left),
SqlGeneratorBase::dateTimePartName(op));
AbstractSqlGenerator::dateTimePartName(op));
default:
break;
}
}
return SqlGeneratorBase::createConditionalPhrase(d);
return AbstractSqlGenerator::createConditionalPhrase(d);
}
void MySqlGenerator::appendSkipTake(QString &sql, int skip, int take)
{
if (take > 0 && skip > 0) {
sql.append(QString(" LIMIT %1 OFFSET %2")
sql.append(QStringLiteral(" LIMIT %1 OFFSET %2")
.arg(take)
.arg(skip));
} 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
#include <QtCore/qglobal.h>
#include "sqlgeneratorbase_p.h"
#include <QtNut/abstractsqlgenerator.h>
NUT_BEGIN_NAMESPACE
class NUT_EXPORT MySqlGenerator : public SqlGeneratorBase
class NUT_EXPORT MySqlGenerator : public AbstractSqlGenerator
{
public:
explicit MySqlGenerator(Database *parent = nullptr);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -22,28 +22,27 @@
#define SQLMODEL_H
#include <QtCore/QAbstractTableModel>
#include "defines.h"
#include "sqlmodel_p.h"
#include <QExplicitlySharedDataPointer>
#include <QList>
#include <functional>
#include <QtCore/QExplicitlySharedDataPointer>
#include <QtCore/QList>
#include <QtNut/nut_global.h>
NUT_BEGIN_NAMESPACE
class Database;
class TableSetBase;
class AbstractTableSet;
class Table;
class TableModel;
class SqlModelPrivate;
class NUT_EXPORT SqlModel : public QAbstractTableModel
{
Q_OBJECT
std::function <QVariant(int, QVariant)> _renderer;
SqlModelPrivate *d_ptr;
Q_DECLARE_PRIVATE(SqlModel)
public:
// 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 columnCount(const QModelIndex &parent) const;
@ -56,14 +55,11 @@ public:
void append(Row<Table> table);
// void append(Table *table);
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);
private:
QExplicitlySharedDataPointer<SqlModelPrivate> d;
signals:
Q_SIGNALS:
void beforeShowText(int col, QVariant &value);
};
@ -71,7 +67,7 @@ template<class T>
Q_OUTOFLINE_TEMPLATE void SqlModel::setTable(RowList<T> rows)
{
RowList<Table> tab;
foreach (auto t, rows)
Q_FOREACH (auto t, rows)
tab.append(t);
setRows(tab);
}

View File

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

View File

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

View File

@ -22,8 +22,9 @@
#define TABLEMODEL_H
#include <QtCore/QVariant>
#include <QDebug>
#include "defines.h"
#include <QtCore/QDebug>
#include <QtNut/nut_global.h>
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 <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 <QDebug>
NUT_BEGIN_NAMESPACE
@ -34,22 +35,26 @@ AbstractFieldPhrase::AbstractFieldPhrase(const char *className,
AbstractFieldPhrase::AbstractFieldPhrase(const AbstractFieldPhrase &other)
{
data = other.data;
data->parents++;
data->ref.ref();
}
AbstractFieldPhrase::AbstractFieldPhrase(AbstractFieldPhrase &&other)
{
data = other.data;
data->parents++;
other.data = nullptr;
}
AbstractFieldPhrase::~AbstractFieldPhrase()
{
if (data) {
--data->parents;
if (data->parents <= 0)
if (!data->ref.deref()) {
// qDebug() << "deleted" << data->className
// << data->fieldName;
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);
}
void AbstractFieldPhrase::detach()
{
auto clone = data->clone();
if (!data->ref.deref())
delete data;
data = clone;
}
#define AbstractFieldPhraseOperatorVariant(class, op, cond) \
ConditionalPhrase class::operator op(const QVariant &other) \
{ \
@ -118,7 +131,7 @@ AbstractFieldPhrase AbstractFieldPhrase::operator ~()
AbstractFieldPhrase AbstractFieldPhrase::operator !()
{
AbstractFieldPhrase f(data->className, data->fieldName);
AbstractFieldPhrase f(data->clone());
f.data->isNot = !data->isNot;
return f;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -21,9 +21,8 @@
#ifndef FIELDPHRASE_H
#define FIELDPHRASE_H
#include "../defines.h"
#include "abstractfieldphrase.h"
#include <QtNut/nut_global.h>
#include <QtNut/abstractfieldphrase.h>
NUT_BEGIN_NAMESPACE
@ -51,28 +50,6 @@ Q_OUTOFLINE_TEMPLATE ConditionalPhrase FieldPhrase<T>::operator ==(const QVarian
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
#define CONDITIONAL_VARIANT_METHOD(name, cond) \
ConditionalPhrase name(int val) \
@ -80,31 +57,6 @@ public:
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

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

View File

@ -21,10 +21,11 @@
#ifndef DATEPHRASE_H
#define DATEPHRASE_H
#include "fieldphrase.h"
#include <QDateTime>
#include <QtCore/QDateTime>
#include <type_traits>
#include <QtNut/fieldphrase.h>
NUT_BEGIN_NAMESPACE
#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