Merge pull request #43 from HamedMasafi/dev
Finally _dev_ merged into _master_ !!!
This commit is contained in:
commit
404c1c3198
|
|
@ -32,3 +32,5 @@ Makefile*
|
||||||
#QtCtreator Qml
|
#QtCtreator Qml
|
||||||
*.qmlproject.user
|
*.qmlproject.user
|
||||||
*.qmlproject.user.*
|
*.qmlproject.user.*
|
||||||
|
|
||||||
|
build
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "3rdparty/serializer"]
|
||||||
|
path = 3rdparty/serializer
|
||||||
|
url = https://github.com/HamedMasafi/Serializer.git
|
||||||
39
.travis.yml
39
.travis.yml
|
|
@ -13,29 +13,23 @@ compiler:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
matrix:
|
matrix:
|
||||||
- QT=5 BREW=
|
- QT=59 BREW=ex PPA=beineri/opt-qt591-trusty
|
||||||
- QT=5 BREW=ex PPA=ubuntu-sdk-team/ppa
|
- QT=59 BREW=ex PPA=beineri/opt-qt592-trusty
|
||||||
- QT=51 BREW=ex PPA=beineri/opt-qt511-trusty
|
- QT=59 BREW=ex PPA=beineri/opt-qt593-trusty
|
||||||
- QT=52 BREW=ex PPA=beineri/opt-qt521-trusty
|
- QT=59 BREW=ex PPA=beineri/opt-qt594-trusty
|
||||||
- QT=53 BREW=ex PPA=beineri/opt-qt532-trusty
|
- QT=59 BREW=ex PPA=beineri/opt-qt595-trusty
|
||||||
- QT=54 BREW=ex PPA=beineri/opt-qt542-trusty
|
- QT=59 BREW=ex PPA=beineri/opt-qt596-trusty
|
||||||
- QT=55 BREW=@5.5 PPA=beineri/opt-qt551-trusty
|
- QT=510 BREW=ex PPA=beineri/opt-qt-5.10.1-trusty
|
||||||
- QT=56 BREW=ex PPA=beineri/opt-qt562-trusty
|
|
||||||
- QT=56 BREW=ex PPA=beineri/opt-qt563-trusty
|
|
||||||
- QT=57 BREW=@5.7 PPA=beineri/opt-qt571-trusty
|
|
||||||
- QT=58 BREW=ex PPA=beineri/opt-qt58-trusty
|
|
||||||
- QT=59 BREW=@5.9 PPA=beineri/opt-qt591-trusty
|
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
exclude:
|
exclude:
|
||||||
- { os: osx, env: QT=5 BREW=ex PPA=ubuntu-sdk-team/ppa }
|
- { os: osx, env: QT=59 BREW=ex PPA=beineri/opt-qt591-trusty }
|
||||||
- { os: osx, env: QT=51 BREW=ex PPA=beineri/opt-qt511-trusty }
|
- { os: osx, env: QT=59 BREW=ex PPA=beineri/opt-qt592-trusty }
|
||||||
- { os: osx, env: QT=52 BREW=ex PPA=beineri/opt-qt521-trusty }
|
- { os: osx, env: QT=59 BREW=ex PPA=beineri/opt-qt593-trusty }
|
||||||
- { os: osx, env: QT=53 BREW=ex PPA=beineri/opt-qt532-trusty }
|
- { os: osx, env: QT=59 BREW=ex PPA=beineri/opt-qt594-trusty }
|
||||||
- { os: osx, env: QT=54 BREW=ex PPA=beineri/opt-qt542-trusty }
|
- { os: osx, env: QT=59 BREW=ex PPA=beineri/opt-qt595-trusty }
|
||||||
- { os: osx, env: QT=56 BREW=ex PPA=beineri/opt-qt562-trusty }
|
- { os: osx, env: QT=59 BREW=ex PPA=beineri/opt-qt596-trusty }
|
||||||
- { os: osx, env: QT=56 BREW=ex PPA=beineri/opt-qt563-trusty }
|
- { os: osx, env: QT=510 BREW=ex PPA=beineri/opt-qt-5.10.1-trusty }
|
||||||
- { os: osx, env: QT=58 BREW=ex PPA=beineri/opt-qt58-trusty }
|
|
||||||
|
|
||||||
addons:
|
addons:
|
||||||
coverity_scan:
|
coverity_scan:
|
||||||
|
|
@ -72,7 +66,8 @@ before_script:
|
||||||
- '[[ "$TRAVIS_OS_NAME" != linux || "$PPA" != */opt-* ]] || . /opt/qt$QT/bin/qt$QT-env.sh'
|
- '[[ "$TRAVIS_OS_NAME" != linux || "$PPA" != */opt-* ]] || . /opt/qt$QT/bin/qt$QT-env.sh'
|
||||||
- '[[ "$TRAVIS_OS_NAME" != linux || "$PPA" == */opt-* ]] || export QT_SELECT=qt5'
|
- '[[ "$TRAVIS_OS_NAME" != linux || "$PPA" == */opt-* ]] || export QT_SELECT=qt5'
|
||||||
- mkdir -p "$TRAVIS_BUILD_DIR-build"
|
- mkdir -p "$TRAVIS_BUILD_DIR-build"
|
||||||
- qmake -o "$TRAVIS_BUILD_DIR-build" -r -Wall -Wlogic -Wparser CONFIG+=debug_and_release "$TRAVIS_BUILD_DIR"
|
- cd "$TRAVIS_BUILD_DIR-build"
|
||||||
|
- qmake -r -Wall -Wlogic -Wparser CONFIG+=debug_and_release "$TRAVIS_BUILD_DIR/nut.pro"
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- make -C "$TRAVIS_BUILD_DIR-build" all
|
- make -C "$TRAVIS_BUILD_DIR-build" all
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit f9d81fcc6244271b3926891b0c86554e1e6b967e
|
||||||
54
README.md
54
README.md
|
|
@ -1,11 +1,17 @@
|
||||||
|
|
||||||
|
|
||||||
# Nut
|
# Nut
|
||||||
|
|
||||||
## Build result
|
## Build result
|
||||||
| Brancc name | Icon |
|
| Branch | Status |
|
||||||
| ------------- |:-------------:|
|
| ------------- |:-------------:|
|
||||||
| master | [](https://travis-ci.org/HamedMasafi/Nut) |
|
| master | [](https://travis-ci.org/HamedMasafi/Nut) |
|
||||||
| dev | [](https://travis-ci.org/HamedMasafi/Nut) |
|
| dev | [](https://travis-ci.org/HamedMasafi/Nut) |
|
||||||
|
|
||||||
|
[](https://gitlicense.com/license/hamedmasafi/nut)
|
||||||
|
|
||||||
|
[](https://www.codacy.com/app/HamedMasafi/Nut?utm_source=github.com&utm_medium=referral&utm_content=HamedMasafi/Nut&utm_campaign=Badge_Grade)
|
||||||
|
|
||||||
## Advanced, Powerful and easy to use ORM for Qt5
|
## Advanced, Powerful and easy to use ORM for Qt5
|
||||||
|
|
||||||
|
|
@ -17,6 +23,52 @@
|
||||||
- Automatically create and update database
|
- Automatically create and update database
|
||||||
- IDE auto complete support, No hard-code nedded
|
- IDE auto complete support, No hard-code nedded
|
||||||
- Table join detect
|
- Table join detect
|
||||||
|
- Supported types:
|
||||||
|
|
||||||
|
| Type | Sqlite | MySql | Postgresql| Ms Sql server |
|
||||||
|
|--------|--------|--------|--------|--------|
|
||||||
|
| QBitArray | BLOB | VARBINARY | BYTEA | VARBINARY (MAX) |
|
||||||
|
| QByteArray | BLOB | BLOB | BYTEA | VARBINARY (MAX) |
|
||||||
|
| QChar | NCHAR(1) | CHAR(1) | CHAR(1) | CHAR(1) |
|
||||||
|
| QColor | TEXT | TEXT | TEXT | TEXT |
|
||||||
|
| QDate | DATE | DATE | DATE | DATE |
|
||||||
|
| QDateTime | DATETIME | DATETIME | TIMESTAMP | DATETIME |
|
||||||
|
| QJsonArray | TEXT | TEXT | JSON | TEXT |
|
||||||
|
| QJsonDocument | TEXT | TEXT | JSON | TEXT |
|
||||||
|
| QJsonObject | TEXT | TEXT | JSON | TEXT |
|
||||||
|
| QJsonValue | TEXT | TEXT | JSON | TEXT |
|
||||||
|
| QLine | TEXT | TEXT | LINE | TEXT |
|
||||||
|
| QLineF | TEXT | TEXT | LINE | TEXT |
|
||||||
|
| QPoint | TEXT | POINT | POINT | GEOMETRY |
|
||||||
|
| QPointF | TEXT | POINT | POINT | GEOMETRY |
|
||||||
|
| QPolygon | TEXT | POLYGON | POLYGON | TEXT |
|
||||||
|
| QPolygonF | TEXT | POLYGON | POLYGON | TEXT |
|
||||||
|
| QRect | TEXT | TEXT | BOX | TEXT |
|
||||||
|
| QRectF | TEXT | TEXT | BOX | TEXT |
|
||||||
|
| QSize | TEXT | TEXT | TEXT | TEXT |
|
||||||
|
| QSizeF | TEXT | TEXT | TEXT | TEXT |
|
||||||
|
| QString | TEXT | TEXT | TEXT | NVARCHAR(MAX) |
|
||||||
|
| QStringList | TEXT[^*] | TEXT | TEXT[] | TEXT |
|
||||||
|
| QTime | TIME | TIME | TIME | TIME |
|
||||||
|
| QUrl | TEXT | TEXT | TEXT | TEXT |
|
||||||
|
| QUuid | TEXT | VARCHAR(64) | UUID | UNIQUEIDENTIFIER |
|
||||||
|
| bool | BOOLEAN | BOOLEAN | BOOLEAN | BIT |
|
||||||
|
| char | TINYINT | CHAR(1) | CHAR(1) | CHAR(1) |
|
||||||
|
| double | DOUBLE | REAL | REAL | REAL |
|
||||||
|
| float | FLOAT | FLOAT | FLOAT | FLOAT(24) |
|
||||||
|
| int | INT | INT | INTEGER | INT |
|
||||||
|
| long | MEDIUMINT | BIGINT | BIGINT | BIGINT |
|
||||||
|
| qlonglong | BIGINT | BIGINT | BIGINT | BIGINT |
|
||||||
|
| qulonglong | BIGINT UNSIGNED | BIGINT | BIGINT | BIGINT |
|
||||||
|
| short | SMALLINT | SMALLINT | SMALLINT | SMALLINT |
|
||||||
|
| signed char | TINYINT | TINYINT | SMALLINT | TINYINT |
|
||||||
|
| uchar | TINYINT UNSIGNED | TINYINT | SMALLINT | TINYINT |
|
||||||
|
| uint | INT UNSIGNED | INT | INTEGER | INT |
|
||||||
|
| ulong | MEDIUMINT UNSIGNED | BIGINT | BIGINT | BIGINT |
|
||||||
|
| ushort | SMALLINT UNSIGNED | SMALLINT | SMALLINT | SMALLINT |
|
||||||
|
|
||||||
|
[^*]: Using internal store/restore serialization
|
||||||
|
|
||||||
|
|
||||||
## Sample Codes
|
## Sample Codes
|
||||||
### Read data from database:
|
### Read data from database:
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
#QT -= gui
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
|
|
||||||
#include "../src/table.h"
|
#include "../src/table.h"
|
||||||
#include "../src/database.h"
|
#include "../src/database.h"
|
||||||
|
#include "../src/sqlmodel.h"
|
||||||
#include "../src/tableset.h"
|
#include "../src/tableset.h"
|
||||||
|
#include "../src/tablemodel.h"
|
||||||
#include "../src/query.h"
|
#include "../src/query.h"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
#include "../src/sqlmodel.h"
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
#include "../src/tablemodel.h"
|
||||||
|
|
@ -3,11 +3,10 @@
|
||||||
src_dir="src"
|
src_dir="src"
|
||||||
namespace_name="nut"
|
namespace_name="nut"
|
||||||
|
|
||||||
ns=$(echo $namespace_name|awk '{print tolower($0)}')
|
#ns=$(echo $namespace_name|awk '{print tolower($0)}')
|
||||||
Ns="Nut"
|
Ns="Nut"
|
||||||
NS=$(echo $namespace_name|awk '{print toupper($0)}')
|
NS=$(echo $namespace_name|awk '{print toupper($0)}')
|
||||||
echo $NS
|
|
||||||
exit
|
|
||||||
|
|
||||||
create_sub_folder=true
|
create_sub_folder=true
|
||||||
|
|
||||||
|
|
@ -38,5 +37,6 @@ while read line; do
|
||||||
echo "#include \"../$src_dir/$header.h\"" >> "$Ns"
|
echo "#include \"../$src_dir/$header.h\"" >> "$Ns"
|
||||||
echo "#include \"../$src_dir/$header.h\"" >> "$ns.h"
|
echo "#include \"../$src_dir/$header.h\"" >> "$ns.h"
|
||||||
fi
|
fi
|
||||||
|
echo $Ns
|
||||||
done <&3
|
done <&3
|
||||||
exec 3<&-
|
exec 3<&-
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
#include "../src/table.h"
|
#include "../src/table.h"
|
||||||
#include "../src/database.h"
|
#include "../src/database.h"
|
||||||
|
#include "../src/sqlmodel.h"
|
||||||
#include "../src/tableset.h"
|
#include "../src/tableset.h"
|
||||||
#include "../src/dbgeography.h"
|
#include "../src/tablemodel.h"
|
||||||
#include "../src/query.h"
|
#include "../src/query.h"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
#include "../src/sqlmodel.h"
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
#include "../src/tablemodel.h"
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
QT += sql gui
|
||||||
|
|
||||||
|
TARGET = nut
|
||||||
|
TEMPLATE = lib
|
||||||
|
CONFIG += c++11
|
||||||
|
|
||||||
|
DEFINES += QT_DEPRECATED_WARNINGS NUT_COMPILE_STATIC
|
||||||
|
|
||||||
|
include($$PWD/src/src.pri)
|
||||||
|
include($$PWD/3rdparty/serializer/src/src.pri)
|
||||||
30
nut.pri
30
nut.pri
|
|
@ -3,6 +3,8 @@ QT += core sql
|
||||||
CONFIG += c++11
|
CONFIG += c++11
|
||||||
|
|
||||||
INCLUDEPATH += $$PWD/include
|
INCLUDEPATH += $$PWD/include
|
||||||
|
DEFINES += NUT_SHARED_POINTER
|
||||||
|
include(3rdparty/serializer/src/src.pri)
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
$$PWD/src/generators/sqlgeneratorbase_p.h \
|
$$PWD/src/generators/sqlgeneratorbase_p.h \
|
||||||
|
|
@ -27,7 +29,19 @@ HEADERS += \
|
||||||
$$PWD/src/serializableobject.h \
|
$$PWD/src/serializableobject.h \
|
||||||
$$PWD/src/sqlmodel.h \
|
$$PWD/src/sqlmodel.h \
|
||||||
$$PWD/src/sqlmodel_p.h \
|
$$PWD/src/sqlmodel_p.h \
|
||||||
$$PWD/src/phrase.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 += \
|
SOURCES += \
|
||||||
$$PWD/src/generators/sqlgeneratorbase.cpp \
|
$$PWD/src/generators/sqlgeneratorbase.cpp \
|
||||||
|
|
@ -47,4 +61,16 @@ SOURCES += \
|
||||||
$$PWD/src/database.cpp \
|
$$PWD/src/database.cpp \
|
||||||
$$PWD/src/serializableobject.cpp \
|
$$PWD/src/serializableobject.cpp \
|
||||||
$$PWD/src/sqlmodel.cpp \
|
$$PWD/src/sqlmodel.cpp \
|
||||||
$$PWD/src/phrase.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
|
||||||
|
|
|
||||||
55
nut.pro
55
nut.pro
|
|
@ -1,53 +1,6 @@
|
||||||
QT += sql
|
TEMPLATE = subdirs
|
||||||
QT -= gui
|
|
||||||
|
|
||||||
TARGET = nut
|
SUBDIRS += \
|
||||||
TEMPLATE = lib
|
src \
|
||||||
CONFIG += c++11
|
test
|
||||||
|
|
||||||
DEFINES += QT_DEPRECATED_WARNINGS
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
#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->sqlGenertor()->insertBulk(_className, _fields, variants);
|
||||||
|
QSqlQuery q = _database->exec(sql);
|
||||||
|
return q.numRowsAffected();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
#ifndef BULKINSERTER_H
|
||||||
|
#define BULKINSERTER_H
|
||||||
|
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <QDebug>
|
||||||
|
#include "defines.h"
|
||||||
|
#include "phrases/phraselist.h"
|
||||||
|
#include "phrases/fieldphrase.h"
|
||||||
|
|
||||||
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class PhraseList;
|
||||||
|
class Database;
|
||||||
|
class BulkInserter
|
||||||
|
{
|
||||||
|
Database *_database;
|
||||||
|
QString _className;
|
||||||
|
Nut::PhraseList _fields;
|
||||||
|
QList<QVariantList> variants;
|
||||||
|
size_t _fieldCount;
|
||||||
|
|
||||||
|
public:
|
||||||
|
BulkInserter(Database *db, QString &className);
|
||||||
|
void setFields(const PhraseList &ph);
|
||||||
|
|
||||||
|
void insert(std::initializer_list<QVariant> vars);
|
||||||
|
template<typename... Args>
|
||||||
|
void insert(Args... args) {
|
||||||
|
insert({args...});
|
||||||
|
}
|
||||||
|
int apply();
|
||||||
|
};
|
||||||
|
|
||||||
|
NUT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // BULKINSERTER_H
|
||||||
|
|
@ -35,7 +35,7 @@ class ChangeLogTable : public Table
|
||||||
|
|
||||||
NUT_DECLARE_FIELD(QString, data, data, setData)
|
NUT_DECLARE_FIELD(QString, data, data, setData)
|
||||||
|
|
||||||
NUT_DECLARE_FIELD(QString, version, version, setVersion)
|
NUT_DECLARE_FIELD(int, version, version, setVersion)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ChangeLogTable(QObject *parentTableSet = Q_NULLPTR);
|
explicit ChangeLogTable(QObject *parentTableSet = Q_NULLPTR);
|
||||||
|
|
|
||||||
150
src/database.cpp
150
src/database.cpp
|
|
@ -45,7 +45,9 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
|
|
||||||
#define __CHANGE_LOG_TABLE_NAME "__change_logs"
|
#ifndef __CHANGE_LOG_TABLE_NAME
|
||||||
|
# define __CHANGE_LOG_TABLE_NAME "__change_logs"
|
||||||
|
#endif
|
||||||
|
|
||||||
NUT_BEGIN_NAMESPACE
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
|
@ -53,7 +55,7 @@ qulonglong DatabasePrivate::lastId = 0;
|
||||||
QMap<QString, DatabaseModel> DatabasePrivate::allTableMaps;
|
QMap<QString, DatabaseModel> DatabasePrivate::allTableMaps;
|
||||||
|
|
||||||
DatabasePrivate::DatabasePrivate(Database *parent) : q_ptr(parent),
|
DatabasePrivate::DatabasePrivate(Database *parent) : q_ptr(parent),
|
||||||
port(0), sqlGenertor(0), changeLogs(0),
|
port(0), sqlGenertor(nullptr), changeLogs(nullptr),
|
||||||
isDatabaseNew(false)
|
isDatabaseNew(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -69,12 +71,13 @@ bool DatabasePrivate::open(bool update)
|
||||||
|
|
||||||
db = QSqlDatabase::addDatabase(driver, connectionName);
|
db = QSqlDatabase::addDatabase(driver, connectionName);
|
||||||
db.setHostName(hostName);
|
db.setHostName(hostName);
|
||||||
db.setPort(port);
|
if (port)
|
||||||
|
db.setPort(port);
|
||||||
db.setDatabaseName(databaseName);
|
db.setDatabaseName(databaseName);
|
||||||
db.setUserName(userName);
|
db.setUserName(userName);
|
||||||
db.setPassword(password);
|
db.setPassword(password);
|
||||||
|
|
||||||
if (driver.toLower().startsWith("qsqlite")
|
if (driver.startsWith("qsqlite", Qt::CaseInsensitive)
|
||||||
&& !QFile::exists(databaseName)) {
|
&& !QFile::exists(databaseName)) {
|
||||||
//Force to execute update database
|
//Force to execute update database
|
||||||
isDatabaseNew = true;
|
isDatabaseNew = true;
|
||||||
|
|
@ -108,18 +111,18 @@ bool DatabasePrivate::open(bool update)
|
||||||
|
|
||||||
isDatabaseNew = true;
|
isDatabaseNew = true;
|
||||||
return open(update);
|
return open(update);
|
||||||
} else {
|
|
||||||
qWarning("Unknown error detecting change logs, %s",
|
|
||||||
db.lastError().text().toLatin1().data());
|
|
||||||
}
|
}
|
||||||
|
qWarning("Unknown error detecting change logs, %s",
|
||||||
|
db.lastError().text().toLatin1().data());
|
||||||
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(update)
|
// if(update)
|
||||||
return updateDatabase();
|
return updateDatabase();
|
||||||
else
|
// else
|
||||||
return true;
|
// return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DatabasePrivate::updateDatabase()
|
bool DatabasePrivate::updateDatabase()
|
||||||
|
|
@ -134,24 +137,39 @@ bool DatabasePrivate::updateDatabase()
|
||||||
|
|
||||||
if (last == current) {
|
if (last == current) {
|
||||||
qDebug("Databse is up-to-date");
|
qDebug("Databse is up-to-date");
|
||||||
|
//TODO: crash without this and I don't know why!
|
||||||
|
changeLogs->clearChilds();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (TableModel *tm, current) {
|
||||||
|
foreach (FieldModel *fm, tm->fields()) {
|
||||||
|
if (sqlGenertor->fieldType(fm).isEmpty()) {
|
||||||
|
qWarning("The type (%s) is not supported for field %s::%s",
|
||||||
|
QMetaType::typeName(fm->type),
|
||||||
|
qPrintable(tm->className()),
|
||||||
|
qPrintable(fm->name));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!last.count())
|
if (!last.count())
|
||||||
qDebug("Databse is new");
|
qDebug("Databse is new");
|
||||||
else
|
else
|
||||||
qDebug("Databse is changed");
|
qDebug("Databse is changed");
|
||||||
|
|
||||||
QStringList sql = sqlGenertor->diff(last, current);
|
QStringList sql = sqlGenertor->diff(last, current);
|
||||||
qDebug()<<"database Sql =\n"<<sql;
|
|
||||||
db.transaction();
|
db.transaction();
|
||||||
foreach (QString s, sql) {
|
foreach (QString s, sql) {
|
||||||
db.exec(s);
|
db.exec(s);
|
||||||
|
|
||||||
if (db.lastError().type() != QSqlError::NoError)
|
if (db.lastError().type() != QSqlError::NoError) {
|
||||||
qWarning("Error executing sql command `%s`, %s",
|
qWarning("Error executing sql command `%s`, %s",
|
||||||
qPrintable(s),
|
qPrintable(s),
|
||||||
db.lastError().text().toLatin1().data());
|
db.lastError().text().toLatin1().data());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
putModelToDatabase();
|
putModelToDatabase();
|
||||||
bool ok = db.commit();
|
bool ok = db.commit();
|
||||||
|
|
@ -159,15 +177,9 @@ qDebug()<<"database Sql =\n"<<sql;
|
||||||
if (db.lastError().type() == QSqlError::NoError) {
|
if (db.lastError().type() == QSqlError::NoError) {
|
||||||
|
|
||||||
q->databaseUpdated(last.version(), current.version());
|
q->databaseUpdated(last.version(), current.version());
|
||||||
|
if (!last.count())
|
||||||
|
q->databaseCreated();
|
||||||
|
|
||||||
for (int i = 0; i < q->metaObject()->methodCount(); i++) {
|
|
||||||
QMetaMethod m = q->metaObject()->method(i);
|
|
||||||
if (m.name() == "update" + current.version()) {
|
|
||||||
m.invoke(q, Qt::DirectConnection,
|
|
||||||
Q_ARG(QString, current.version()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
qWarning("Unable update database, error = %s",
|
qWarning("Unable update database, error = %s",
|
||||||
db.lastError().text().toLatin1().data());
|
db.lastError().text().toLatin1().data());
|
||||||
|
|
@ -186,6 +198,7 @@ bool DatabasePrivate::getCurrectScheema()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QMap<QString, QString> tables;
|
||||||
tables.clear();
|
tables.clear();
|
||||||
|
|
||||||
// TODO: change logs must not be in model
|
// TODO: change logs must not be in model
|
||||||
|
|
@ -205,7 +218,9 @@ bool DatabasePrivate::getCurrectScheema()
|
||||||
|
|
||||||
if (!nutClassInfoString(q->metaObject()->classInfo(i),
|
if (!nutClassInfoString(q->metaObject()->classInfo(i),
|
||||||
type, name, value)) {
|
type, name, value)) {
|
||||||
qDebug() << "No valid table in" << q->metaObject()->classInfo(i).value();
|
|
||||||
|
errorMessage = QString("No valid table in %1")
|
||||||
|
.arg(q->metaObject()->classInfo(i).value());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (type == __nut_TABLE) {
|
if (type == __nut_TABLE) {
|
||||||
|
|
@ -222,23 +237,13 @@ bool DatabasePrivate::getCurrectScheema()
|
||||||
currentModel.append(sch);
|
currentModel.append(sch);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == __nut_DB_VERSION)
|
if (type == __nut_DB_VERSION) {
|
||||||
currentModel.setVersion(name);
|
bool ok;
|
||||||
|
int version = value.toInt(&ok);
|
||||||
/* TODO: remove
|
|
||||||
QStringList version
|
|
||||||
= QString(ci.value()).replace("\"", "").split('.');
|
|
||||||
bool ok = false;
|
|
||||||
if (version.length() == 1) {
|
|
||||||
currentModel.setVersion(version.at(0).toInt(&ok));
|
|
||||||
} else if (version.length() == 2) {
|
|
||||||
currentModel.setVersionMajor(version.at(0).toInt(&ok));
|
|
||||||
currentModel.setVersionMinor(version.at(1).toInt(&ok));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ok)
|
if (!ok)
|
||||||
qFatal("NUT_DB_VERSION macro accept version in format 'x' or "
|
qFatal("NUT_DB_VERSION macro accept version in format 'x'");
|
||||||
"'x[.y]' only, and x,y must be integer values\n");*/
|
currentModel.setVersion(version);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 1; i < q->metaObject()->propertyCount(); i++) {
|
for (int i = 1; i < q->metaObject()->propertyCount(); i++) {
|
||||||
|
|
@ -252,42 +257,37 @@ bool DatabasePrivate::getCurrectScheema()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (TableModel *table, currentModel)
|
foreach (TableModel *table, currentModel) {
|
||||||
|
foreach (FieldModel *f, table->fields()) {
|
||||||
|
if (f->isPrimaryKey && ! sqlGenertor->supportPrimaryKey(f->type))
|
||||||
|
qFatal("The field of type %s does not support as primary key",
|
||||||
|
qPrintable(f->typeName));
|
||||||
|
|
||||||
|
if (f->isAutoIncrement && ! sqlGenertor->supportAutoIncrement(f->type))
|
||||||
|
qFatal("The field of type %s does not support as auto increment",
|
||||||
|
qPrintable(f->typeName));
|
||||||
|
}
|
||||||
|
|
||||||
foreach (RelationModel *fk, table->foregionKeys())
|
foreach (RelationModel *fk, table->foregionKeys())
|
||||||
fk->masterTable = currentModel.tableByClassName(fk->masterClassName);
|
fk->masterTable = currentModel.tableByClassName(fk->masterClassName);
|
||||||
|
}
|
||||||
|
|
||||||
allTableMaps.insert(q->metaObject()->className(), currentModel);
|
allTableMaps.insert(q->metaObject()->className(), currentModel);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//bool DatabasePrivate::checkClassInfo(const QMetaClassInfo &classInfo, QString &type, QString &name, QString &value)
|
|
||||||
//{
|
|
||||||
// if (!QString(classInfo.name()).startsWith(__nut_NAME_PERFIX)) {
|
|
||||||
// return false;
|
|
||||||
// } else {
|
|
||||||
// QStringList parts = QString(classInfo.value()).split("\n");
|
|
||||||
// if (parts.count() != 3)
|
|
||||||
// return false;
|
|
||||||
|
|
||||||
// type = parts[0];
|
|
||||||
// name = parts[1];
|
|
||||||
// value = parts[2];
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
DatabaseModel DatabasePrivate::getLastScheema()
|
DatabaseModel DatabasePrivate::getLastScheema()
|
||||||
{
|
{
|
||||||
ChangeLogTable *u = changeLogs->query()
|
Row<ChangeLogTable> u = changeLogs->query()
|
||||||
->orderBy(!ChangeLogTable::idField())
|
->orderBy(!ChangeLogTable::idField())
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
// DatabaseModel ret(q->metaObject()->className());
|
// DatabaseModel ret(q->metaObject()->className());
|
||||||
|
|
||||||
if (u) {
|
if (u) {
|
||||||
|
QJsonParseError e;
|
||||||
QJsonObject json
|
QJsonObject json
|
||||||
= QJsonDocument::fromJson(
|
= QJsonDocument::fromJson(u->data().replace("\\\"", "\"").toUtf8(), &e).object();
|
||||||
QByteArray(u->data().toLocal8Bit().data())).object();
|
|
||||||
|
|
||||||
DatabaseModel ret = json;
|
DatabaseModel ret = json;
|
||||||
return ret;
|
return ret;
|
||||||
|
|
@ -321,11 +321,11 @@ bool DatabasePrivate::putModelToDatabase()
|
||||||
DatabaseModel current = currentModel;
|
DatabaseModel current = currentModel;
|
||||||
/*current.remove(__CHANGE_LOG_TABLE_NAME)*/;
|
/*current.remove(__CHANGE_LOG_TABLE_NAME)*/;
|
||||||
|
|
||||||
ChangeLogTable *changeLog = new ChangeLogTable();
|
auto changeLog = create<ChangeLogTable>();
|
||||||
changeLog->setData(QJsonDocument(current.toJson()).toJson());
|
changeLog->setData(QJsonDocument(current.toJson()).toJson(QJsonDocument::Compact));
|
||||||
changeLog->setVersion(current.version());
|
changeLog->setVersion(current.version());
|
||||||
changeLogs->append(changeLog);
|
changeLogs->append(changeLog);
|
||||||
q->saveChanges();
|
q->saveChanges(true);
|
||||||
changeLog->deleteLater();
|
changeLog->deleteLater();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -344,9 +344,10 @@ bool DatabasePrivate::putModelToDatabase()
|
||||||
void DatabasePrivate::createChangeLogs()
|
void DatabasePrivate::createChangeLogs()
|
||||||
{
|
{
|
||||||
// currentModel.model("change_log")
|
// currentModel.model("change_log")
|
||||||
QString diff = sqlGenertor->diff(0, currentModel.tableByName("__change_log"));
|
QStringList diff = sqlGenertor->diff(nullptr, currentModel.tableByName("__change_log"));
|
||||||
|
|
||||||
db.exec(diff);
|
foreach (QString s, diff)
|
||||||
|
db.exec(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -357,6 +358,7 @@ void DatabasePrivate::createChangeLogs()
|
||||||
Database::Database(QObject *parent)
|
Database::Database(QObject *parent)
|
||||||
: QObject(parent), d_ptr(new DatabasePrivate(this))
|
: QObject(parent), d_ptr(new DatabasePrivate(this))
|
||||||
{
|
{
|
||||||
|
// _d = new QSharedDataPointer<DatabasePrivate>(new DatabasePrivate(this));
|
||||||
DatabasePrivate::lastId++;
|
DatabasePrivate::lastId++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -364,6 +366,7 @@ Database::Database(const Database &other)
|
||||||
: QObject(other.parent()), d_ptr(new DatabasePrivate(this))
|
: QObject(other.parent()), d_ptr(new DatabasePrivate(this))
|
||||||
{
|
{
|
||||||
DatabasePrivate::lastId++;
|
DatabasePrivate::lastId++;
|
||||||
|
// _d = other._d;
|
||||||
|
|
||||||
setDriver(other.driver());
|
setDriver(other.driver());
|
||||||
setHostName(other.hostName());
|
setHostName(other.hostName());
|
||||||
|
|
@ -393,8 +396,7 @@ Database::~Database()
|
||||||
if (d->db.isOpen())
|
if (d->db.isOpen())
|
||||||
d->db.close();
|
d->db.close();
|
||||||
|
|
||||||
if (d_ptr)
|
delete d_ptr;
|
||||||
delete d_ptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Database::databaseName() const
|
QString Database::databaseName() const
|
||||||
|
|
@ -516,7 +518,12 @@ QSqlDatabase Database::database()
|
||||||
return d->db;
|
return d->db;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::databaseUpdated(QString oldVersion, QString newVersion)
|
void Database::databaseCreated()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Database::databaseUpdated(int oldVersion, int newVersion)
|
||||||
{
|
{
|
||||||
Q_UNUSED(oldVersion);
|
Q_UNUSED(oldVersion);
|
||||||
Q_UNUSED(newVersion);
|
Q_UNUSED(newVersion);
|
||||||
|
|
@ -559,10 +566,9 @@ bool Database::open(bool updateDatabase)
|
||||||
if (!d->sqlGenertor) {
|
if (!d->sqlGenertor) {
|
||||||
qFatal("Sql generator for driver %s not found",
|
qFatal("Sql generator for driver %s not found",
|
||||||
driver().toLatin1().constData());
|
driver().toLatin1().constData());
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return d->open(updateDatabase);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return d->open(updateDatabase);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::close()
|
void Database::close()
|
||||||
|
|
@ -571,7 +577,7 @@ void Database::close()
|
||||||
d->db.close();
|
d->db.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
QSqlQuery Database::exec(QString sql)
|
QSqlQuery Database::exec(const QString &sql)
|
||||||
{
|
{
|
||||||
Q_D(Database);
|
Q_D(Database);
|
||||||
|
|
||||||
|
|
@ -592,6 +598,12 @@ void Database::add(TableSetBase *t)
|
||||||
int Database::saveChanges(bool cleanUp)
|
int Database::saveChanges(bool cleanUp)
|
||||||
{
|
{
|
||||||
Q_D(Database);
|
Q_D(Database);
|
||||||
|
|
||||||
|
if (!d->db.isOpen()) {
|
||||||
|
qWarning("Database is not open");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int rowsAffected = 0;
|
int rowsAffected = 0;
|
||||||
foreach (TableSetBase *ts, d->tableSets)
|
foreach (TableSetBase *ts, d->tableSets)
|
||||||
rowsAffected += ts->save(this, cleanUp);
|
rowsAffected += ts->save(this, cleanUp);
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
#include <QtCore/qglobal.h>
|
#include <QtCore/qglobal.h>
|
||||||
#include <QtCore/QList>
|
#include <QtCore/QList>
|
||||||
#include <QtSql/QSqlDatabase>
|
#include <QtSql/QSqlDatabase>
|
||||||
|
#include <QSharedDataPointer>
|
||||||
|
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
#include "tableset.h"
|
#include "tableset.h"
|
||||||
|
|
@ -39,11 +40,12 @@ class NUT_EXPORT Database : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
// QSharedDataPointer<DatabasePrivate> *_d;
|
||||||
DatabasePrivate *d_ptr;
|
DatabasePrivate *d_ptr;
|
||||||
Q_DECLARE_PRIVATE(Database)
|
Q_DECLARE_PRIVATE(Database)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Database(QObject *parent = 0);
|
explicit Database(QObject *parent = nullptr);
|
||||||
explicit Database(const Database &other);
|
explicit Database(const Database &other);
|
||||||
explicit Database(const QSqlDatabase &other);
|
explicit Database(const QSqlDatabase &other);
|
||||||
~Database();
|
~Database();
|
||||||
|
|
@ -52,7 +54,7 @@ public:
|
||||||
bool open(bool updateDatabase);
|
bool open(bool updateDatabase);
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
QSqlQuery exec(QString sql);
|
QSqlQuery exec(const QString& sql);
|
||||||
|
|
||||||
int saveChanges(bool cleanUp = false);
|
int saveChanges(bool cleanUp = false);
|
||||||
void cleanUp();
|
void cleanUp();
|
||||||
|
|
@ -73,7 +75,8 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//remove minor version
|
//remove minor version
|
||||||
virtual void databaseUpdated(QString oldVersion, QString newVersion);
|
virtual void databaseCreated();
|
||||||
|
virtual void databaseUpdated(int oldVersion, int newVersion);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setDatabaseName(QString databaseName);
|
void setDatabaseName(QString databaseName);
|
||||||
|
|
|
||||||
|
|
@ -25,11 +25,12 @@
|
||||||
#include "databasemodel.h"
|
#include "databasemodel.h"
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QSharedData>
|
||||||
|
|
||||||
NUT_BEGIN_NAMESPACE
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class ChangeLogTable;
|
class ChangeLogTable;
|
||||||
class DatabasePrivate
|
class DatabasePrivate //: public QSharedData
|
||||||
{
|
{
|
||||||
Database *q_ptr;
|
Database *q_ptr;
|
||||||
Q_DECLARE_PUBLIC(Database)
|
Q_DECLARE_PUBLIC(Database)
|
||||||
|
|
@ -45,8 +46,6 @@ public:
|
||||||
DatabaseModel getLastScheema();
|
DatabaseModel getLastScheema();
|
||||||
bool getCurrectScheema();
|
bool getCurrectScheema();
|
||||||
|
|
||||||
// bool checkClassInfo(const QMetaClassInfo &classInfo,
|
|
||||||
// QString &type, QString &name, QString &value);
|
|
||||||
QSqlDatabase db;
|
QSqlDatabase db;
|
||||||
|
|
||||||
QString hostName;
|
QString hostName;
|
||||||
|
|
@ -62,14 +61,14 @@ public:
|
||||||
|
|
||||||
TableSet<ChangeLogTable> *changeLogs;
|
TableSet<ChangeLogTable> *changeLogs;
|
||||||
|
|
||||||
QT_DEPRECATED
|
|
||||||
QMap<QString, QString> tables;
|
|
||||||
static QMap<QString, DatabaseModel> allTableMaps;
|
static QMap<QString, DatabaseModel> allTableMaps;
|
||||||
static qulonglong lastId;
|
static qulonglong lastId;
|
||||||
|
|
||||||
QSet<TableSetBase *> tableSets;
|
QSet<TableSetBase *> tableSets;
|
||||||
|
|
||||||
bool isDatabaseNew;
|
bool isDatabaseNew;
|
||||||
|
|
||||||
|
QString errorMessage;
|
||||||
};
|
};
|
||||||
|
|
||||||
NUT_END_NAMESPACE
|
NUT_END_NAMESPACE
|
||||||
|
|
|
||||||
|
|
@ -31,13 +31,13 @@ QMap<QString, DatabaseModel*> DatabaseModel::_models;
|
||||||
#define NODE_VERSION "version"
|
#define NODE_VERSION "version"
|
||||||
#define NODE_TABLES "tables"
|
#define NODE_TABLES "tables"
|
||||||
DatabaseModel::DatabaseModel(const QString &name) :
|
DatabaseModel::DatabaseModel(const QString &name) :
|
||||||
QList<TableModel*>(), _databaseClassName(name), _version(QString())
|
QList<TableModel*>(), _databaseClassName(name), _version(0)
|
||||||
{
|
{
|
||||||
_models.insert(name, this);
|
_models.insert(name, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
DatabaseModel::DatabaseModel(const DatabaseModel &other) :
|
DatabaseModel::DatabaseModel(const DatabaseModel &other) :
|
||||||
QList<TableModel*>(other), _version(QString())
|
QList<TableModel*>(other), _version(0)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -45,7 +45,7 @@ DatabaseModel::DatabaseModel(const DatabaseModel &other) :
|
||||||
DatabaseModel::DatabaseModel(const QJsonObject &json) :
|
DatabaseModel::DatabaseModel(const QJsonObject &json) :
|
||||||
QList<TableModel*>()
|
QList<TableModel*>()
|
||||||
{
|
{
|
||||||
setVersion(json.value(NODE_VERSION).toString());
|
setVersion(json.value(NODE_VERSION).toInt());
|
||||||
|
|
||||||
QJsonObject tables = json.value(NODE_TABLES).toObject();
|
QJsonObject tables = json.value(NODE_TABLES).toObject();
|
||||||
foreach (QString key, tables.keys()) {
|
foreach (QString key, tables.keys()) {
|
||||||
|
|
@ -57,11 +57,7 @@ DatabaseModel::DatabaseModel(const QJsonObject &json) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DatabaseModel::~DatabaseModel()
|
TableModel *DatabaseModel::tableByName(const QString &tableName) const
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
TableModel *DatabaseModel::tableByName(QString tableName) const
|
|
||||||
{
|
{
|
||||||
for(int i = 0; i < size(); i++){
|
for(int i = 0; i < size(); i++){
|
||||||
TableModel *s = at(i);
|
TableModel *s = at(i);
|
||||||
|
|
@ -72,7 +68,7 @@ TableModel *DatabaseModel::tableByName(QString tableName) const
|
||||||
|
|
||||||
// qWarning("Table with name '%s' not found in model",
|
// qWarning("Table with name '%s' not found in model",
|
||||||
// qUtf8Printable(tableName));
|
// qUtf8Printable(tableName));
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
TableModel *DatabaseModel::tableByClassName(QString className) const
|
TableModel *DatabaseModel::tableByClassName(QString className) const
|
||||||
|
|
@ -86,7 +82,7 @@ TableModel *DatabaseModel::tableByClassName(QString className) const
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DatabaseModel::operator ==(const DatabaseModel &other) const
|
bool DatabaseModel::operator ==(const DatabaseModel &other) const
|
||||||
|
|
@ -108,19 +104,19 @@ bool DatabaseModel::operator ==(const DatabaseModel &other) const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
DatabaseModel DatabaseModel::operator +(const DatabaseModel &other)
|
//DatabaseModel DatabaseModel::operator +(const DatabaseModel &other)
|
||||||
{
|
//{
|
||||||
DatabaseModel model;
|
// DatabaseModel model;
|
||||||
DatabaseModel::const_iterator i;
|
// DatabaseModel::const_iterator i;
|
||||||
|
|
||||||
for (i = constBegin(); i != constEnd(); ++i)
|
// for (i = constBegin(); i != constEnd(); ++i)
|
||||||
model.append(*i);
|
// model.append(*i);
|
||||||
|
|
||||||
for (i = other.constBegin(); i != other.constEnd(); ++i)
|
// for (i = other.constBegin(); i != other.constEnd(); ++i)
|
||||||
model.append(*i);
|
// model.append(*i);
|
||||||
|
|
||||||
return model;
|
// return model;
|
||||||
}
|
//}
|
||||||
|
|
||||||
QJsonObject DatabaseModel::toJson() const
|
QJsonObject DatabaseModel::toJson() const
|
||||||
{
|
{
|
||||||
|
|
@ -148,13 +144,13 @@ RelationModel *DatabaseModel::relationByClassNames(const QString &masterClassNam
|
||||||
TableModel *childTable = tableByClassName(childClassName);
|
TableModel *childTable = tableByClassName(childClassName);
|
||||||
|
|
||||||
if(!childTable)
|
if(!childTable)
|
||||||
return 0;
|
return nullptr;
|
||||||
|
|
||||||
foreach (RelationModel *rel, childTable->foregionKeys())
|
foreach (RelationModel *rel, childTable->foregionKeys())
|
||||||
if(rel->masterClassName == masterClassName)
|
if(rel->masterClassName == masterClassName)
|
||||||
return rel;
|
return rel;
|
||||||
|
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
RelationModel *DatabaseModel::relationByTableNames(const QString &masterTableName, const QString &childTableName)
|
RelationModel *DatabaseModel::relationByTableNames(const QString &masterTableName, const QString &childTableName)
|
||||||
|
|
@ -162,20 +158,20 @@ RelationModel *DatabaseModel::relationByTableNames(const QString &masterTableNam
|
||||||
TableModel *childTable = tableByName(childTableName);
|
TableModel *childTable = tableByName(childTableName);
|
||||||
|
|
||||||
if(!childTable)
|
if(!childTable)
|
||||||
return 0;
|
return nullptr;
|
||||||
|
|
||||||
foreach (RelationModel *rel, childTable->foregionKeys())
|
foreach (RelationModel *rel, childTable->foregionKeys())
|
||||||
if(rel->masterTable->name() == masterTableName)
|
if(rel->masterTable->name() == masterTableName)
|
||||||
return rel;
|
return rel;
|
||||||
|
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
DatabaseModel DatabaseModel::fromJson(QJsonObject &json)
|
DatabaseModel DatabaseModel::fromJson(QJsonObject &json)
|
||||||
{
|
{
|
||||||
DatabaseModel model;
|
DatabaseModel model;
|
||||||
|
|
||||||
model.setVersion(json.value(NODE_VERSION).toString());
|
model.setVersion(json.value(NODE_VERSION).toInt());
|
||||||
|
|
||||||
QJsonObject tables = json.value(NODE_TABLES).toObject();
|
QJsonObject tables = json.value(NODE_TABLES).toObject();
|
||||||
foreach (QString key, tables.keys()) {
|
foreach (QString key, tables.keys()) {
|
||||||
|
|
@ -188,12 +184,12 @@ DatabaseModel DatabaseModel::fromJson(QJsonObject &json)
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString DatabaseModel::version() const
|
int DatabaseModel::version() const
|
||||||
{
|
{
|
||||||
return _version;
|
return _version;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseModel::setVersion(QString version)
|
void DatabaseModel::setVersion(int version)
|
||||||
{
|
{
|
||||||
_version = version;
|
_version = version;
|
||||||
}
|
}
|
||||||
|
|
@ -236,7 +232,44 @@ void DatabaseModel::deleteAllModels()
|
||||||
// qDeleteAll(i.value());
|
// qDeleteAll(i.value());
|
||||||
}
|
}
|
||||||
// qDeleteAll(_models.values());
|
// qDeleteAll(_models.values());
|
||||||
_models.clear();
|
_models.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
DatabaseModel operator +(const DatabaseModel &l, const DatabaseModel &r)
|
||||||
|
{
|
||||||
|
DatabaseModel model;
|
||||||
|
DatabaseModel::const_iterator i;
|
||||||
|
|
||||||
|
for (i = r.constBegin(); i != r.constEnd(); ++i)
|
||||||
|
model.append(*i);
|
||||||
|
|
||||||
|
for (i = l.constBegin(); i != l.constEnd(); ++i)
|
||||||
|
model.append(*i);
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
DatabaseModel operator |(const DatabaseModel &l, const DatabaseModel &r)
|
||||||
|
{
|
||||||
|
DatabaseModel ret;
|
||||||
|
DatabaseModel::const_iterator i;
|
||||||
|
QSet<QString> tables;
|
||||||
|
|
||||||
|
for (i = r.constBegin(); i != r.constEnd(); ++i) {
|
||||||
|
if (tables.contains((*i)->name()))
|
||||||
|
continue;
|
||||||
|
ret.append(*i);
|
||||||
|
tables.insert((*i)->name());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = l.constBegin(); i != l.constEnd(); ++i) {
|
||||||
|
if (tables.contains((*i)->name()))
|
||||||
|
continue;
|
||||||
|
ret.append(*i);
|
||||||
|
tables.insert((*i)->name());
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
NUT_END_NAMESPACE
|
NUT_END_NAMESPACE
|
||||||
|
|
|
||||||
|
|
@ -36,16 +36,16 @@ struct RelationModel;
|
||||||
class DatabaseModel : public QList<TableModel *>
|
class DatabaseModel : public QList<TableModel *>
|
||||||
{
|
{
|
||||||
QString _databaseClassName;
|
QString _databaseClassName;
|
||||||
QString _version;
|
int _version;
|
||||||
static QMap<QString, DatabaseModel *> _models;
|
static QMap<QString, DatabaseModel *> _models;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DatabaseModel(const QString &name = QString());
|
DatabaseModel(const QString &name = QString());
|
||||||
DatabaseModel(const DatabaseModel &other);
|
DatabaseModel(const DatabaseModel &other);
|
||||||
DatabaseModel(const QJsonObject &json);
|
DatabaseModel(const QJsonObject &json);
|
||||||
~DatabaseModel();
|
~DatabaseModel() = default;
|
||||||
|
|
||||||
TableModel *tableByName(QString tableName) const;
|
TableModel *tableByName(const QString &tableName) const;
|
||||||
TableModel *tableByClassName(QString className) const;
|
TableModel *tableByClassName(QString className) const;
|
||||||
|
|
||||||
RelationModel *relationByClassNames(const QString &masterClassName,
|
RelationModel *relationByClassNames(const QString &masterClassName,
|
||||||
|
|
@ -54,15 +54,15 @@ public:
|
||||||
const QString &childClassName);
|
const QString &childClassName);
|
||||||
|
|
||||||
bool operator==(const DatabaseModel &other) const;
|
bool operator==(const DatabaseModel &other) const;
|
||||||
DatabaseModel operator +(const DatabaseModel &other);
|
// DatabaseModel operator +(const DatabaseModel &other);
|
||||||
|
|
||||||
Q_DECL_DEPRECATED
|
Q_DECL_DEPRECATED
|
||||||
static DatabaseModel fromJson(QJsonObject &json);
|
static DatabaseModel fromJson(QJsonObject &json);
|
||||||
QJsonObject toJson() const;
|
QJsonObject toJson() const;
|
||||||
operator QJsonObject();
|
operator QJsonObject();
|
||||||
|
|
||||||
QString version() const;
|
int version() const;
|
||||||
void setVersion(QString version);
|
void setVersion(int version);
|
||||||
|
|
||||||
bool remove(const QString &tableName);
|
bool remove(const QString &tableName);
|
||||||
|
|
||||||
|
|
@ -73,6 +73,9 @@ public:
|
||||||
static void deleteAllModels();
|
static void deleteAllModels();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
DatabaseModel operator +(const DatabaseModel &l, const DatabaseModel &r);
|
||||||
|
DatabaseModel operator |(const DatabaseModel &l, const DatabaseModel &r);
|
||||||
|
|
||||||
NUT_END_NAMESPACE
|
NUT_END_NAMESPACE
|
||||||
|
|
||||||
#endif // DATABASEMODEL_H
|
#endif // DATABASEMODEL_H
|
||||||
|
|
|
||||||
186
src/defines.h
186
src/defines.h
|
|
@ -45,6 +45,83 @@
|
||||||
Q_CLASSINFO(__nut_NAME_PERFIX type #name #value, \
|
Q_CLASSINFO(__nut_NAME_PERFIX type #name #value, \
|
||||||
type "\n" #name "\n" value)
|
type "\n" #name "\n" value)
|
||||||
|
|
||||||
|
#define NUT_FIELD_PERFIX
|
||||||
|
#define NUT_FIELD_POSTFIX Field
|
||||||
|
|
||||||
|
// Database
|
||||||
|
#define NUT_DB_VERSION(version) \
|
||||||
|
NUT_INFO(__nut_DB_VERSION, version, 0)
|
||||||
|
|
||||||
|
#define NUT_DECLARE_TABLE(type, name) \
|
||||||
|
NUT_INFO(__nut_TABLE, type, name) \
|
||||||
|
Q_PROPERTY(NUT_WRAP_NAMESPACE(TableSet<type>) name READ name) \
|
||||||
|
NUT_WRAP_NAMESPACE(TableSet<type>) *m_##name; \
|
||||||
|
public: \
|
||||||
|
static const type *_##name; \
|
||||||
|
NUT_WRAP_NAMESPACE(TableSet<type>) *name() const \
|
||||||
|
{ return m_##name; } \
|
||||||
|
private:
|
||||||
|
|
||||||
|
//Table
|
||||||
|
#define NUT_DECLARE_FIELD(type, name, read, write) \
|
||||||
|
Q_PROPERTY(type name READ read WRITE write) \
|
||||||
|
NUT_INFO(__nut_FIELD, name, 0) \
|
||||||
|
type m_##name; \
|
||||||
|
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; \
|
||||||
|
} \
|
||||||
|
type read() const{ \
|
||||||
|
return m_##name; \
|
||||||
|
} \
|
||||||
|
void write(type name){ \
|
||||||
|
m_##name = name; \
|
||||||
|
propertyChanged(#name); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define NUT_FOREGION_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_FOREGION_KEY, name, type) \
|
||||||
|
Nut::Row<type> m_##name; \
|
||||||
|
public: \
|
||||||
|
Nut::Row<type> read() const { return m_##name ; } \
|
||||||
|
void write(Nut::Row<type> name){ \
|
||||||
|
m_##name = name; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define NUT_DECLARE_CHILD_TABLE(type, n) \
|
||||||
|
private: \
|
||||||
|
NUT_WRAP_NAMESPACE(TableSet)<type> *m_##n; \
|
||||||
|
public: \
|
||||||
|
static type *n##Table(); \
|
||||||
|
NUT_WRAP_NAMESPACE(TableSet)<type> *n();
|
||||||
|
|
||||||
|
#define NUT_IMPLEMENT_CHILD_TABLE(class, type, n) \
|
||||||
|
type *class::n##Table(){ \
|
||||||
|
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)
|
||||||
|
#define NUT_AUTO_INCREMENT(x) NUT_INFO(__nut_AUTO_INCREMENT, x, 0)
|
||||||
|
#define NUT_PRIMARY_AUTO_INCREMENT(x) NUT_INFO(__nut_PRIMARY_KEY_AI, x, 0)
|
||||||
|
#define NUT_DISPLAY_NAME(field, name) NUT_INFO(__nut_DISPLAY, field, name)
|
||||||
|
#define NUT_UNIQUE(x) NUT_INFO(__nut_UNIQUE, x, 0)
|
||||||
|
#define NUT_LEN(field, len) NUT_INFO(__nut_LEN, field, len)
|
||||||
|
#define NUT_DEFAULT_VALUE(x, n) NUT_INFO(__nut_DEFAULT_VALUE, x, n)
|
||||||
|
#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,
|
inline bool nutClassInfo(const QMetaClassInfo &classInfo,
|
||||||
QString &type, QString &name, QVariant &value)
|
QString &type, QString &name, QVariant &value)
|
||||||
{
|
{
|
||||||
|
|
@ -117,76 +194,57 @@ inline bool nutClassInfoInt(const QMetaClassInfo &classInfo,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef NUT_SHARED_POINTER
|
||||||
|
template <class T>
|
||||||
|
using RowList = QList<QSharedPointer<T>>;
|
||||||
|
|
||||||
// Database
|
template <class T>
|
||||||
#define NUT_DB_VERSION(version) \
|
using RowSet = QSet<QSharedPointer<T>>;
|
||||||
NUT_INFO(__nut_DB_VERSION, version, 0)
|
|
||||||
|
|
||||||
#define NUT_DECLARE_TABLE(type, name) \
|
template <typename T>
|
||||||
NUT_INFO(__nut_TABLE, type, name) \
|
using Row = QSharedPointer<T>;
|
||||||
Q_PROPERTY(NUT_WRAP_NAMESPACE(TableSet<type>) name READ name) \
|
|
||||||
NUT_WRAP_NAMESPACE(TableSet<type>) *m_##name; \
|
|
||||||
public: \
|
|
||||||
static const type *_##name; \
|
|
||||||
NUT_WRAP_NAMESPACE(TableSet<type>) *name() const \
|
|
||||||
{ return m_##name; } \
|
|
||||||
private:
|
|
||||||
|
|
||||||
//Table
|
template<class T>
|
||||||
#define NUT_DECLARE_FIELD(type, name, read, write) \
|
inline Row<T> create() {
|
||||||
Q_PROPERTY(type name READ read WRITE write) \
|
return QSharedPointer<T>(new T);
|
||||||
NUT_INFO(__nut_FIELD, name, 0) \
|
}
|
||||||
type m_##name; \
|
|
||||||
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; \
|
|
||||||
} \
|
|
||||||
type read() const{ \
|
|
||||||
return m_##name; \
|
|
||||||
} \
|
|
||||||
void write(type name){ \
|
|
||||||
m_##name = name; \
|
|
||||||
propertyChanged(#name); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define NUT_FOREGION_KEY(type, keytype, name, read, write) \
|
template<class T>
|
||||||
Q_PROPERTY(type* name READ read WRITE write) \
|
inline T *get(T *row) {
|
||||||
NUT_DECLARE_FIELD(keytype, name##Id, read##Id, write##Id) \
|
return row;
|
||||||
NUT_INFO(__nut_FOREGION_KEY, name, type) \
|
}
|
||||||
type *m_##name; \
|
template<class T>
|
||||||
public: \
|
inline T *get(const QSharedPointer<T> row) {
|
||||||
type *read() const { return m_##name ; } \
|
return row.data();
|
||||||
void write(type *name){ \
|
}
|
||||||
m_##name = name; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define NUT_DECLARE_CHILD_TABLE(type, n) \
|
#else
|
||||||
private: \
|
template <typename T>
|
||||||
NUT_WRAP_NAMESPACE(TableSet)<type> *m_##n; \
|
using RowList = QList<T*>;
|
||||||
public: \
|
|
||||||
static type *n##Table(); \
|
|
||||||
NUT_WRAP_NAMESPACE(TableSet)<type> *n();
|
|
||||||
|
|
||||||
#define NUT_IMPLEMENT_CHILD_TABLE(class, type, n) \
|
template <typename T>
|
||||||
type *class::n##Table(){ \
|
using RowSet = QSet<T*>;
|
||||||
static type *f = new type(); \
|
|
||||||
return f; \
|
|
||||||
} \
|
|
||||||
NUT_WRAP_NAMESPACE(TableSet)<type> *class::n(){ \
|
|
||||||
return m_##n; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define NUT_PRIMARY_KEY(x) NUT_INFO(__nut_PRIMARY_KEY, x, 0)
|
template <typename T>
|
||||||
#define NUT_AUTO_INCREMENT(x) NUT_INFO(__nut_AUTO_INCREMENT, x, 0)
|
using Row = T*;
|
||||||
#define NUT_PRIMARY_AUTO_INCREMENT(x) NUT_INFO(__nut_PRIMARY_KEY_AI, x, 0)
|
|
||||||
#define NUT_DISPLAY_NAME(field, name) NUT_INFO(__nut_DISPLAY, field, name)
|
template<class T>
|
||||||
#define NUT_UNIQUE(x) NUT_INFO(__nut_UNIQUE, x, 0)
|
inline Row<T> create() {
|
||||||
#define NUT_LEN(field, len) NUT_INFO(__nut_LEN, field, len)
|
return new T;
|
||||||
#define NUT_DEFAULT_VALUE(x, n) NUT_INFO(__nut_DEFAULT_VALUE, x, n)
|
}
|
||||||
#define NUT_NOT_NULL(x) NUT_INFO(__nut_NOT_NULL, x, 1)
|
|
||||||
#define NUT_INDEX(name, field, order)
|
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 // SYNTAX_DEFINES_H
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,15 @@
|
||||||
|
|
||||||
#include <QPoint>
|
#include <QPoint>
|
||||||
#include <QPointF>
|
#include <QPointF>
|
||||||
|
#include <QTime>
|
||||||
|
#include <QDate>
|
||||||
|
#include <QDateTime>
|
||||||
|
#ifdef QT_GUI_LIB
|
||||||
|
#include <QPolygon>
|
||||||
|
#include <QPolygonF>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "sqlserializer.h"
|
||||||
|
|
||||||
NUT_BEGIN_NAMESPACE
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
|
@ -36,52 +45,71 @@ QString MySqlGenerator::fieldType(FieldModel *field)
|
||||||
QString dbType;
|
QString dbType;
|
||||||
|
|
||||||
switch (field->type) {
|
switch (field->type) {
|
||||||
case QVariant::Bool:
|
case QMetaType::Bool: return "BOOLEAN";
|
||||||
dbType = "BOOLEAN";
|
case QMetaType::Char:
|
||||||
break;
|
case QMetaType::QChar: return "CHAR(1)";
|
||||||
case QVariant::ByteArray:
|
case QMetaType::SChar:
|
||||||
dbType = "BLOB";
|
case QMetaType::UChar: return "TINYINT";
|
||||||
break;
|
case QMetaType::Short:
|
||||||
case QVariant::DateTime:
|
case QMetaType::UShort: return "SMALLINT";
|
||||||
dbType = "DATETIME";
|
case QMetaType::UInt:
|
||||||
break;
|
case QMetaType::Int:
|
||||||
|
dbType = "INT";
|
||||||
case QVariant::Date:
|
|
||||||
dbType = "DATE";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case QVariant::Time:
|
|
||||||
dbType = "TIME";
|
|
||||||
break;
|
|
||||||
case QVariant::Double:
|
|
||||||
dbType = "REAL";
|
|
||||||
break;
|
|
||||||
case QVariant::Int:
|
|
||||||
dbType = "INT(4)";
|
|
||||||
if(field->isAutoIncrement)
|
if(field->isAutoIncrement)
|
||||||
dbType += " AUTO_INCREMENT";
|
dbType += " AUTO_INCREMENT";
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case QVariant::String:
|
case QMetaType::Long:
|
||||||
|
case QMetaType::ULong:
|
||||||
|
case QMetaType::LongLong:
|
||||||
|
case QMetaType::ULongLong:
|
||||||
|
return "BIGINT";
|
||||||
|
|
||||||
|
case QMetaType::Float:
|
||||||
|
return "FLOAT";
|
||||||
|
|
||||||
|
case QMetaType::Double:
|
||||||
|
return "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::QString:
|
||||||
if(field->length)
|
if(field->length)
|
||||||
dbType = QString("VARCHAR(%1)").arg(field->length);
|
dbType = QString("VARCHAR(%1)").arg(field->length);
|
||||||
else
|
else
|
||||||
dbType = "TEXT";
|
dbType = "TEXT";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QVariant::Point:
|
|
||||||
case QVariant::PointF:
|
|
||||||
dbType = "POINT";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case QVariant::Polygon:
|
case QMetaType::QPolygon:
|
||||||
case QVariant::PolygonF:
|
case QMetaType::QPolygonF:
|
||||||
dbType = "POLYGON";
|
// dbType = "POLYGON";
|
||||||
break;
|
// break;
|
||||||
|
|
||||||
case QVariant::Uuid:
|
case QMetaType::QUuid:
|
||||||
dbType = "VARCHAR(64)";
|
// dbType = "VARCHAR(64)";
|
||||||
break;
|
// break;
|
||||||
|
|
||||||
|
case QMetaType::QPoint:
|
||||||
|
case QMetaType::QPointF:
|
||||||
|
// dbType = "POINT";
|
||||||
|
// break;
|
||||||
|
case QMetaType::QSize:
|
||||||
|
case QMetaType::QSizeF:
|
||||||
|
case QMetaType::QRect:
|
||||||
|
case QMetaType::QRectF:
|
||||||
|
case QMetaType::QLine:
|
||||||
|
case QMetaType::QLineF:
|
||||||
|
case QMetaType::QColor:
|
||||||
|
case QMetaType::QUrl:
|
||||||
|
case QMetaType::QJsonArray:
|
||||||
|
case QMetaType::QJsonValue:
|
||||||
|
case QMetaType::QJsonObject:
|
||||||
|
case QMetaType::QJsonDocument:
|
||||||
|
case QMetaType::QStringList: return "TEXT";
|
||||||
|
|
||||||
default:
|
default:
|
||||||
qWarning("Type %s::%s(%d) is not supported",
|
qWarning("Type %s::%s(%d) is not supported",
|
||||||
|
|
@ -91,38 +119,146 @@ QString MySqlGenerator::fieldType(FieldModel *field)
|
||||||
dbType = QString();
|
dbType = QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(field->typeName == QStringLiteral("Nut::DbGeography"))
|
// if(field->typeName == QStringLiteral("Nut::DbGeography"))
|
||||||
dbType = "GEOMETRY";
|
// dbType = "GEOMETRY";
|
||||||
|
|
||||||
return dbType;
|
return dbType;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString MySqlGenerator::escapeValue(const QVariant &v) const
|
QString MySqlGenerator::escapeValue(const QVariant &v) const
|
||||||
{
|
{
|
||||||
switch (v.type()) {
|
if (v.type() == QVariant::Bool)
|
||||||
case QVariant::Point: {
|
return v.toBool() ? "1" : "0";
|
||||||
QPoint pt = v.toPoint();
|
|
||||||
return QString("GeomFromText('POINT(%1 %2)',0)").arg(pt.x()).arg(pt.y());
|
|
||||||
}
|
|
||||||
|
|
||||||
case QVariant::PointF: {
|
if (v.type() == QVariant::Time)
|
||||||
QPointF pt = v.toPointF();
|
return "'" + v.toTime().toString("HH:mm:ss") + "'";
|
||||||
return QString("GeomFromText('POINT(%1 %2)',0)").arg(pt.x()).arg(pt.y());
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
if (v.type() == QVariant::Date)
|
||||||
|
return "'" + v.toDate().toString("yyyy-MM-dd") + "'";
|
||||||
|
|
||||||
|
if (v.type() == QVariant::DateTime)
|
||||||
|
return "'" + v.toDateTime().toString("yyyy-MM-dd HH:mm:ss") + "'";
|
||||||
|
|
||||||
|
//#ifdef QT_GUI_LIB
|
||||||
|
// if (v.type() == QVariant::Polygon) {
|
||||||
|
// QString ret;
|
||||||
|
// QPoint pt;
|
||||||
|
// QPolygon pol = v.value<QPolygon>();
|
||||||
|
// 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()));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return "GeomFromText('POLYGON(" + ret + "))')";
|
||||||
|
// }
|
||||||
|
// if (v.type() == QVariant::PolygonF) {
|
||||||
|
// QString ret;
|
||||||
|
// QPointF pt;
|
||||||
|
// QPolygonF pol = v.value<QPolygonF>();
|
||||||
|
// 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()));
|
||||||
|
// }
|
||||||
|
// return "GeomFromText('POLYGON(" + ret + "))')";
|
||||||
|
// }
|
||||||
|
//#endif
|
||||||
|
// switch (v.type()) {
|
||||||
|
// case QMetaType::QPoint: {
|
||||||
|
// QPoint pt = v.toPoint();
|
||||||
|
// return QString("GeomFromText('POINT(%1 %2)',0)").arg(pt.x()).arg(pt.y());
|
||||||
|
// }
|
||||||
|
|
||||||
|
// case QMetaType::QPointF: {
|
||||||
|
// QPointF pt = v.toPointF();
|
||||||
|
// return QString("GeomFromText('POINT(%1 %2)',0)").arg(pt.x()).arg(pt.y());
|
||||||
|
// }
|
||||||
|
|
||||||
|
// default:
|
||||||
return SqlGeneratorBase::escapeValue(v);
|
return SqlGeneratorBase::escapeValue(v);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant MySqlGenerator::readValue(const QVariant::Type &type, const QVariant &dbValue)
|
QVariant MySqlGenerator::unescapeValue(const QMetaType::Type &type, const QVariant &dbValue)
|
||||||
{
|
{
|
||||||
if (type == QVariant::PointF) {
|
|
||||||
qDebug() << "QVariant::PointF" << dbValue;
|
//#ifdef QT_GUI_LIB
|
||||||
}
|
// if (type == QMetaType::QPolygon) {
|
||||||
return SqlGeneratorBase::readValue(type, dbValue);
|
// qDebug() << "p=" << dbValue;
|
||||||
|
// QString p;
|
||||||
|
// QString ref = dbValue.toString();
|
||||||
|
// QPolygon pol;
|
||||||
|
// if (!readInsideParentese(ref, p))
|
||||||
|
// return pol;
|
||||||
|
// QStringList parts = p.split(",");
|
||||||
|
// foreach (QString v, parts) {
|
||||||
|
// QList<int> l = _serializer->toListInt(p.trimmed(), " ");
|
||||||
|
// if (l.count() != 2)
|
||||||
|
// return QPolygon();
|
||||||
|
// pol.append(QPoint(l.at(0), l.at(1)));
|
||||||
|
// }
|
||||||
|
// return pol;
|
||||||
|
// }
|
||||||
|
// if (type == QMetaType::QPolygonF) {
|
||||||
|
// QString p;
|
||||||
|
// QString ref = dbValue.toString();
|
||||||
|
// QPolygonF pol;
|
||||||
|
// if (!readInsideParentese(ref, p))
|
||||||
|
// return pol;
|
||||||
|
|
||||||
|
// QStringList parts = p.split(",");
|
||||||
|
// foreach (QString v, parts) {
|
||||||
|
// QList<qreal> l = _serializer->toListReal(p.trimmed(), " ");
|
||||||
|
// if (l.count() != 2)
|
||||||
|
// return QPolygonF();
|
||||||
|
// pol.append(QPointF(l.at(0), l.at(1)));
|
||||||
|
// }
|
||||||
|
// return pol;
|
||||||
|
// }
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
if (type == QMetaType::QDateTime)
|
||||||
|
return dbValue.toDateTime();
|
||||||
|
|
||||||
|
if (type == QMetaType::QTime)
|
||||||
|
return dbValue.toTime();
|
||||||
|
|
||||||
|
if (type == QMetaType::QDate)
|
||||||
|
return dbValue.toDate();
|
||||||
|
|
||||||
|
return SqlGeneratorBase::unescapeValue(type, dbValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MySqlGenerator::readInsideParentese(QString &text, QString &out)
|
||||||
|
{
|
||||||
|
int start = -1;
|
||||||
|
int end = -1;
|
||||||
|
int pc = 0;
|
||||||
|
for (int i = 0; i < text.length(); ++i) {
|
||||||
|
QChar ch = text.at(i);
|
||||||
|
|
||||||
|
if (ch == '(') {
|
||||||
|
if (start == -1)
|
||||||
|
start = i;
|
||||||
|
pc++;
|
||||||
|
}
|
||||||
|
if (ch == ')') {
|
||||||
|
pc--;
|
||||||
|
|
||||||
|
if (!pc && end == -1)
|
||||||
|
end = i;
|
||||||
|
}
|
||||||
|
if (start != -1 && end != -1){
|
||||||
|
out = text.mid(start + 1, end - start - 1);
|
||||||
|
text = text.mid(end + 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
//QString MySqlGenerator::phrase(const PhraseData *d) const
|
//QString MySqlGenerator::phrase(const PhraseData *d) const
|
||||||
//{
|
//{
|
||||||
// if (d->operatorCond == PhraseData::Distance) {
|
// if (d->operatorCond == PhraseData::Distance) {
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,11 @@ public:
|
||||||
|
|
||||||
QString fieldType(FieldModel *field);
|
QString fieldType(FieldModel *field);
|
||||||
QString escapeValue(const QVariant &v) const;
|
QString escapeValue(const QVariant &v) const;
|
||||||
QVariant readValue(const QVariant::Type &type, const QVariant &dbValue);
|
QVariant unescapeValue(const QMetaType::Type &type, const QVariant &dbValue);
|
||||||
// QString phrase(const PhraseData *d) const;
|
// QString phrase(const PhraseData *d) const;
|
||||||
// QString selectCommand(AgregateType t, QString agregateArg, QString tableName, QList<WherePhrase> &wheres, QList<WherePhrase> &orders, QList<RelationModel *> joins, int skip, int take);
|
// QString selectCommand(AgregateType t, QString agregateArg, QString tableName, QList<WherePhrase> &wheres, QList<WherePhrase> &orders, QList<RelationModel *> joins, int skip, int take);
|
||||||
|
private:
|
||||||
|
bool readInsideParentese(QString &text, QString &out);
|
||||||
};
|
};
|
||||||
|
|
||||||
NUT_END_NAMESPACE
|
NUT_END_NAMESPACE
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,60 @@
|
||||||
**
|
**
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QPoint>
|
||||||
|
#ifdef QT_GUI_LIB
|
||||||
|
#include <QPolygon>
|
||||||
|
#include <QPolygonF>
|
||||||
|
#endif
|
||||||
|
#include <QVariant>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
|
||||||
#include "postgresqlgenerator.h"
|
#include "postgresqlgenerator.h"
|
||||||
#include "../table.h"
|
#include "../table.h"
|
||||||
#include "../tablemodel.h"
|
#include "../tablemodel.h"
|
||||||
|
#include "sqlserializer.h"
|
||||||
|
|
||||||
NUT_BEGIN_NAMESPACE
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
bool PostgreSqlGenerator::readInsideParentese(QString &text, QString &out)
|
||||||
|
{
|
||||||
|
int start = -1;
|
||||||
|
int end = -1;
|
||||||
|
int pc = 0;
|
||||||
|
for (int i = 0; i < text.length(); ++i) {
|
||||||
|
QChar ch = text.at(i);
|
||||||
|
|
||||||
|
if (ch == '(') {
|
||||||
|
if (start == -1)
|
||||||
|
start = i;
|
||||||
|
pc++;
|
||||||
|
}
|
||||||
|
if (ch == ')') {
|
||||||
|
pc--;
|
||||||
|
|
||||||
|
if (!pc && end == -1)
|
||||||
|
end = i;
|
||||||
|
}
|
||||||
|
if (start != -1 && end != -1){
|
||||||
|
out = text.mid(start + 1, end - start - 1);
|
||||||
|
text = text.mid(end + 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PostgreSqlGenerator::isPostGisType(const QVariant::Type &t) const
|
||||||
|
{
|
||||||
|
return t == QVariant::Point
|
||||||
|
|| t == QVariant::PointF
|
||||||
|
|| t == QVariant::Rect
|
||||||
|
|| t == QVariant::RectF
|
||||||
|
|| t == QVariant::Polygon
|
||||||
|
|| t == QVariant::PolygonF;
|
||||||
|
}
|
||||||
|
|
||||||
PostgreSqlGenerator::PostgreSqlGenerator(Database *parent) : SqlGeneratorBase (parent)
|
PostgreSqlGenerator::PostgreSqlGenerator(Database *parent) : SqlGeneratorBase (parent)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
@ -34,70 +82,109 @@ QString PostgreSqlGenerator::fieldType(FieldModel *field)
|
||||||
QString dbType;
|
QString dbType;
|
||||||
|
|
||||||
switch (field->type) {
|
switch (field->type) {
|
||||||
case QVariant::Bool:
|
case QMetaType::Bool:
|
||||||
dbType = "BOOLEAN";
|
dbType = "BOOLEAN";
|
||||||
break;
|
break;
|
||||||
case QVariant::ByteArray:
|
|
||||||
|
case QMetaType::QBitArray:
|
||||||
|
case QMetaType::QByteArray:
|
||||||
dbType = "BYTEA";
|
dbType = "BYTEA";
|
||||||
break;
|
break;
|
||||||
case QVariant::Date:
|
case QMetaType::QDate:
|
||||||
dbType = "DATE";
|
dbType = "DATE";
|
||||||
break;
|
break;
|
||||||
case QVariant::DateTime:
|
case QMetaType::QDateTime:
|
||||||
dbType = "TIMESTAMP";
|
dbType = "TIMESTAMP";
|
||||||
break;
|
break;
|
||||||
case QVariant::Time:
|
case QMetaType::QTime:
|
||||||
dbType = "TIME";
|
dbType = "TIME";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QVariant::Int:
|
case QMetaType::SChar:
|
||||||
case QVariant::UInt:
|
case QMetaType::UChar:
|
||||||
|
case QMetaType::Short:
|
||||||
|
case QMetaType::UShort:
|
||||||
|
dbType = "SMALLINT";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QMetaType::Float:
|
||||||
|
dbType = "FLOAT";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QMetaType::Double:
|
||||||
|
dbType = "REAL";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QMetaType::Int:
|
||||||
|
case QMetaType::UInt:
|
||||||
if(field->isAutoIncrement)
|
if(field->isAutoIncrement)
|
||||||
dbType = "SERIAL";
|
dbType = "SERIAL";
|
||||||
else
|
else
|
||||||
dbType = "INTEGER";
|
dbType = "INTEGER";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QVariant::ULongLong:
|
case QMetaType::Long:
|
||||||
case QVariant::LongLong:
|
case QMetaType::ULong:
|
||||||
|
case QMetaType::LongLong:
|
||||||
|
case QMetaType::ULongLong:
|
||||||
if(field->isAutoIncrement)
|
if(field->isAutoIncrement)
|
||||||
dbType = "BIGSERIAL";
|
dbType = "BIGSERIAL";
|
||||||
else
|
else
|
||||||
dbType = "BIGINT";
|
dbType = "BIGINT";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QVariant::Double:
|
case QMetaType::Char:
|
||||||
dbType = "REAL";
|
case QMetaType::QChar:
|
||||||
break;
|
return "CHAR(1)";
|
||||||
case QVariant::String:
|
|
||||||
|
case QMetaType::QString:
|
||||||
if(field->length)
|
if(field->length)
|
||||||
dbType = QString("VARCHAR(%1)").arg(field->length);
|
dbType = QString("VARCHAR(%1)").arg(field->length);
|
||||||
else
|
else
|
||||||
dbType = "TEXT";
|
dbType = "TEXT";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QVariant::Point:
|
case QMetaType::QPoint:
|
||||||
case QVariant::PointF:
|
case QMetaType::QPointF:
|
||||||
dbType="POINT";
|
dbType="POINT";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QVariant::Uuid:
|
case QMetaType::QUuid:
|
||||||
dbType = "UUID";
|
dbType = "UUID";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QVariant::Polygon:
|
case QMetaType::QPolygon:
|
||||||
case QVariant::PolygonF:
|
case QMetaType::QPolygonF:
|
||||||
dbType = "POLYGON";
|
dbType = "POLYGON";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case QMetaType::QLine:
|
||||||
|
case QMetaType::QLineF:
|
||||||
|
return "LINE";
|
||||||
|
|
||||||
|
case QMetaType::QRect:
|
||||||
|
case QMetaType::QRectF:
|
||||||
|
return "BOX";
|
||||||
|
|
||||||
|
case QMetaType::QJsonArray:
|
||||||
|
case QMetaType::QJsonValue:
|
||||||
|
case QMetaType::QJsonObject:
|
||||||
|
case QMetaType::QJsonDocument:
|
||||||
|
return "JSON";
|
||||||
|
|
||||||
|
case QMetaType::QStringList:
|
||||||
|
return "TEXT[]";
|
||||||
|
|
||||||
|
case QMetaType::QSize:
|
||||||
|
case QMetaType::QSizeF:
|
||||||
|
case QMetaType::QUrl:
|
||||||
|
case QMetaType::QColor:
|
||||||
|
return "TEXT";
|
||||||
|
|
||||||
default:
|
default:
|
||||||
qDebug() << "Type for " << (int)field->type << field->type << "(" << QMetaType::typeName(field->type) << ")" << "nut supported";
|
|
||||||
dbType = QString();
|
dbType = QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(field->type == (unsigned)QMetaType::type("Nut::DbGeography"))
|
|
||||||
dbType = "GEOGRAPHY";
|
|
||||||
|
|
||||||
return dbType;
|
return dbType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -122,11 +209,134 @@ QString PostgreSqlGenerator::diff(FieldModel *oldField, FieldModel *newField)
|
||||||
return sql;
|
return sql;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PostgreSqlGenerator::replaceTableNames(QString &command)
|
QString PostgreSqlGenerator::escapeValue(const QVariant &v) const
|
||||||
{
|
{
|
||||||
foreach (TableModel *m, TableModel::allModels())
|
if (v.type() == QVariant::Time)
|
||||||
command = command
|
return "'" + v.toTime().toString("HH:mm:ss") + "'";
|
||||||
.replace("[" + m->className() + "]", m->name() );
|
|
||||||
|
if (v.type() == QVariant::Date)
|
||||||
|
return "'" + v.toDate().toString("yyyy-MM-dd") + "'";
|
||||||
|
|
||||||
|
if (v.type() == QVariant::DateTime)
|
||||||
|
return "'" + v.toDateTime().toString("yyyy-MM-dd HH:mm:ss") + "'";
|
||||||
|
|
||||||
|
if (v.type() == QVariant::StringList)
|
||||||
|
return "'{" + v.toStringList().join(",") + "}'";
|
||||||
|
|
||||||
|
if (v.type() == QVariant::Point) {
|
||||||
|
QPoint pt = v.toPoint();
|
||||||
|
return QString("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());
|
||||||
|
}
|
||||||
|
if (v.userType() == QMetaType::QJsonDocument) {
|
||||||
|
return "'" + QString(v.toJsonDocument().toJson(QJsonDocument::Compact)) + "'";
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef QT_GUI_LIB
|
||||||
|
if (v.type() == QVariant::Polygon) {
|
||||||
|
QString ret;
|
||||||
|
QPoint pt;
|
||||||
|
QPolygon pol = v.value<QPolygon>();
|
||||||
|
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()));
|
||||||
|
}
|
||||||
|
return "'((" + ret + "))'";
|
||||||
|
}
|
||||||
|
if (v.type() == QVariant::PolygonF) {
|
||||||
|
QString ret;
|
||||||
|
QPointF pt;
|
||||||
|
QPolygonF pol = v.value<QPolygonF>();
|
||||||
|
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()));
|
||||||
|
}
|
||||||
|
return "'((" + ret + "))'";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return SqlGeneratorBase::escapeValue(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant PostgreSqlGenerator::unescapeValue(const QMetaType::Type &type, const QVariant &dbValue)
|
||||||
|
{
|
||||||
|
if (type == QMetaType::QDateTime)
|
||||||
|
return dbValue.toDateTime();
|
||||||
|
|
||||||
|
if (type == QMetaType::QTime)
|
||||||
|
return dbValue.toTime();
|
||||||
|
|
||||||
|
if (type == QMetaType::QDate)
|
||||||
|
return dbValue.toDate();
|
||||||
|
|
||||||
|
if (type == QMetaType::QPoint)
|
||||||
|
return SqlGeneratorBase::unescapeValue(QMetaType::QPoint, dbValue.toString()
|
||||||
|
.replace("(", "").replace(")", ""));
|
||||||
|
if (type == QMetaType::QPointF)
|
||||||
|
return SqlGeneratorBase::unescapeValue(QMetaType::QPointF, dbValue.toString()
|
||||||
|
.replace("(", "").replace(")", ""));
|
||||||
|
if (type == QMetaType::QStringList)
|
||||||
|
return dbValue.toString().replace("{", "").replace("}", "")
|
||||||
|
.split(",");
|
||||||
|
|
||||||
|
#ifdef QT_GUI_LIB
|
||||||
|
if (type == QMetaType::QPolygon) {
|
||||||
|
QString p;
|
||||||
|
QString ref = dbValue.toString();
|
||||||
|
QPolygon pol;
|
||||||
|
if (!readInsideParentese(ref, p))
|
||||||
|
return pol;
|
||||||
|
|
||||||
|
ref = p;
|
||||||
|
while (readInsideParentese(ref, p)) {
|
||||||
|
QList<int> l = _serializer->toListInt(p);
|
||||||
|
if (l.count() != 2)
|
||||||
|
return QPolygon();
|
||||||
|
pol.append(QPoint(l.at(0), l.at(1)));
|
||||||
|
}
|
||||||
|
return pol;
|
||||||
|
}
|
||||||
|
if (type == QMetaType::QPolygonF) {
|
||||||
|
QString p;
|
||||||
|
QString ref = dbValue.toString();
|
||||||
|
QPolygonF pol;
|
||||||
|
if (!readInsideParentese(ref, p))
|
||||||
|
return pol;
|
||||||
|
|
||||||
|
ref = p;
|
||||||
|
while (readInsideParentese(ref, p)) {
|
||||||
|
QList<qreal> l = _serializer->toListReal(p);
|
||||||
|
if (l.count() != 2)
|
||||||
|
return QPolygonF();
|
||||||
|
pol.append(QPointF(l.at(0), l.at(1)));
|
||||||
|
}
|
||||||
|
return pol;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return SqlGeneratorBase::unescapeValue(type, dbValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PostgreSqlGenerator::createConditionalPhrase(const PhraseData *d) const
|
||||||
|
{
|
||||||
|
if (!d)
|
||||||
|
return QString();
|
||||||
|
|
||||||
|
if (d->type == PhraseData::WithVariant) {
|
||||||
|
if (isPostGisType(d->operand.type()) && d->operatorCond == PhraseData::Equal) {
|
||||||
|
return QString("%1 ~= %2")
|
||||||
|
.arg(SqlGeneratorBase::createConditionalPhrase(d->left),
|
||||||
|
escapeValue(d->operand));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SqlGeneratorBase::createConditionalPhrase(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
NUT_END_NAMESPACE
|
NUT_END_NAMESPACE
|
||||||
|
|
|
||||||
|
|
@ -28,14 +28,24 @@ NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class PostgreSqlGenerator : public SqlGeneratorBase
|
class PostgreSqlGenerator : public SqlGeneratorBase
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
bool readInsideParentese(QString &ref, QString &out);
|
||||||
|
bool isPostGisType(const QVariant::Type &t) const;
|
||||||
public:
|
public:
|
||||||
explicit PostgreSqlGenerator(Database *parent);
|
explicit PostgreSqlGenerator(Database *parent = nullptr);
|
||||||
|
|
||||||
QString fieldType(FieldModel *field);
|
QString fieldType(FieldModel *field) override;
|
||||||
|
|
||||||
QString diff(FieldModel *oldField, FieldModel *newField);
|
QString diff(FieldModel *oldField, FieldModel *newField) override;
|
||||||
|
|
||||||
void replaceTableNames(QString &command);
|
// SqlGeneratorBase interface
|
||||||
|
public:
|
||||||
|
QString escapeValue(const QVariant &v) const override;
|
||||||
|
QVariant unescapeValue(const QMetaType::Type &type, const QVariant &dbValue) override;
|
||||||
|
|
||||||
|
// SqlGeneratorBase interface
|
||||||
|
protected:
|
||||||
|
QString createConditionalPhrase(const PhraseData *d) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
NUT_END_NAMESPACE
|
NUT_END_NAMESPACE
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
#include "../table.h"
|
#include "../table.h"
|
||||||
#include "../databasemodel.h"
|
#include "../databasemodel.h"
|
||||||
#include "../tablemodel.h"
|
#include "../tablemodel.h"
|
||||||
|
#include "sqlserializer.h"
|
||||||
|
|
||||||
NUT_BEGIN_NAMESPACE
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
|
@ -51,15 +52,28 @@ NUT_BEGIN_NAMESPACE
|
||||||
* INNER JOIN dbo.GiftCards ON dbo.GiftTypes.GiftTypeID = dbo.GiftCards.GiftTypeID
|
* INNER JOIN dbo.GiftCards ON dbo.GiftTypes.GiftTypeID = dbo.GiftCards.GiftTypeID
|
||||||
* INNER JOIN dbo.Entities ON dbo.GiftCards.GiftCardID = dbo.Entities.GiftCardID
|
* INNER JOIN dbo.Entities ON dbo.GiftCards.GiftCardID = dbo.Entities.GiftCardID
|
||||||
*/
|
*/
|
||||||
|
bool SqlGeneratorBase::isNumeric(const QMetaType::Type &type)
|
||||||
|
{
|
||||||
|
return type == QMetaType::SChar
|
||||||
|
|| type == QMetaType::Char
|
||||||
|
|| type == QMetaType::UChar
|
||||||
|
|| type == QMetaType::Short
|
||||||
|
|| type == QMetaType::UShort
|
||||||
|
|| type == QMetaType::Int
|
||||||
|
|| type == QMetaType::UInt
|
||||||
|
|| type == QMetaType::Long
|
||||||
|
|| type == QMetaType::ULong
|
||||||
|
|| type == QMetaType::LongLong
|
||||||
|
|| type == QMetaType::ULongLong;
|
||||||
|
}
|
||||||
|
|
||||||
SqlGeneratorBase::SqlGeneratorBase(Database *parent)
|
SqlGeneratorBase::SqlGeneratorBase(Database *parent)
|
||||||
: QObject((QObject *)parent)
|
: QObject(parent)
|
||||||
{
|
{
|
||||||
if (parent)
|
if (parent)
|
||||||
_database = parent;
|
_database = parent;
|
||||||
}
|
|
||||||
|
|
||||||
SqlGeneratorBase::~SqlGeneratorBase()
|
_serializer = new SqlSerializer;
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SqlGeneratorBase::masterDatabaseName(QString databaseName)
|
QString SqlGeneratorBase::masterDatabaseName(QString databaseName)
|
||||||
|
|
@ -104,36 +118,65 @@ QString SqlGeneratorBase::recordsPhrase(TableModel *table)
|
||||||
foreach (FieldModel *f, table->fields()) {
|
foreach (FieldModel *f, table->fields()) {
|
||||||
if (!ret.isEmpty())
|
if (!ret.isEmpty())
|
||||||
ret.append(", ");
|
ret.append(", ");
|
||||||
ret.append(QString("%1.%2 AS [%1.%2]").arg(table->name()).arg(f->name));
|
ret.append(QString("%1.%2 AS \"%1.%2\"").arg(table->name(), f->name));
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString SqlGeneratorBase::insertBulk(const QString &tableName, const PhraseList &ph, const QList<QVariantList> &vars)
|
||||||
|
{
|
||||||
|
QString sql;
|
||||||
|
foreach (QVariantList list, vars) {
|
||||||
|
QStringList values;
|
||||||
|
foreach (QVariant v, list)
|
||||||
|
values.append(escapeValue(v));
|
||||||
|
|
||||||
|
if (!sql.isEmpty())
|
||||||
|
sql.append(", ");
|
||||||
|
sql.append("(" + values.join(", ") + ")");
|
||||||
|
}
|
||||||
|
sql = "INSERT INTO " + tableName + "(" + createFieldPhrase(ph)
|
||||||
|
+ ") VALUES" + sql;
|
||||||
|
|
||||||
|
removeTableNames(sql);
|
||||||
|
return sql;
|
||||||
|
}
|
||||||
|
|
||||||
QString SqlGeneratorBase::fieldDeclare(FieldModel *field)
|
QString SqlGeneratorBase::fieldDeclare(FieldModel *field)
|
||||||
{
|
{
|
||||||
return field->name + " " + fieldType(field) + (field->notNull ? " NOT NULL" : "");
|
QString type = fieldType(field);
|
||||||
|
if (type.isEmpty())
|
||||||
|
return type;
|
||||||
|
return field->name + " " + type + (field->notNull ? " NOT NULL" : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList SqlGeneratorBase::constraints(TableModel *table)
|
||||||
|
{
|
||||||
|
Q_UNUSED(table);
|
||||||
|
return QStringList();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SqlGeneratorBase::relationDeclare(const RelationModel *relation)
|
QString SqlGeneratorBase::relationDeclare(const RelationModel *relation)
|
||||||
{
|
{
|
||||||
return QString("FOREIGN KEY (FK_%1) REFERENCES %2(%1)")
|
return QString("FOREIGN KEY (FK_%1) REFERENCES %2(%1)")
|
||||||
.arg(relation->localColumn)
|
.arg(relation->localColumn, relation->slaveTable->name());
|
||||||
.arg(relation->slaveTable->name());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList SqlGeneratorBase::diff(DatabaseModel lastModel,
|
QStringList SqlGeneratorBase::diff(const DatabaseModel &lastModel,
|
||||||
DatabaseModel newModel)
|
const DatabaseModel &newModel)
|
||||||
{
|
{
|
||||||
QStringList ret;
|
QStringList ret;
|
||||||
|
|
||||||
DatabaseModel unionModel = lastModel + newModel;
|
DatabaseModel unionModel = lastModel | newModel;
|
||||||
|
DatabaseModel::iterator i;
|
||||||
|
|
||||||
foreach (TableModel *table, unionModel) {
|
for (i = unionModel.begin(); i != unionModel.end(); ++i) {
|
||||||
TableModel *oldTable = lastModel.tableByName(table->name());
|
TableModel *oldTable = lastModel.tableByName((*i)->name());
|
||||||
TableModel *newTable = newModel.tableByName(table->name());
|
TableModel *newTable = newModel.tableByName((*i)->name());
|
||||||
QString sql = diff(oldTable, newTable);
|
QStringList sql = diff(oldTable, newTable);
|
||||||
if (!sql.isEmpty())
|
if (!sql.isEmpty())
|
||||||
ret << sql;
|
ret << sql;
|
||||||
|
|
||||||
// QString sqlRel = diffRelation(oldTable, newTable);
|
// QString sqlRel = diffRelation(oldTable, newTable);
|
||||||
// if (!sqlRel.isEmpty())
|
// if (!sqlRel.isEmpty())
|
||||||
// ret << sqlRel;
|
// ret << sqlRel;
|
||||||
|
|
@ -147,7 +190,7 @@ QString SqlGeneratorBase::diff(FieldModel *oldField, FieldModel *newField)
|
||||||
QString sql = QString();
|
QString sql = QString();
|
||||||
if (oldField && newField)
|
if (oldField && newField)
|
||||||
if (*oldField == *newField)
|
if (*oldField == *newField)
|
||||||
return QString();
|
return sql;
|
||||||
|
|
||||||
if (!newField) {
|
if (!newField) {
|
||||||
sql = "DROP COLUMN " + oldField->name;
|
sql = "DROP COLUMN " + oldField->name;
|
||||||
|
|
@ -161,14 +204,17 @@ QString SqlGeneratorBase::diff(FieldModel *oldField, FieldModel *newField)
|
||||||
return sql;
|
return sql;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SqlGeneratorBase::diff(TableModel *oldTable, TableModel *newTable)
|
QStringList SqlGeneratorBase::diff(TableModel *oldTable, TableModel *newTable)
|
||||||
{
|
{
|
||||||
|
if (!newTable && !oldTable)
|
||||||
|
return QStringList();
|
||||||
|
|
||||||
if (oldTable && newTable)
|
if (oldTable && newTable)
|
||||||
if (*oldTable == *newTable)
|
if (*oldTable == *newTable)
|
||||||
return QString();
|
return QStringList();
|
||||||
|
|
||||||
if (!newTable)
|
if (!newTable)
|
||||||
return "DROP TABLE " + oldTable->name();
|
return QStringList() << ("DROP TABLE " + oldTable->name());
|
||||||
|
|
||||||
QList<QString> fieldNames;
|
QList<QString> fieldNames;
|
||||||
QList<QString> relations;
|
QList<QString> relations;
|
||||||
|
|
@ -196,10 +242,13 @@ QString SqlGeneratorBase::diff(TableModel *oldTable, TableModel *newTable)
|
||||||
FieldModel *oldField = oldTable->field(fieldName);
|
FieldModel *oldField = oldTable->field(fieldName);
|
||||||
|
|
||||||
QString buffer = diff(oldField, newField);
|
QString buffer = diff(oldField, newField);
|
||||||
if (!buffer.isNull())
|
if (!buffer.isEmpty())
|
||||||
columnSql << buffer;
|
columnSql << buffer;
|
||||||
} else {
|
} else {
|
||||||
columnSql << fieldDeclare(newField);
|
QString declare = fieldDeclare(newField);
|
||||||
|
if (declare.isEmpty())
|
||||||
|
return QStringList() << declare;
|
||||||
|
columnSql << declare;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// foreach (QString fieldName, relations) {
|
// foreach (QString fieldName, relations) {
|
||||||
|
|
@ -217,25 +266,27 @@ QString SqlGeneratorBase::diff(TableModel *oldTable, TableModel *newTable)
|
||||||
QString sql;
|
QString sql;
|
||||||
if (oldTable) {
|
if (oldTable) {
|
||||||
sql = QString("ALTER TABLE %1 \n%2")
|
sql = QString("ALTER TABLE %1 \n%2")
|
||||||
.arg(newTable->name())
|
.arg(newTable->name(), columnSql.join(",\n"));
|
||||||
.arg(columnSql.join(",\n"));
|
|
||||||
} else {
|
} else {
|
||||||
if (!newTable->primaryKey().isNull())
|
if (!newTable->primaryKey().isNull()) {
|
||||||
columnSql << QString("CONSTRAINT pk_%1 PRIMARY KEY (%2)")
|
QString pkCon = primaryKeyConstraint(newTable);
|
||||||
.arg(newTable->name())
|
if (!pkCon.isEmpty())
|
||||||
.arg(newTable->primaryKey());
|
columnSql << pkCon;
|
||||||
|
columnSql << constraints(newTable);
|
||||||
|
}
|
||||||
|
|
||||||
sql = QString("CREATE TABLE %1 \n(%2)")
|
sql = QString("CREATE TABLE %1 \n(%2)")
|
||||||
.arg(newTable->name())
|
.arg(newTable->name(), columnSql.join(",\n"));
|
||||||
.arg(columnSql.join(",\n"));
|
|
||||||
}
|
}
|
||||||
return sql;
|
return QStringList() << sql;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SqlGeneratorBase::diffRelation(TableModel *oldTable, TableModel *newTable)
|
QStringList SqlGeneratorBase::diffRelation(TableModel *oldTable, TableModel *newTable)
|
||||||
{
|
{
|
||||||
|
QStringList ret;
|
||||||
if (!newTable)
|
if (!newTable)
|
||||||
return QString();
|
return ret;
|
||||||
|
|
||||||
QList<QString> relations;
|
QList<QString> relations;
|
||||||
|
|
||||||
|
|
@ -251,25 +302,25 @@ QString SqlGeneratorBase::diffRelation(TableModel *oldTable, TableModel *newTabl
|
||||||
QStringList columnSql;
|
QStringList columnSql;
|
||||||
foreach (QString fieldName, relations) {
|
foreach (QString fieldName, relations) {
|
||||||
RelationModel *newRelation = newTable->foregionKeyByField(fieldName);
|
RelationModel *newRelation = newTable->foregionKeyByField(fieldName);
|
||||||
RelationModel *oldRelation = 0;
|
RelationModel *oldRelation = nullptr;
|
||||||
if (oldTable)
|
if (oldTable)
|
||||||
oldRelation = oldTable->foregionKeyByField(fieldName);
|
oldRelation = oldTable->foregionKeyByField(fieldName);
|
||||||
|
|
||||||
QString buffer = diff(oldRelation, newRelation);
|
QStringList buffer = diff(oldRelation, newRelation);
|
||||||
if (!buffer.isNull())
|
if (!buffer.isEmpty())
|
||||||
columnSql << buffer;
|
columnSql << buffer.at(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (columnSql.count())
|
if (columnSql.count())
|
||||||
return "ALTER TABLE " + newTable->name() + "\n"
|
ret.append("ALTER TABLE " + newTable->name() + "\n"
|
||||||
+ columnSql.join(",\n");
|
+ columnSql.join(",\n"));
|
||||||
else
|
|
||||||
return QString();
|
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SqlGeneratorBase::diff(RelationModel *oldRel, RelationModel *newRel)
|
QStringList SqlGeneratorBase::diff(RelationModel *oldRel, RelationModel *newRel)
|
||||||
{
|
{
|
||||||
|
QStringList ret;
|
||||||
/*
|
/*
|
||||||
CONSTRAINT FK_PersonOrder FOREIGN KEY (PersonID)
|
CONSTRAINT FK_PersonOrder FOREIGN KEY (PersonID)
|
||||||
REFERENCES Persons(PersonID)
|
REFERENCES Persons(PersonID)
|
||||||
|
|
@ -283,25 +334,23 @@ QString SqlGeneratorBase::diff(RelationModel *oldRel, RelationModel *newRel)
|
||||||
.arg(newRelation->foreignColumn);
|
.arg(newRelation->foreignColumn);
|
||||||
*/
|
*/
|
||||||
if (!oldRel)
|
if (!oldRel)
|
||||||
return QString("ADD CONSTRAINT FK_%1 FOREIGN KEY (%1) "
|
ret.append(QString("ADD CONSTRAINT FK_%1 FOREIGN KEY (%1) "
|
||||||
"REFERENCES %2(%3)")
|
"REFERENCES %2(%3)")
|
||||||
.arg(newRel->localColumn)
|
.arg(newRel->localColumn, newRel->masterTable->name(),
|
||||||
.arg(newRel->masterTable->name())
|
newRel->foreignColumn));
|
||||||
.arg(newRel->foreignColumn);
|
|
||||||
|
|
||||||
if (!newRel)
|
if (!newRel)
|
||||||
return QString("ADD CONSTRAINT FK_%1 FOREIGN KEY (%1) "
|
ret.append(QString("ADD CONSTRAINT FK_%1 FOREIGN KEY (%1) "
|
||||||
"REFERENCES %2(%3)")
|
"REFERENCES %2(%3)")
|
||||||
.arg(oldRel->localColumn)
|
.arg(oldRel->localColumn, oldRel->masterTable->name(),
|
||||||
.arg(oldRel->masterTable->name())
|
oldRel->foreignColumn));
|
||||||
.arg(oldRel->foreignColumn);
|
|
||||||
|
|
||||||
// if (*oldRel == *newRel)
|
// if (*oldRel == *newRel)
|
||||||
return QString();
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SqlGeneratorBase::join(const QString &mainTable,
|
QString SqlGeneratorBase::join(const QString &mainTable,
|
||||||
const QList<RelationModel*> list,
|
const QList<RelationModel*> &list,
|
||||||
QStringList *order)
|
QStringList *order)
|
||||||
{
|
{
|
||||||
QString ret = mainTable;
|
QString ret = mainTable;
|
||||||
|
|
@ -309,19 +358,19 @@ QString SqlGeneratorBase::join(const QString &mainTable,
|
||||||
for (i = list.begin(); i != list.end(); ++i) {
|
for (i = list.begin(); i != list.end(); ++i) {
|
||||||
if ((*i)->masterTable->name() == mainTable) {
|
if ((*i)->masterTable->name() == mainTable) {
|
||||||
ret.append(QString(" INNER JOIN %3 ON %1.%2 = %3.%4")
|
ret.append(QString(" INNER JOIN %3 ON %1.%2 = %3.%4")
|
||||||
.arg((*i)->masterTable->name())
|
.arg((*i)->masterTable->name(),
|
||||||
.arg((*i)->masterTable->primaryKey())
|
(*i)->masterTable->primaryKey(),
|
||||||
.arg((*i)->slaveTable->name())
|
(*i)->slaveTable->name(),
|
||||||
.arg((*i)->localColumn));
|
(*i)->localColumn));
|
||||||
|
|
||||||
if (order != Q_NULLPTR)
|
if (order != Q_NULLPTR)
|
||||||
order->append((*i)->slaveTable->name() + "." + (*i)->slaveTable->primaryKey());
|
order->append((*i)->slaveTable->name() + "." + (*i)->slaveTable->primaryKey());
|
||||||
} else {
|
} else {
|
||||||
ret.append(QString(" INNER JOIN %3 ON %1.%2 = %3.%4")
|
ret.append(QString(" INNER JOIN %3 ON %1.%2 = %3.%4")
|
||||||
.arg(mainTable)
|
.arg(mainTable,
|
||||||
.arg((*i)->localColumn)
|
(*i)->localColumn,
|
||||||
.arg((*i)->masterTable->name())
|
(*i)->masterTable->name(),
|
||||||
.arg((*i)->masterTable->primaryKey()));
|
(*i)->masterTable->primaryKey()));
|
||||||
|
|
||||||
if (order != Q_NULLPTR)
|
if (order != Q_NULLPTR)
|
||||||
order->append((*i)->masterTable->name() + "." + (*i)->masterTable->primaryKey());
|
order->append((*i)->masterTable->name() + "." + (*i)->masterTable->primaryKey());
|
||||||
|
|
@ -359,10 +408,8 @@ QString SqlGeneratorBase::join(const QStringList &list, QStringList *order)
|
||||||
if (rel) {
|
if (rel) {
|
||||||
//mainTable is master of table
|
//mainTable is master of table
|
||||||
ret.append(QString(" INNER JOIN [%1] ON %4.%2 = %1.%3")
|
ret.append(QString(" INNER JOIN [%1] ON %4.%2 = %1.%3")
|
||||||
.arg(table)
|
.arg(table, rel->masterTable->primaryKey(),
|
||||||
.arg(rel->masterTable->primaryKey())
|
rel->localColumn, mainTable));
|
||||||
.arg(rel->localColumn)
|
|
||||||
.arg(mainTable));
|
|
||||||
|
|
||||||
if (order != Q_NULLPTR)
|
if (order != Q_NULLPTR)
|
||||||
order->append(mainTable + "." + rel->masterTable->primaryKey());
|
order->append(mainTable + "." + rel->masterTable->primaryKey());
|
||||||
|
|
@ -372,10 +419,8 @@ QString SqlGeneratorBase::join(const QStringList &list, QStringList *order)
|
||||||
if (rel) {
|
if (rel) {
|
||||||
// table is master of mainTable
|
// table is master of mainTable
|
||||||
ret.append(QString(" INNER JOIN [%1] ON %4.%2 = %1.%3")
|
ret.append(QString(" INNER JOIN [%1] ON %4.%2 = %1.%3")
|
||||||
.arg(table)
|
.arg(table, rel->localColumn,
|
||||||
.arg(rel->localColumn)
|
rel->masterTable->primaryKey(), mainTable));
|
||||||
.arg(rel->masterTable->primaryKey())
|
|
||||||
.arg(mainTable));
|
|
||||||
|
|
||||||
if (order != Q_NULLPTR)
|
if (order != Q_NULLPTR)
|
||||||
order->append(mainTable + "." + rel->localColumn);
|
order->append(mainTable + "." + rel->localColumn);
|
||||||
|
|
@ -395,7 +440,9 @@ QString SqlGeneratorBase::join(const QStringList &list, QStringList *order)
|
||||||
QString SqlGeneratorBase::insertRecord(Table *t, QString tableName)
|
QString SqlGeneratorBase::insertRecord(Table *t, QString tableName)
|
||||||
{
|
{
|
||||||
QString sql = QString();
|
QString sql = QString();
|
||||||
QString key = t->isPrimaryKeyAutoIncrement() ? t->primaryKey() : QString();
|
auto model = _database->model().tableByName(tableName);
|
||||||
|
|
||||||
|
QString key = model->isPrimaryKeyAutoIncrement() ? model->primaryKey() : QString();
|
||||||
|
|
||||||
QStringList values;
|
QStringList values;
|
||||||
|
|
||||||
|
|
@ -411,9 +458,7 @@ QString SqlGeneratorBase::insertRecord(Table *t, QString tableName)
|
||||||
changedPropertiesText.append(s);
|
changedPropertiesText.append(s);
|
||||||
}
|
}
|
||||||
sql = QString("INSERT INTO %1 (%2) VALUES (%3)")
|
sql = QString("INSERT INTO %1 (%2) VALUES (%3)")
|
||||||
.arg(tableName)
|
.arg(tableName, changedPropertiesText, values.join(", "));
|
||||||
.arg(changedPropertiesText)
|
|
||||||
.arg(values.join(", "));
|
|
||||||
|
|
||||||
removeTableNames(sql);
|
removeTableNames(sql);
|
||||||
|
|
||||||
|
|
@ -423,7 +468,8 @@ QString SqlGeneratorBase::insertRecord(Table *t, QString tableName)
|
||||||
QString SqlGeneratorBase::updateRecord(Table *t, QString tableName)
|
QString SqlGeneratorBase::updateRecord(Table *t, QString tableName)
|
||||||
{
|
{
|
||||||
QString sql = QString();
|
QString sql = QString();
|
||||||
QString key = t->primaryKey();
|
auto model = _database->model().tableByName(tableName);
|
||||||
|
QString key = model->primaryKey();
|
||||||
QStringList values;
|
QStringList values;
|
||||||
|
|
||||||
foreach (QString f, t->changedProperties())
|
foreach (QString f, t->changedProperties())
|
||||||
|
|
@ -431,10 +477,8 @@ QString SqlGeneratorBase::updateRecord(Table *t, QString tableName)
|
||||||
values.append(f + "='" + t->property(f.toLatin1().data()).toString()
|
values.append(f + "='" + t->property(f.toLatin1().data()).toString()
|
||||||
+ "'");
|
+ "'");
|
||||||
sql = QString("UPDATE %1 SET %2 WHERE %3=%4")
|
sql = QString("UPDATE %1 SET %2 WHERE %3=%4")
|
||||||
.arg(tableName)
|
.arg(tableName, values.join(", "),
|
||||||
.arg(values.join(", "))
|
key, t->property(key.toUtf8().data()).toString());
|
||||||
.arg(key)
|
|
||||||
.arg(t->primaryValue().toString());
|
|
||||||
|
|
||||||
removeTableNames(sql);
|
removeTableNames(sql);
|
||||||
|
|
||||||
|
|
@ -443,10 +487,10 @@ QString SqlGeneratorBase::updateRecord(Table *t, QString tableName)
|
||||||
|
|
||||||
QString SqlGeneratorBase::deleteRecord(Table *t, QString tableName)
|
QString SqlGeneratorBase::deleteRecord(Table *t, QString tableName)
|
||||||
{
|
{
|
||||||
|
auto model = _database->model().tableByName(tableName);
|
||||||
|
QString key = model->primaryKey();
|
||||||
QString sql = QString("DELETE FROM %1 WHERE %2='%3'")
|
QString sql = QString("DELETE FROM %1 WHERE %2='%3'")
|
||||||
.arg(tableName)
|
.arg(tableName, key, t->property(key.toUtf8().data()).toString());
|
||||||
.arg(t->primaryKey())
|
|
||||||
.arg(t->primaryValue().toString());
|
|
||||||
replaceTableNames(sql);
|
replaceTableNames(sql);
|
||||||
return sql;
|
return sql;
|
||||||
}
|
}
|
||||||
|
|
@ -457,27 +501,20 @@ QString SqlGeneratorBase::agregateText(const AgregateType &t,
|
||||||
switch (t) {
|
switch (t) {
|
||||||
case Min:
|
case Min:
|
||||||
return "MIN(" + arg + ")";
|
return "MIN(" + arg + ")";
|
||||||
break;
|
|
||||||
|
|
||||||
case Max:
|
case Max:
|
||||||
return "MAX(" + arg + ")";
|
return "MAX(" + arg + ")";
|
||||||
break;
|
|
||||||
|
|
||||||
case Average:
|
case Average:
|
||||||
return "AVERAGE(" + arg + ")";
|
return "AVG(" + arg + ")";
|
||||||
break;
|
|
||||||
|
|
||||||
case Count:
|
case Count:
|
||||||
return "COUNT(" + arg + ")";
|
return "COUNT(" + arg + ")";
|
||||||
break;
|
|
||||||
|
|
||||||
case SignleField:
|
case SignleField:
|
||||||
return arg;
|
return arg;
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return QString();
|
|
||||||
}
|
}
|
||||||
|
return QString(); // never reach
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SqlGeneratorBase::fromTableText(const QString &tableName,
|
QString SqlGeneratorBase::fromTableText(const QString &tableName,
|
||||||
|
|
@ -492,10 +529,8 @@ QString SqlGeneratorBase::fromTableText(const QString &tableName,
|
||||||
if (rel) {
|
if (rel) {
|
||||||
QString pk = _database->model().tableByName(tableName)->primaryKey();
|
QString pk = _database->model().tableByName(tableName)->primaryKey();
|
||||||
tableNameText = QString("%1 INNER JOIN %2 ON (%1.%3 = %2.%4)")
|
tableNameText = QString("%1 INNER JOIN %2 ON (%1.%3 = %2.%4)")
|
||||||
.arg(tableName)
|
.arg(tableName, joinTableName,
|
||||||
.arg(joinTableName)
|
pk, rel->localColumn);
|
||||||
.arg(pk)
|
|
||||||
.arg(rel->localColumn);
|
|
||||||
orderBy = tableName + "." + pk;
|
orderBy = tableName + "." + pk;
|
||||||
} else {
|
} else {
|
||||||
qWarning("Relation between table %s and class %s (%s) not exists!",
|
qWarning("Relation between table %s and class %s (%s) not exists!",
|
||||||
|
|
@ -509,7 +544,7 @@ QString SqlGeneratorBase::fromTableText(const QString &tableName,
|
||||||
return tableNameText;
|
return tableNameText;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SqlGeneratorBase::deleteRecords(QString tableName, QString where)
|
QString SqlGeneratorBase::deleteRecords(const QString &tableName, const QString &where)
|
||||||
{
|
{
|
||||||
QString sql = QString();
|
QString sql = QString();
|
||||||
if (where.isEmpty() || where.isNull())
|
if (where.isEmpty() || where.isNull())
|
||||||
|
|
@ -526,7 +561,7 @@ QString SqlGeneratorBase::selectCommand(const QString &tableName,
|
||||||
const PhraseList &fields,
|
const PhraseList &fields,
|
||||||
const ConditionalPhrase &where,
|
const ConditionalPhrase &where,
|
||||||
const PhraseList &order,
|
const PhraseList &order,
|
||||||
const QList<RelationModel*> joins,
|
const QList<RelationModel*> &joins,
|
||||||
const int skip,
|
const int skip,
|
||||||
const int take)
|
const int take)
|
||||||
{
|
{
|
||||||
|
|
@ -563,9 +598,9 @@ QString SqlGeneratorBase::selectCommand(const QString &tableName,
|
||||||
if (orderText != "")
|
if (orderText != "")
|
||||||
sql.append(" ORDER BY " + orderText);
|
sql.append(" ORDER BY " + orderText);
|
||||||
|
|
||||||
for (int i = 0; i < _database->model().count(); i++)
|
// for (int i = 0; i < _database->model().count(); i++)
|
||||||
sql = sql.replace(_database->model().at(i)->className() + ".",
|
// sql = sql.replace(_database->model().at(i)->className() + ".",
|
||||||
_database->model().at(i)->name() + ".");
|
// _database->model().at(i)->name() + ".");
|
||||||
|
|
||||||
appendSkipTake(sql, skip, take);
|
appendSkipTake(sql, skip, take);
|
||||||
replaceTableNames(sql);
|
replaceTableNames(sql);
|
||||||
|
|
@ -664,9 +699,7 @@ QString SqlGeneratorBase::insertCommand(const QString &tableName, const Assignme
|
||||||
values.append(escapeValue(d->operand));
|
values.append(escapeValue(d->operand));
|
||||||
}
|
}
|
||||||
return QString("INSERT INTO %1 (%2) VALUES (%3);")
|
return QString("INSERT INTO %1 (%2) VALUES (%3);")
|
||||||
.arg(tableName)
|
.arg(tableName, fieldNames, values);
|
||||||
.arg(fieldNames)
|
|
||||||
.arg(values);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//QString SqlGeneratorBase::selectCommand(SqlGeneratorBase::AgregateType t,
|
//QString SqlGeneratorBase::selectCommand(SqlGeneratorBase::AgregateType t,
|
||||||
|
|
@ -740,14 +773,14 @@ QString SqlGeneratorBase::insertCommand(const QString &tableName, const Assignme
|
||||||
|
|
||||||
void SqlGeneratorBase::replaceTableNames(QString &command)
|
void SqlGeneratorBase::replaceTableNames(QString &command)
|
||||||
{
|
{
|
||||||
foreach (TableModel *m, TableModel::allModels())
|
foreach (TableModel *m, _database->model())
|
||||||
command = command
|
command = command
|
||||||
.replace("[" + m->className() + "]", "`" + m->name() + "`");
|
.replace("[" + m->className() + "]", m->name());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SqlGeneratorBase::removeTableNames(QString &command)
|
void SqlGeneratorBase::removeTableNames(QString &command)
|
||||||
{
|
{
|
||||||
foreach (TableModel *m, TableModel::allModels())
|
foreach (TableModel *m, _database->model())
|
||||||
command = command.replace("[" + m->className() + "].", "");
|
command = command.replace("[" + m->className() + "].", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -792,65 +825,25 @@ void SqlGeneratorBase::removeTableNames(QString &command)
|
||||||
|
|
||||||
QString SqlGeneratorBase::escapeValue(const QVariant &v) const
|
QString SqlGeneratorBase::escapeValue(const QVariant &v) const
|
||||||
{
|
{
|
||||||
switch (v.type()) {
|
if (v.type() == QVariant::String && v.toString().isEmpty())
|
||||||
case QVariant::Bool:
|
return "''";
|
||||||
return v.toBool() ? "1" : "0";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case QVariant::Int:
|
QString serialized = _serializer->serialize(v);
|
||||||
case QVariant::UInt:
|
if (serialized.isEmpty()) {
|
||||||
case QVariant::ULongLong:
|
qWarning("No field escape rule for: %s", v.typeName());
|
||||||
case QVariant::LongLong:
|
return QString();
|
||||||
case QVariant::Double:
|
|
||||||
return v.toString();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case QVariant::Uuid:
|
|
||||||
return "'" + v.toUuid().toString() + "'";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case QVariant::Char:
|
|
||||||
case QVariant::String:
|
|
||||||
return "'" + v.toString() + "'";
|
|
||||||
|
|
||||||
case QVariant::DateTime:
|
|
||||||
return "'" + v.toDateTime().toString(Qt::ISODate) + "'";
|
|
||||||
|
|
||||||
case QVariant::Date:
|
|
||||||
return "'" + v.toDate().toString(Qt::ISODate) + "'";
|
|
||||||
|
|
||||||
case QVariant::Time:
|
|
||||||
return "'" + v.toTime().toString(Qt::ISODate) + "'";
|
|
||||||
|
|
||||||
case QVariant::StringList:
|
|
||||||
case QVariant::List:
|
|
||||||
return "('" + v.toStringList().join("', '") + "')";
|
|
||||||
|
|
||||||
case QVariant::Point: {
|
|
||||||
QPoint pt = v.toPoint();
|
|
||||||
return QString("POINT(%1 %2)").arg(pt.x()).arg(pt.y());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case QVariant::PointF: {
|
if (v.type() == QVariant::List)
|
||||||
QPointF pt = v.toPointF();
|
return serialized;
|
||||||
return QString("POINT(%1 %2)").arg(pt.x()).arg(pt.y());
|
|
||||||
}
|
|
||||||
|
|
||||||
case QVariant::Invalid:
|
return "'" + serialized + "'";
|
||||||
qFatal("Invalud field value");
|
|
||||||
return "<FAIL>";
|
|
||||||
|
|
||||||
default:
|
|
||||||
Q_UNREACHABLE();
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant SqlGeneratorBase::readValue(const QVariant::Type &type,
|
QVariant SqlGeneratorBase::unescapeValue(const QMetaType::Type &type,
|
||||||
const QVariant &dbValue)
|
const QVariant &dbValue)
|
||||||
{
|
{
|
||||||
Q_UNUSED(type);
|
return _serializer->deserialize(dbValue.toString(), type);
|
||||||
return dbValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SqlGeneratorBase::phrase(const PhraseData *d) const
|
QString SqlGeneratorBase::phrase(const PhraseData *d) const
|
||||||
|
|
@ -875,9 +868,6 @@ QString SqlGeneratorBase::phrase(const PhraseData *d) const
|
||||||
case PhraseData::WithoutOperand:
|
case PhraseData::WithoutOperand:
|
||||||
ret = phrase(d->left) + " " + operatorString(d->operatorCond);
|
ret = phrase(d->left) + " " + operatorString(d->operatorCond);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
|
||||||
ret = "<FAIL>";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d->operatorCond == PhraseData::And || d->operatorCond == PhraseData::Or)
|
if (d->operatorCond == PhraseData::And || d->operatorCond == PhraseData::Or)
|
||||||
|
|
@ -957,6 +947,12 @@ void SqlGeneratorBase::appendSkipTake(QString &sql, int skip, int take)
|
||||||
Q_UNUSED(take);
|
Q_UNUSED(take);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString SqlGeneratorBase::primaryKeyConstraint(const TableModel *table) const
|
||||||
|
{
|
||||||
|
return QString("CONSTRAINT pk_%1 PRIMARY KEY (%2)")
|
||||||
|
.arg(table->name(), table->primaryKey());
|
||||||
|
}
|
||||||
|
|
||||||
QString SqlGeneratorBase::createConditionalPhrase(const PhraseData *d) const
|
QString SqlGeneratorBase::createConditionalPhrase(const PhraseData *d) const
|
||||||
{
|
{
|
||||||
if (!d)
|
if (!d)
|
||||||
|
|
@ -968,7 +964,7 @@ QString SqlGeneratorBase::createConditionalPhrase(const PhraseData *d) const
|
||||||
//apply not (!)
|
//apply not (!)
|
||||||
if (d->isNot) {
|
if (d->isNot) {
|
||||||
if (op < 20)
|
if (op < 20)
|
||||||
op = (PhraseData::Condition)((op + 10) % 20);
|
op = static_cast<PhraseData::Condition>((op + 10) % 20);
|
||||||
}
|
}
|
||||||
switch (d->type) {
|
switch (d->type) {
|
||||||
case PhraseData::Field:
|
case PhraseData::Field:
|
||||||
|
|
@ -978,22 +974,40 @@ QString SqlGeneratorBase::createConditionalPhrase(const PhraseData *d) const
|
||||||
case PhraseData::WithVariant:
|
case PhraseData::WithVariant:
|
||||||
if (op == PhraseData::AddYears)
|
if (op == PhraseData::AddYears)
|
||||||
ret = QString("DATEADD(year, %1, %2)")
|
ret = QString("DATEADD(year, %1, %2)")
|
||||||
.arg(d->operand.toString()).arg(createConditionalPhrase(d->left));
|
.arg(d->operand.toString(), createConditionalPhrase(d->left));
|
||||||
else if (op == PhraseData::AddMonths)
|
else if (op == PhraseData::AddMonths)
|
||||||
ret = QString("DATEADD(month, %1, %2)")
|
ret = QString("DATEADD(month, %1, %2)")
|
||||||
.arg(d->operand.toString()).arg(createConditionalPhrase(d->left));
|
.arg(d->operand.toString(), createConditionalPhrase(d->left));
|
||||||
else if (op == PhraseData::AddDays)
|
else if (op == PhraseData::AddDays)
|
||||||
ret = QString("DATEADD(day, %1, %2)")
|
ret = QString("DATEADD(day, %1, %2)")
|
||||||
.arg(d->operand.toString()).arg(createConditionalPhrase(d->left));
|
.arg(d->operand.toString(), createConditionalPhrase(d->left));
|
||||||
else if (op == PhraseData::AddHours)
|
else if (op == PhraseData::AddHours)
|
||||||
ret = QString("DATEADD(hour, %1, %2)")
|
ret = QString("DATEADD(hour, %1, %2)")
|
||||||
.arg(d->operand.toString()).arg(createConditionalPhrase(d->left));
|
.arg(d->operand.toString(), createConditionalPhrase(d->left));
|
||||||
else if (op == PhraseData::AddMinutes)
|
else if (op == PhraseData::AddMinutes)
|
||||||
ret = QString("DATEADD(minute, %1, %2)")
|
ret = QString("DATEADD(minute, %1, %2)")
|
||||||
.arg(d->operand.toString()).arg(createConditionalPhrase(d->left));
|
.arg(d->operand.toString(), createConditionalPhrase(d->left));
|
||||||
else if (op == PhraseData::AddSeconds)
|
else if (op == PhraseData::AddSeconds)
|
||||||
ret = QString("DATEADD(second, %1, %2)")
|
ret = QString("DATEADD(second, %1, %2)")
|
||||||
.arg(d->operand.toString()).arg(createConditionalPhrase(d->left));
|
.arg(d->operand.toString(), createConditionalPhrase(d->left));
|
||||||
|
else if (op == PhraseData::DatePartYear)
|
||||||
|
ret = QString("DATEPART(year, %1)")
|
||||||
|
.arg(d->operand.toString());
|
||||||
|
else if (op == PhraseData::DatePartMonth)
|
||||||
|
ret = QString("DATEPART(month, %1)")
|
||||||
|
.arg(d->operand.toString());
|
||||||
|
else if (op == PhraseData::DatePartDay)
|
||||||
|
ret = QString("DATEPART(day, %1)")
|
||||||
|
.arg(d->operand.toString());
|
||||||
|
else if (op == PhraseData::DatePartHour)
|
||||||
|
ret = QString("DATEPART(hour, %1)")
|
||||||
|
.arg(d->operand.toString());
|
||||||
|
else if (op == PhraseData::DatePartMinute)
|
||||||
|
ret = QString("DATEPART(minute, %1)")
|
||||||
|
.arg(d->operand.toString());
|
||||||
|
else if (op == PhraseData::DatePartMilisecond)
|
||||||
|
ret = QString("DATEPART(milisecond, %1)")
|
||||||
|
.arg(d->operand.toString());
|
||||||
else
|
else
|
||||||
ret = createConditionalPhrase(d->left) + " " + operatorString(op) + " "
|
ret = createConditionalPhrase(d->left) + " " + operatorString(op) + " "
|
||||||
+ escapeValue(d->operand);
|
+ escapeValue(d->operand);
|
||||||
|
|
@ -1007,9 +1021,6 @@ QString SqlGeneratorBase::createConditionalPhrase(const PhraseData *d) const
|
||||||
case PhraseData::WithoutOperand:
|
case PhraseData::WithoutOperand:
|
||||||
ret = createConditionalPhrase(d->left) + " " + operatorString(op);
|
ret = createConditionalPhrase(d->left) + " " + operatorString(op);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
|
||||||
ret = "<FAIL phrase>";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d->operatorCond == PhraseData::And || d->operatorCond == PhraseData::Or)
|
if (d->operatorCond == PhraseData::And || d->operatorCond == PhraseData::Or)
|
||||||
|
|
@ -1069,7 +1080,6 @@ void SqlGeneratorBase::createInsertPhrase(const AssignmentPhraseList &ph, QStrin
|
||||||
|
|
||||||
case PhraseData::Field:
|
case PhraseData::Field:
|
||||||
case PhraseData::WithoutOperand:
|
case PhraseData::WithoutOperand:
|
||||||
default:
|
|
||||||
qFatal("Invalid insert command");
|
qFatal("Invalid insert command");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,8 @@
|
||||||
#include "../phrase.h"
|
#include "../phrase.h"
|
||||||
//#include "../wherephrase.h"
|
//#include "../wherephrase.h"
|
||||||
|
|
||||||
|
class SqlSerializer;
|
||||||
|
|
||||||
NUT_BEGIN_NAMESPACE
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class Table;
|
class Table;
|
||||||
|
|
@ -40,6 +42,11 @@ class SqlGeneratorBase : public QObject
|
||||||
// Q_OBJECT
|
// Q_OBJECT
|
||||||
|
|
||||||
Database *_database;
|
Database *_database;
|
||||||
|
protected:
|
||||||
|
SqlSerializer *_serializer;
|
||||||
|
|
||||||
|
bool isNumeric(const QMetaType::Type &type);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//TODO: remove this enum
|
//TODO: remove this enum
|
||||||
enum CommandType{
|
enum CommandType{
|
||||||
|
|
@ -58,24 +65,38 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit SqlGeneratorBase(Database *parent);
|
explicit SqlGeneratorBase(Database *parent);
|
||||||
virtual ~SqlGeneratorBase();
|
virtual ~SqlGeneratorBase() = default;
|
||||||
|
|
||||||
|
virtual bool supportPrimaryKey(const QMetaType::Type &type) {
|
||||||
|
Q_UNUSED(type);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
virtual bool supportAutoIncrement(const QMetaType::Type &type) {
|
||||||
|
Q_UNUSED(type);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//fields
|
||||||
|
virtual QString fieldType(FieldModel *field) = 0;
|
||||||
|
virtual QString fieldDeclare(FieldModel *field);
|
||||||
|
virtual QStringList constraints(TableModel *table);
|
||||||
|
virtual QString escapeValue(const QVariant &v) const;
|
||||||
|
virtual QVariant unescapeValue(const QMetaType::Type &type, const QVariant &dbValue);
|
||||||
|
|
||||||
virtual QString masterDatabaseName(QString databaseName);
|
virtual QString masterDatabaseName(QString databaseName);
|
||||||
|
|
||||||
virtual QString createTable(TableModel *table);
|
virtual QString createTable(TableModel *table);
|
||||||
|
|
||||||
virtual QString fieldType(FieldModel *field) = 0;
|
|
||||||
virtual QString fieldDeclare(FieldModel *field);
|
|
||||||
virtual QString relationDeclare(const RelationModel *relation);
|
virtual QString relationDeclare(const RelationModel *relation);
|
||||||
|
|
||||||
virtual QStringList diff(DatabaseModel lastModel, DatabaseModel newModel);
|
virtual QStringList diff(const DatabaseModel &lastModel, const DatabaseModel &newModel);
|
||||||
virtual QString diff(FieldModel *oldField, FieldModel *newField);
|
virtual QString diff(FieldModel *oldField, FieldModel *newField);
|
||||||
virtual QString diff(TableModel *oldTable, TableModel *newTable);
|
virtual QStringList diff(TableModel *oldTable, TableModel *newTable);
|
||||||
virtual QString diffRelation(TableModel *oldTable, TableModel *newTable);
|
virtual QStringList diffRelation(TableModel *oldTable, TableModel *newTable);
|
||||||
virtual QString diff(RelationModel *oldRel, RelationModel *newRel);
|
virtual QStringList diff(RelationModel *oldRel, RelationModel *newRel);
|
||||||
|
|
||||||
virtual QString join(const QString &mainTable,
|
virtual QString join(const QString &mainTable,
|
||||||
const QList<RelationModel*> list,
|
const QList<RelationModel*> &list,
|
||||||
QStringList *order = Q_NULLPTR);
|
QStringList *order = Q_NULLPTR);
|
||||||
virtual QString join(const QStringList &list, QStringList *order = Q_NULLPTR);
|
virtual QString join(const QStringList &list, QStringList *order = Q_NULLPTR);
|
||||||
|
|
||||||
|
|
@ -83,16 +104,17 @@ public:
|
||||||
|
|
||||||
virtual QString recordsPhrase(TableModel *table);
|
virtual QString recordsPhrase(TableModel *table);
|
||||||
|
|
||||||
|
virtual QString insertBulk(const QString &tableName, const PhraseList &ph, const QList<QVariantList> &vars);
|
||||||
virtual QString insertRecord(Table *t, QString tableName);
|
virtual QString insertRecord(Table *t, QString tableName);
|
||||||
virtual QString updateRecord(Table *t, QString tableName);
|
virtual QString updateRecord(Table *t, QString tableName);
|
||||||
virtual QString deleteRecord(Table *t, QString tableName);
|
virtual QString deleteRecord(Table *t, QString tableName);
|
||||||
virtual QString deleteRecords(QString tableName, QString where);
|
virtual QString deleteRecords(const QString &tableName, const QString &where);
|
||||||
|
|
||||||
virtual QString selectCommand(const QString &tableName,
|
virtual QString selectCommand(const QString &tableName,
|
||||||
const PhraseList &fields,
|
const PhraseList &fields,
|
||||||
const ConditionalPhrase &where,
|
const ConditionalPhrase &where,
|
||||||
const PhraseList &order,
|
const PhraseList &order,
|
||||||
const QList<RelationModel*> joins,
|
const QList<RelationModel *> &joins,
|
||||||
const int skip = -1,
|
const int skip = -1,
|
||||||
const int take = -1);
|
const int take = -1);
|
||||||
|
|
||||||
|
|
@ -123,18 +145,13 @@ public:
|
||||||
|
|
||||||
// virtual QString updateCommand(WherePhrase &phrase, QList<WherePhrase> &wheres, QString tableName);
|
// virtual QString updateCommand(WherePhrase &phrase, QList<WherePhrase> &wheres, QString tableName);
|
||||||
|
|
||||||
virtual QString escapeValue(const QVariant &v) const;
|
|
||||||
virtual QVariant readValue(const QVariant::Type &type, const QVariant &dbValue);
|
|
||||||
virtual QString phrase(const PhraseData *d) const;
|
virtual QString phrase(const PhraseData *d) const;
|
||||||
virtual QString operatorString(const PhraseData::Condition &cond) const;
|
virtual QString operatorString(const PhraseData::Condition &cond) const;
|
||||||
virtual void appendSkipTake(QString &sql, int skip = -1, int take = -1);
|
virtual void appendSkipTake(QString &sql, int skip = -1, int take = -1);
|
||||||
|
virtual QString primaryKeyConstraint(const TableModel *table) const;
|
||||||
|
|
||||||
virtual void replaceTableNames(QString &command);
|
|
||||||
virtual void removeTableNames(QString &command);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QString createConditionalPhrase(const PhraseData *d) const;
|
virtual QString createConditionalPhrase(const PhraseData *d) const;
|
||||||
QString createFieldPhrase(const PhraseList &ph);
|
QString createFieldPhrase(const PhraseList &ph);
|
||||||
QString createOrderPhrase(const PhraseList &ph);
|
QString createOrderPhrase(const PhraseList &ph);
|
||||||
void createInsertPhrase(const AssignmentPhraseList &ph, QString &fields, QString &values);
|
void createInsertPhrase(const AssignmentPhraseList &ph, QString &fields, QString &values);
|
||||||
|
|
|
||||||
|
|
@ -31,55 +31,178 @@ SqliteGenerator::SqliteGenerator(Database *parent) : SqlGeneratorBase(parent)
|
||||||
|
|
||||||
QString SqliteGenerator::fieldType(FieldModel *field)
|
QString SqliteGenerator::fieldType(FieldModel *field)
|
||||||
{
|
{
|
||||||
QString ret = field->name + " ";
|
|
||||||
QString dbType;
|
|
||||||
|
|
||||||
switch (field->type) {
|
switch (field->type) {
|
||||||
case QVariant::Bool:
|
case QMetaType::Bool: return "BOOLEAN";
|
||||||
dbType = "int";
|
case QMetaType::QBitArray:
|
||||||
break;
|
case QMetaType::QByteArray: return "BLOB";
|
||||||
case QVariant::ByteArray:
|
case QMetaType::QDate: return "DATE";
|
||||||
dbType = "blob";
|
case QMetaType::QDateTime: return "DATETIME";
|
||||||
break;
|
case QMetaType::QTime: return "TIME";
|
||||||
case QVariant::Date:
|
case QMetaType::Double: return "DOUBLE";
|
||||||
dbType = "date";
|
case QMetaType::Float: return "FLOAT";
|
||||||
break;
|
|
||||||
case QVariant::DateTime:
|
case QMetaType::SChar:
|
||||||
dbType = "datetime";
|
case QMetaType::Char: return "TINYINT";
|
||||||
break;
|
case QMetaType::UChar: return "TINYINT UNSIGNED";
|
||||||
case QVariant::Time:
|
case QMetaType::Short: return "SMALLINT";
|
||||||
dbType = "time";
|
case QMetaType::UShort: return "SMALLINT UNSIGNED";
|
||||||
break;
|
case QMetaType::Int: return "INT";
|
||||||
case QVariant::Double:
|
case QMetaType::UInt: return "INT UNSIGNED";
|
||||||
dbType = "real";
|
case QMetaType::Long: return "MEDIUMINT";
|
||||||
break;
|
case QMetaType::ULong: return "MEDIUMINT UNSIGNED";
|
||||||
case QVariant::Int:
|
case QMetaType::LongLong: return "BIGINT";
|
||||||
dbType = "integer";
|
case QMetaType::ULongLong: return "BIGINT UNSIGNED";
|
||||||
|
|
||||||
|
case QMetaType::QChar: return "NCHAR(1)";
|
||||||
|
|
||||||
|
case QMetaType::QUrl:
|
||||||
|
case QMetaType::QJsonArray:
|
||||||
|
case QMetaType::QJsonValue:
|
||||||
|
case QMetaType::QJsonObject:
|
||||||
|
case QMetaType::QJsonDocument:
|
||||||
|
case QMetaType::QPoint:
|
||||||
|
case QMetaType::QPointF:
|
||||||
|
case QMetaType::QSize:
|
||||||
|
case QMetaType::QSizeF:
|
||||||
|
case QMetaType::QLine:
|
||||||
|
case QMetaType::QLineF:
|
||||||
|
case QMetaType::QRect:
|
||||||
|
case QMetaType::QRectF:
|
||||||
|
case QMetaType::QPolygon:
|
||||||
|
case QMetaType::QPolygonF:
|
||||||
|
case QMetaType::QStringList:
|
||||||
|
case QMetaType::QColor:
|
||||||
|
case QMetaType::QUuid: return "TEXT";
|
||||||
|
|
||||||
// if (field->isAutoIncrement)
|
// if (field->isAutoIncrement)
|
||||||
// dbType.append(" PRIMARY KEY AUTOINCREMENT");
|
// dbType.append(" PRIMARY KEY AUTOINCREMENT");
|
||||||
break;
|
|
||||||
case QVariant::String:
|
|
||||||
if(field->length)
|
|
||||||
dbType = QString("varchar(%1)").arg(field->length);
|
|
||||||
else
|
|
||||||
dbType = "text";
|
|
||||||
break;
|
|
||||||
case QVariant::Uuid:
|
|
||||||
dbType = "text";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
dbType = QString();
|
|
||||||
}
|
|
||||||
|
|
||||||
return dbType;
|
case QMetaType::QString:
|
||||||
|
if(field->length)
|
||||||
|
return QString("VARCHAR(%1)").arg(field->length);
|
||||||
|
else
|
||||||
|
return "TEXT";
|
||||||
|
default:
|
||||||
|
// qWarning("The type (%s) does not supported",
|
||||||
|
// QMetaType::typeName(field->type));
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString SqliteGenerator::fieldDeclare(FieldModel *field)
|
||||||
|
{
|
||||||
|
QString type = fieldType(field);
|
||||||
|
if (type.isEmpty())
|
||||||
|
return type;
|
||||||
|
|
||||||
|
if (isNumeric(field->type) && field->isPrimaryKey) {
|
||||||
|
type = "INTEGER PRIMARY KEY";
|
||||||
|
if (field->isAutoIncrement)
|
||||||
|
type.append(" AUTOINCREMENT");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (field->notNull)
|
||||||
|
type.append(" NOT NULL");
|
||||||
|
|
||||||
|
return field->name + " " + type;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SqliteGenerator::supportAutoIncrement(const QMetaType::Type &type)
|
||||||
|
{
|
||||||
|
return isNumeric(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QStringList SqliteGenerator::diff(TableModel *oldTable, TableModel *newTable)
|
||||||
|
{
|
||||||
|
QStringList ret;
|
||||||
|
|
||||||
|
if (oldTable && newTable)
|
||||||
|
if (*oldTable == *newTable)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
QStringList newTableSql = SqlGeneratorBase::diff(nullptr, newTable);
|
||||||
|
|
||||||
|
if (!newTable)
|
||||||
|
return QStringList() << "DROP TABLE " + oldTable->name();
|
||||||
|
|
||||||
|
if (!oldTable)
|
||||||
|
return newTableSql;
|
||||||
|
|
||||||
|
QList<QString> fieldNames;
|
||||||
|
QList<QString> relations;
|
||||||
|
|
||||||
|
foreach (FieldModel *f, oldTable->fields())
|
||||||
|
if (!fieldNames.contains(f->name))
|
||||||
|
fieldNames.append(f->name);
|
||||||
|
foreach (RelationModel *r, oldTable->foregionKeys())
|
||||||
|
if (!relations.contains(r->localColumn))
|
||||||
|
relations.append(r->localColumn);
|
||||||
|
|
||||||
|
foreach (FieldModel *f, newTable->fields())
|
||||||
|
if (!fieldNames.contains(f->name))
|
||||||
|
fieldNames.append(f->name);
|
||||||
|
foreach (RelationModel *r, newTable->foregionKeys())
|
||||||
|
if (!relations.contains(r->localColumn))
|
||||||
|
relations.append(r->localColumn);
|
||||||
|
|
||||||
|
QString columns;
|
||||||
|
foreach (FieldModel *f, oldTable->fields()) {
|
||||||
|
if (!newTable->field(f->name))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!columns.isEmpty())
|
||||||
|
columns.append(", ");
|
||||||
|
columns.append(f->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
ALTER TABLE sampleTable RENAME TO sqlitestudio_temp_table;
|
||||||
|
|
||||||
|
CREATE TABLE sampleTable (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
t BIGINT,
|
||||||
|
m CHAR
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO sampleTable (
|
||||||
|
id,
|
||||||
|
t,
|
||||||
|
m
|
||||||
|
)
|
||||||
|
SELECT id,
|
||||||
|
t,
|
||||||
|
m
|
||||||
|
FROM sqlitestudio_temp_table;
|
||||||
|
|
||||||
|
DROP TABLE sqlitestudio_temp_table;
|
||||||
|
*/
|
||||||
|
|
||||||
|
ret.append("ALTER TABLE " + newTable->name() + " RENAME TO sqlitestudio_temp_table;");
|
||||||
|
ret.append(newTableSql);
|
||||||
|
ret.append(QString("INSERT INTO %1 ( %2 ) SELECT %2 FROM sqlitestudio_temp_table;")
|
||||||
|
.arg(newTable->name(), columns));
|
||||||
|
ret.append("DROP TABLE sqlitestudio_temp_table;");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
void SqliteGenerator::appendSkipTake(QString &sql, int skip, int take)
|
void SqliteGenerator::appendSkipTake(QString &sql, int skip, int take)
|
||||||
{
|
{
|
||||||
if (take != -1 && skip != -1)
|
if (take != -1 && skip != -1)
|
||||||
sql.append(QString(" LIMIT %1 OFFSET %2")
|
sql.append(QString(" LIMIT %1 OFFSET %2")
|
||||||
.arg(take)
|
.arg(take)
|
||||||
.arg(skip));
|
.arg(skip));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SqliteGenerator::primaryKeyConstraint(const TableModel *table) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(table);
|
||||||
|
return QString();
|
||||||
|
// QString sql = QString("CONSTRAINT pk_%1 PRIMARY KEY (%2)")
|
||||||
|
// .arg(table->name())
|
||||||
|
// .arg(table->primaryKey());
|
||||||
|
// if (table->field(table->primaryKey())->isAutoIncrement)
|
||||||
|
// sql += " AUTOINCREMENT";
|
||||||
|
// return sql;
|
||||||
}
|
}
|
||||||
|
|
||||||
NUT_END_NAMESPACE
|
NUT_END_NAMESPACE
|
||||||
|
|
|
||||||
|
|
@ -29,11 +29,18 @@ NUT_BEGIN_NAMESPACE
|
||||||
class SqliteGenerator : public SqlGeneratorBase
|
class SqliteGenerator : public SqlGeneratorBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit SqliteGenerator(Database *parent = 0);
|
explicit SqliteGenerator(Database *parent = nullptr);
|
||||||
|
|
||||||
QString fieldType(FieldModel *field);
|
QString fieldType(FieldModel *field) override;
|
||||||
|
QString fieldDeclare(FieldModel *field) override;
|
||||||
|
|
||||||
|
bool supportAutoIncrement(const QMetaType::Type &type) override;
|
||||||
|
|
||||||
|
void appendSkipTake(QString &sql, int skip, int take) override;
|
||||||
|
|
||||||
|
QString primaryKeyConstraint(const TableModel *table) const override;
|
||||||
|
QStringList diff(TableModel *oldTable, TableModel *newTable) override;
|
||||||
|
|
||||||
void appendSkipTake(QString &sql, int skip, int take);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
NUT_END_NAMESPACE
|
NUT_END_NAMESPACE
|
||||||
|
|
|
||||||
|
|
@ -45,10 +45,44 @@ QString SqlServerGenerator::fieldType(FieldModel *field)
|
||||||
QString dbType;
|
QString dbType;
|
||||||
|
|
||||||
switch (field->type) {
|
switch (field->type) {
|
||||||
case QVariant::Bool:
|
case QMetaType::Bool:
|
||||||
dbType = "BIT";
|
dbType = "BIT";
|
||||||
break;
|
break;
|
||||||
case QVariant::ByteArray:
|
|
||||||
|
case QMetaType::Char:
|
||||||
|
case QMetaType::QChar:
|
||||||
|
dbType = "CHAR(1)";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QMetaType::SChar:
|
||||||
|
case QMetaType::UChar:
|
||||||
|
return "tinyint";
|
||||||
|
|
||||||
|
case QMetaType::Short:
|
||||||
|
case QMetaType::UShort:
|
||||||
|
return "smallint";
|
||||||
|
|
||||||
|
case QMetaType::UInt:
|
||||||
|
case QMetaType::Int:
|
||||||
|
dbType = "INT";
|
||||||
|
if (field->isAutoIncrement)
|
||||||
|
dbType += " IDENTITY(1,1)";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QMetaType::Long:
|
||||||
|
case QMetaType::ULong:
|
||||||
|
case QMetaType::LongLong:
|
||||||
|
case QMetaType::ULongLong:
|
||||||
|
return "bigint";
|
||||||
|
|
||||||
|
case QMetaType::Float:
|
||||||
|
return "FLOAT(24)";
|
||||||
|
|
||||||
|
case QMetaType::Double:
|
||||||
|
return "REAL";
|
||||||
|
|
||||||
|
case QMetaType::QBitArray:
|
||||||
|
case QMetaType::QByteArray:
|
||||||
dbType = "VARBINARY";
|
dbType = "VARBINARY";
|
||||||
|
|
||||||
if (field->length)
|
if (field->length)
|
||||||
|
|
@ -56,42 +90,51 @@ QString SqlServerGenerator::fieldType(FieldModel *field)
|
||||||
else
|
else
|
||||||
dbType.append(" (MAX)");
|
dbType.append(" (MAX)");
|
||||||
break;
|
break;
|
||||||
case QVariant::Date:
|
case QMetaType::QDate:
|
||||||
dbType = "DATE";
|
dbType = "DATE";
|
||||||
break;
|
break;
|
||||||
case QVariant::DateTime:
|
case QMetaType::QDateTime:
|
||||||
dbType = "DATETIME";
|
dbType = "DATETIME";
|
||||||
break;
|
break;
|
||||||
case QVariant::Time:
|
case QMetaType::QTime:
|
||||||
dbType = "TIME";
|
dbType = "TIME";
|
||||||
break;
|
break;
|
||||||
case QVariant::Double:
|
|
||||||
dbType = "REAL";
|
|
||||||
break;
|
|
||||||
case QVariant::Int:
|
|
||||||
dbType = "INT";
|
|
||||||
if (field->isAutoIncrement)
|
|
||||||
dbType += " IDENTITY(1,1)";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case QVariant::Point:
|
case QMetaType::QPoint:
|
||||||
case QVariant::PointF:
|
case QMetaType::QPointF:
|
||||||
dbType = "GEOMETRY";
|
dbType = "GEOMETRY";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QVariant::String:
|
case QMetaType::QString:
|
||||||
if (field->length)
|
if (field->length)
|
||||||
dbType = QString("NVARCHAR(%1)").arg(field->length);
|
dbType = QString("NVARCHAR(%1)").arg(field->length);
|
||||||
else
|
else
|
||||||
dbType = "NVARCHAR(MAX)";
|
dbType = "NVARCHAR(MAX)";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QVariant::Uuid:
|
case QMetaType::QUuid:
|
||||||
dbType = "UNIQUEIDENTIFIER";
|
dbType = "UNIQUEIDENTIFIER";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case QMetaType::QPolygon:
|
||||||
|
case QMetaType::QPolygonF:
|
||||||
|
case QMetaType::QSize:
|
||||||
|
case QMetaType::QSizeF:
|
||||||
|
case QMetaType::QRect:
|
||||||
|
case QMetaType::QRectF:
|
||||||
|
case QMetaType::QLine:
|
||||||
|
case QMetaType::QLineF:
|
||||||
|
case QMetaType::QColor:
|
||||||
|
case QMetaType::QStringList:
|
||||||
|
case QMetaType::QJsonArray:
|
||||||
|
case QMetaType::QJsonValue:
|
||||||
|
case QMetaType::QJsonObject:
|
||||||
|
case QMetaType::QJsonDocument:
|
||||||
|
case QMetaType::QUrl:
|
||||||
|
return "TEXT";
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Q_UNREACHABLE();
|
// Q_UNREACHABLE();
|
||||||
dbType = QString();
|
dbType = QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -103,7 +146,7 @@ QString SqlServerGenerator::diff(FieldModel *oldField, FieldModel *newField)
|
||||||
QString sql = QString();
|
QString sql = QString();
|
||||||
if (oldField && newField)
|
if (oldField && newField)
|
||||||
if (*oldField == *newField)
|
if (*oldField == *newField)
|
||||||
return QString();
|
return sql;
|
||||||
|
|
||||||
if (!newField) {
|
if (!newField) {
|
||||||
sql = "DROP COLUMN " + oldField->name;
|
sql = "DROP COLUMN " + oldField->name;
|
||||||
|
|
@ -120,13 +163,15 @@ QString SqlServerGenerator::diff(FieldModel *oldField, FieldModel *newField)
|
||||||
|
|
||||||
QString SqlServerGenerator::escapeValue(const QVariant &v) const
|
QString SqlServerGenerator::escapeValue(const QVariant &v) const
|
||||||
{
|
{
|
||||||
if (v.type() == QVariant::String || v.type() == QVariant::Char)
|
auto mid = static_cast<QMetaType::Type>(v.userType());
|
||||||
|
|
||||||
|
if (mid == QMetaType::QString || mid == QMetaType::QChar)
|
||||||
return "N'" + v.toString() + "'";
|
return "N'" + v.toString() + "'";
|
||||||
else if (v.type() == QVariant::Point) {
|
else if (mid == QMetaType::QPoint) {
|
||||||
QPoint pt = v.toPoint();
|
QPoint pt = v.toPoint();
|
||||||
return QString("geography::POINT(%1, %2, 4326)").arg(pt.x()).arg(
|
return QString("geography::POINT(%1, %2, 4326)").arg(pt.x()).arg(
|
||||||
pt.y());
|
pt.y());
|
||||||
} else if (v.type() == QVariant::PointF) {
|
} else if (mid == QMetaType::QPointF) {
|
||||||
QPointF pt = v.toPointF();
|
QPointF pt = v.toPointF();
|
||||||
return QString("geography::POINT(%1, %2, 4326)").arg(pt.x()).arg(
|
return QString("geography::POINT(%1, %2, 4326)").arg(pt.x()).arg(
|
||||||
pt.y());
|
pt.y());
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ NUT_BEGIN_NAMESPACE
|
||||||
class SqlServerGenerator : public SqlGeneratorBase
|
class SqlServerGenerator : public SqlGeneratorBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit SqlServerGenerator(Database *parent = 0);
|
explicit SqlServerGenerator(Database *parent = nullptr);
|
||||||
|
|
||||||
QString masterDatabaseName(QString databaseName);
|
QString masterDatabaseName(QString databaseName);
|
||||||
|
|
||||||
|
|
|
||||||
534
src/phrase.cpp
534
src/phrase.cpp
|
|
@ -24,275 +24,9 @@
|
||||||
|
|
||||||
NUT_BEGIN_NAMESPACE
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
PhraseData::PhraseData() :
|
|
||||||
className(""), fieldName(""),
|
|
||||||
type(Field), operatorCond(NotAssign),
|
|
||||||
left(0), right(0), operand(QVariant::Invalid), isNot(false), parents(1)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
PhraseData::PhraseData(const char *className, const char *fieldName) :
|
|
||||||
className(className), fieldName(fieldName),
|
|
||||||
type(Field), operatorCond(NotAssign),
|
|
||||||
left(0), right(0), operand(QVariant::Invalid), isNot(false), parents(1)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
PhraseData::PhraseData(PhraseData *l, PhraseData::Condition o)
|
|
||||||
: className(0), fieldName(0),
|
|
||||||
type(WithoutOperand), operatorCond(o), left(l), right(0),
|
|
||||||
isNot(false), parents(1)
|
|
||||||
{
|
|
||||||
l->parents++;
|
|
||||||
}
|
|
||||||
|
|
||||||
PhraseData::PhraseData(PhraseData *l, PhraseData::Condition o,
|
|
||||||
PhraseData *r)
|
|
||||||
: className(0), fieldName(0),
|
|
||||||
type(WithOther), operatorCond(o),
|
|
||||||
left(l), right(r),
|
|
||||||
isNot(false), parents(1)
|
|
||||||
{
|
|
||||||
l->parents++;
|
|
||||||
r->parents++;
|
|
||||||
}
|
|
||||||
|
|
||||||
PhraseData::PhraseData(PhraseData *l, PhraseData::Condition o, QVariant r)
|
|
||||||
: className(0), fieldName(0),
|
|
||||||
type(WithVariant), operatorCond(o), left(l),
|
|
||||||
right(0), operand(r), isNot(false), parents(1)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
PhraseData *PhraseData::operator =(PhraseData *other)
|
|
||||||
{
|
|
||||||
other->parents++;
|
|
||||||
return other;
|
|
||||||
}
|
|
||||||
|
|
||||||
PhraseData &PhraseData::operator =(PhraseData &other)
|
|
||||||
{
|
|
||||||
other.parents++;
|
|
||||||
return other;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString PhraseData::toString() const
|
|
||||||
{
|
|
||||||
return QString("[%1].%2").arg(className).arg(fieldName);
|
|
||||||
}
|
|
||||||
|
|
||||||
PhraseData::~PhraseData()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void PhraseData::cleanUp()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void PhraseData::cleanUp(PhraseData *d)
|
|
||||||
{
|
|
||||||
if (d->left)
|
|
||||||
cleanUp(d->left);
|
|
||||||
if (d->right)
|
|
||||||
cleanUp(d->right);
|
|
||||||
}
|
|
||||||
|
|
||||||
AbstractFieldPhrase::AbstractFieldPhrase(PhraseData *d) : data(d)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
AbstractFieldPhrase::AbstractFieldPhrase(const char *className,
|
|
||||||
const char *fieldName)
|
|
||||||
:data(new PhraseData(className, fieldName))
|
|
||||||
{
|
|
||||||
qDebug() <<"AbstractFieldPhrase created"<<className<<fieldName;
|
|
||||||
}
|
|
||||||
|
|
||||||
AbstractFieldPhrase::AbstractFieldPhrase(const AbstractFieldPhrase &other)
|
|
||||||
{
|
|
||||||
data = other.data;
|
|
||||||
data->parents++;
|
|
||||||
qDebug() <<"Copy ctor"<<other.data->toString()<<other.data->parents;
|
|
||||||
}
|
|
||||||
|
|
||||||
AbstractFieldPhrase::AbstractFieldPhrase(AbstractFieldPhrase &&other)
|
|
||||||
{
|
|
||||||
data = other.data;
|
|
||||||
data->parents++;
|
|
||||||
other.data = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
AbstractFieldPhrase::~AbstractFieldPhrase()
|
|
||||||
{
|
|
||||||
if (data) {
|
|
||||||
--data->parents;
|
|
||||||
if (data->parents <= 0)
|
|
||||||
delete data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PhraseList AbstractFieldPhrase::operator |(const AbstractFieldPhrase &other)
|
|
||||||
{
|
|
||||||
return PhraseList(this, other);
|
|
||||||
}
|
|
||||||
|
|
||||||
ConditionalPhrase AbstractFieldPhrase::isNull()
|
|
||||||
{
|
|
||||||
return ConditionalPhrase(this, PhraseData::Null);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ConditionalPhrase AbstractFieldPhrase::operator ==(const ConditionalPhrase
|
|
||||||
&other)
|
|
||||||
{
|
|
||||||
return ConditionalPhrase(this, PhraseData::Equal,
|
|
||||||
const_cast<ConditionalPhrase&>(other));
|
|
||||||
}
|
|
||||||
|
|
||||||
#define AbstractFieldPhraseOperatorVariant(class, op, cond) \
|
|
||||||
ConditionalPhrase class::operator op(const QVariant &other) \
|
|
||||||
{ \
|
|
||||||
return ConditionalPhrase(this, cond, other); \
|
|
||||||
}
|
|
||||||
|
|
||||||
AbstractFieldPhraseOperatorVariant(AbstractFieldPhrase, ==, PhraseData::Equal)
|
|
||||||
AbstractFieldPhraseOperatorVariant(AbstractFieldPhrase, !=, PhraseData::NotEqual)
|
|
||||||
|
|
||||||
#define AbstractFieldPhraseOperatorField(op, cond) \
|
|
||||||
ConditionalPhrase AbstractFieldPhrase::operator op(const AbstractFieldPhrase &other) \
|
|
||||||
{ \
|
|
||||||
return ConditionalPhrase(this, cond, other); \
|
|
||||||
}
|
|
||||||
|
|
||||||
AbstractFieldPhraseOperatorField(==, PhraseData::Equal)
|
|
||||||
AbstractFieldPhraseOperatorField(!=, PhraseData::NotEqual)
|
|
||||||
AbstractFieldPhraseOperatorField(< , PhraseData::Less)
|
|
||||||
AbstractFieldPhraseOperatorField(<=, PhraseData::LessEqual)
|
|
||||||
AbstractFieldPhraseOperatorField(> , PhraseData::Greater)
|
|
||||||
AbstractFieldPhraseOperatorField(>=, PhraseData::GreaterEqual)
|
|
||||||
|
|
||||||
AbstractFieldPhrase AbstractFieldPhrase::operator !()
|
|
||||||
{
|
|
||||||
|
|
||||||
AbstractFieldPhrase f(data->className, data->fieldName);
|
|
||||||
f.data->isNot = !data->isNot;
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
AssignmentPhrase AbstractFieldPhrase::operator =(const QVariant &other)
|
|
||||||
{
|
|
||||||
return AssignmentPhrase(this, other);
|
|
||||||
}
|
|
||||||
|
|
||||||
AssignmentPhrase AbstractFieldPhrase::operator <<(const QVariant &other)
|
|
||||||
{
|
|
||||||
return AssignmentPhrase(this, other);
|
|
||||||
}
|
|
||||||
|
|
||||||
PhraseList::PhraseList() : isValid(false)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
PhraseList::PhraseList(const PhraseList &other) : isValid(true)
|
|
||||||
{
|
|
||||||
data = qMove(other.data);
|
|
||||||
const_cast<PhraseList&>(other).data.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
PhraseList::PhraseList(PhraseList &&other)
|
|
||||||
{
|
|
||||||
data = other.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
PhraseList::PhraseList(const AbstractFieldPhrase &other) : isValid(true)
|
|
||||||
{
|
|
||||||
data.append(other.data);
|
|
||||||
incAllDataParents();
|
|
||||||
}
|
|
||||||
|
|
||||||
PhraseList::PhraseList(const AbstractFieldPhrase *left,
|
|
||||||
const AbstractFieldPhrase &right)
|
|
||||||
: isValid(true)
|
|
||||||
{
|
|
||||||
data.append(left->data);
|
|
||||||
data.append(right.data);
|
|
||||||
incAllDataParents();
|
|
||||||
}
|
|
||||||
|
|
||||||
PhraseList::PhraseList(PhraseList *left, PhraseList *right) : isValid(true)
|
|
||||||
{
|
|
||||||
// data = qMove(left->data + right->data);
|
|
||||||
data.append(left->data);
|
|
||||||
data.append(right->data);
|
|
||||||
// left->data.clear();
|
|
||||||
// right->data.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
PhraseList::PhraseList(PhraseList *left, const AbstractFieldPhrase *right)
|
|
||||||
: isValid(true)
|
|
||||||
{
|
|
||||||
data.append(left->data);
|
|
||||||
data.append(right->data);
|
|
||||||
incAllDataParents();
|
|
||||||
}
|
|
||||||
|
|
||||||
PhraseList::~PhraseList()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PhraseList &PhraseList::operator =(const PhraseList &other)
|
|
||||||
{
|
|
||||||
data.append(const_cast<PhraseList&>(other).data);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
PhraseList PhraseList::operator |(const AbstractFieldPhrase &other) {
|
|
||||||
return PhraseList(this, &other);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PhraseList::incAllDataParents()
|
|
||||||
{
|
|
||||||
// foreach (PhraseData *d, data)
|
|
||||||
// d->parents++;
|
|
||||||
}
|
|
||||||
|
|
||||||
PhraseList PhraseList::operator |(PhraseList &other) {
|
|
||||||
return PhraseList(this, &other);
|
|
||||||
}
|
|
||||||
|
|
||||||
AssignmentPhrase::AssignmentPhrase(PhraseData *d) : data(d)
|
|
||||||
{
|
|
||||||
d->parents++;
|
|
||||||
}
|
|
||||||
|
|
||||||
AssignmentPhrase::AssignmentPhrase(AbstractFieldPhrase *l, const QVariant r)
|
|
||||||
{
|
|
||||||
|
|
||||||
data = new PhraseData(l->data, PhraseData::Equal, r);
|
|
||||||
// l->data = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
AssignmentPhrase::AssignmentPhrase(AbstractFieldPhrase *l,
|
|
||||||
const AssignmentPhrase *r)
|
|
||||||
{
|
|
||||||
data = new PhraseData(l->data, PhraseData::Equal, r->data);
|
|
||||||
// l->data = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
AssignmentPhrase::AssignmentPhrase(AssignmentPhrase *ph, const QVariant &v)
|
|
||||||
{
|
|
||||||
data = new PhraseData(ph->data, PhraseData::Equal, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
//AssignmentPhrase::AssignmentPhrase(AssignmentPhrase &other)
|
|
||||||
//{
|
|
||||||
// data = other.data;
|
|
||||||
// other.data = 0;
|
|
||||||
//}
|
|
||||||
|
|
||||||
AssignmentPhrase::~AssignmentPhrase()
|
|
||||||
{
|
|
||||||
if (data)
|
|
||||||
if (!--data->parents)
|
|
||||||
delete data;
|
|
||||||
}
|
|
||||||
|
|
||||||
//AssignmentPhrase::AssignmentPhrase(AssignmentPhrase *l, const AssignmentPhrase *r)
|
//AssignmentPhrase::AssignmentPhrase(AssignmentPhrase *l, const AssignmentPhrase *r)
|
||||||
//{
|
//{
|
||||||
|
|
@ -300,278 +34,10 @@ AssignmentPhrase::~AssignmentPhrase()
|
||||||
// qFatal("SS");
|
// qFatal("SS");
|
||||||
//}
|
//}
|
||||||
|
|
||||||
AssignmentPhraseList AssignmentPhrase::operator &(const AssignmentPhrase &other)
|
|
||||||
{
|
|
||||||
return AssignmentPhraseList(this, &other);
|
|
||||||
}
|
|
||||||
|
|
||||||
AssignmentPhraseList::AssignmentPhraseList()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
AssignmentPhraseList::AssignmentPhraseList(const AssignmentPhrase &l)
|
|
||||||
{
|
|
||||||
data.append(l.data);
|
|
||||||
incAllDataParents();
|
|
||||||
}
|
|
||||||
|
|
||||||
AssignmentPhraseList::AssignmentPhraseList(AssignmentPhraseList *l,
|
|
||||||
const AssignmentPhrase *r)
|
|
||||||
{
|
|
||||||
data.append(l->data);
|
|
||||||
data.append(r->data);
|
|
||||||
incAllDataParents();
|
|
||||||
}
|
|
||||||
|
|
||||||
AssignmentPhraseList::AssignmentPhraseList(AssignmentPhrase *l,
|
|
||||||
const AssignmentPhrase *r)
|
|
||||||
{
|
|
||||||
data.append(l->data);
|
|
||||||
data.append(r->data);
|
|
||||||
incAllDataParents();
|
|
||||||
}
|
|
||||||
|
|
||||||
AssignmentPhraseList::AssignmentPhraseList(const AssignmentPhrase &r,
|
|
||||||
const AssignmentPhrase &l)
|
|
||||||
{
|
|
||||||
data.append(l.data);
|
|
||||||
data.append(r.data);
|
|
||||||
incAllDataParents();
|
|
||||||
}
|
|
||||||
|
|
||||||
AssignmentPhraseList AssignmentPhraseList::operator &(const AssignmentPhrase
|
|
||||||
&ph)
|
|
||||||
{
|
|
||||||
return AssignmentPhraseList(this, &ph);
|
|
||||||
}
|
|
||||||
|
|
||||||
AssignmentPhraseList::~AssignmentPhraseList()
|
|
||||||
{
|
|
||||||
foreach (PhraseData *d, data)
|
|
||||||
if (!--d->parents)
|
|
||||||
delete d;
|
|
||||||
// qDeleteAll(data);
|
|
||||||
// data.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AssignmentPhraseList::incAllDataParents()
|
|
||||||
{
|
|
||||||
foreach (PhraseData *d, data)
|
|
||||||
d->parents++;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConditionalPhrase::ConditionalPhrase() : data(0)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
ConditionalPhrase::ConditionalPhrase(const ConditionalPhrase &other)
|
|
||||||
{
|
|
||||||
qDebug() << "************* ctor called:";
|
|
||||||
data = other.data;
|
|
||||||
data->parents++;
|
|
||||||
// const_cast<ConditionalPhrase&>(other).data = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef Q_COMPILER_RVALUE_REFS
|
|
||||||
ConditionalPhrase::ConditionalPhrase(const ConditionalPhrase &&other)
|
|
||||||
{
|
|
||||||
qDebug() << "************* ctor called:";
|
|
||||||
this->data = qMove(other.data);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ConditionalPhrase::ConditionalPhrase(const PhraseData *data)
|
|
||||||
{
|
|
||||||
this->data = const_cast<PhraseData*>(data);
|
|
||||||
this->data->parents++;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConditionalPhrase::ConditionalPhrase(AbstractFieldPhrase *l,
|
|
||||||
PhraseData::Condition cond)
|
|
||||||
{
|
|
||||||
data = new PhraseData(l->data, cond);
|
|
||||||
}
|
|
||||||
|
|
||||||
ConditionalPhrase::ConditionalPhrase(AbstractFieldPhrase *l,
|
|
||||||
PhraseData::Condition cond,
|
|
||||||
const QVariant &v)
|
|
||||||
{
|
|
||||||
data = new PhraseData(l->data, cond, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
ConditionalPhrase::ConditionalPhrase(AbstractFieldPhrase *l,
|
|
||||||
PhraseData::Condition cond,
|
|
||||||
const AbstractFieldPhrase &other)
|
|
||||||
{
|
|
||||||
data = new PhraseData(l->data, cond, other.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
ConditionalPhrase::ConditionalPhrase(AbstractFieldPhrase *l,
|
|
||||||
PhraseData::Condition cond,
|
|
||||||
ConditionalPhrase &r)
|
|
||||||
{
|
|
||||||
data = new PhraseData(l->data, cond, r.data);
|
|
||||||
r.data = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConditionalPhrase::ConditionalPhrase(ConditionalPhrase *l,
|
|
||||||
PhraseData::Condition cond,
|
|
||||||
const AbstractFieldPhrase &r)
|
|
||||||
{
|
|
||||||
data = new PhraseData(l->data, cond, r.data);
|
|
||||||
l->data = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConditionalPhrase::ConditionalPhrase(ConditionalPhrase *l,
|
|
||||||
PhraseData::Condition cond,
|
|
||||||
const QVariant &r)
|
|
||||||
{
|
|
||||||
data = new PhraseData(l->data, cond, r);
|
|
||||||
l->data = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConditionalPhrase::ConditionalPhrase(ConditionalPhrase *l,
|
|
||||||
PhraseData::Condition cond,
|
|
||||||
ConditionalPhrase &r)
|
|
||||||
{
|
|
||||||
data = new PhraseData(l->data, cond, r.data);
|
|
||||||
l->data = 0;
|
|
||||||
r.data = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConditionalPhrase::~ConditionalPhrase()
|
|
||||||
{
|
|
||||||
if (data) {
|
|
||||||
data->cleanUp();
|
|
||||||
if (!--data->parents)
|
|
||||||
delete data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ConditionalPhrase &ConditionalPhrase::operator =(const ConditionalPhrase &other)
|
|
||||||
{
|
|
||||||
data = other.data;
|
|
||||||
data->parents++;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
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) \
|
|
||||||
{ \
|
|
||||||
ConditionalPhrase p; \
|
|
||||||
p.data = new PhraseData; \
|
|
||||||
p.data->operatorCond = cond; \
|
|
||||||
p.data->left = l.data; \
|
|
||||||
p.data->right = r.data; \
|
|
||||||
l.data->parents++; \
|
|
||||||
r.data->parents++; \
|
|
||||||
return p; \
|
|
||||||
} \
|
|
||||||
ConditionalPhrase operator op(const ConditionalPhrase &l, \
|
|
||||||
ConditionalPhrase &&r) \
|
|
||||||
{ \
|
|
||||||
ConditionalPhrase p; \
|
|
||||||
p.data = new PhraseData; \
|
|
||||||
p.data->operatorCond = cond; \
|
|
||||||
p.data->left = l.data; \
|
|
||||||
p.data->right = r.data; \
|
|
||||||
l.data->parents++; \
|
|
||||||
r.data->parents++; \
|
|
||||||
return p; \
|
|
||||||
} \
|
|
||||||
ConditionalPhrase operator op(ConditionalPhrase &&l, \
|
|
||||||
const ConditionalPhrase &r) \
|
|
||||||
{ \
|
|
||||||
ConditionalPhrase p; \
|
|
||||||
p.data = new PhraseData; \
|
|
||||||
p.data->operatorCond = cond; \
|
|
||||||
p.data->left = l.data; \
|
|
||||||
p.data->right = r.data; \
|
|
||||||
l.data->parents++; \
|
|
||||||
r.data->parents++; \
|
|
||||||
return p; \
|
|
||||||
} \
|
|
||||||
ConditionalPhrase operator op(ConditionalPhrase &&l, ConditionalPhrase &&r) \
|
|
||||||
{ \
|
|
||||||
ConditionalPhrase p; \
|
|
||||||
p.data = new PhraseData; \
|
|
||||||
p.data->operatorCond = cond; \
|
|
||||||
p.data->left = l.data; \
|
|
||||||
p.data->right = r.data; \
|
|
||||||
l.data->parents++; \
|
|
||||||
r.data->parents++; \
|
|
||||||
return p; \
|
|
||||||
}
|
|
||||||
|
|
||||||
DECLARE_CONDITIONALPHRASE_OPERATORS_IMPL(==, PhraseData::Equal)
|
|
||||||
DECLARE_CONDITIONALPHRASE_OPERATORS_IMPL(||, PhraseData::Or)
|
|
||||||
DECLARE_CONDITIONALPHRASE_OPERATORS_IMPL(&&, PhraseData::And)
|
|
||||||
|
|
||||||
ConditionalPhrase ConditionalPhrase::operator !()
|
|
||||||
{
|
|
||||||
ConditionalPhrase f(data);
|
|
||||||
f.data->isNot = !data->isNot;
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
PhraseDataList::PhraseDataList() : QList<PhraseData*>()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
PhraseDataList::PhraseDataList(const PhraseDataList &other) : QList<PhraseData*>()
|
|
||||||
{
|
|
||||||
PhraseDataList &o = const_cast<PhraseDataList&>(other);
|
|
||||||
PhraseDataList::iterator i;
|
|
||||||
for (i = o.begin(); i != o.end(); ++i)
|
|
||||||
append(*i);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PhraseDataList::append(PhraseData *d)
|
|
||||||
{
|
|
||||||
d->parents++;
|
|
||||||
QList<PhraseData*>::append(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PhraseDataList::append(QList<PhraseData *> &dl)
|
|
||||||
{
|
|
||||||
foreach (PhraseData *d, dl)
|
|
||||||
d->parents++;
|
|
||||||
QList<PhraseData*>::append(dl);
|
|
||||||
}
|
|
||||||
|
|
||||||
PhraseDataList::~PhraseDataList()
|
|
||||||
{
|
|
||||||
QList<PhraseData*>::iterator i;
|
|
||||||
for (i = begin(); i != end(); ++i) {
|
|
||||||
(*i)->cleanUp();
|
|
||||||
if (!--(*i)->parents)
|
|
||||||
delete *i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//AssignmentPhraseList operator &(const AssignmentPhrase &l, const AssignmentPhrase &r)
|
//AssignmentPhraseList operator &(const AssignmentPhrase &l, const AssignmentPhrase &r)
|
||||||
//{
|
//{
|
||||||
|
|
|
||||||
446
src/phrase.h
446
src/phrase.h
|
|
@ -21,15 +21,16 @@
|
||||||
#ifndef PHRASE_H
|
#ifndef PHRASE_H
|
||||||
#define PHRASE_H
|
#define PHRASE_H
|
||||||
|
|
||||||
#include <QSharedPointer>
|
#include "phrases/conditionalphrase.h"
|
||||||
#include <QString>
|
#include "phrases/abstractfieldphrase.h"
|
||||||
#include <QVariant>
|
#include "phrases/fieldphrase.h"
|
||||||
#include <QtGlobal>
|
#include "phrases/phraselist.h"
|
||||||
#ifdef Q_COMPILER_INITIALIZER_LISTS
|
#include "phrases/assignmentphraselist.h"
|
||||||
# include <initializer_list>
|
#include "phrases/phrasedatalist.h"
|
||||||
#endif
|
#include "phrases/phrasedata.h"
|
||||||
|
#include "phrases/assignmentphrase.h"
|
||||||
#include "defines.h"
|
#include "phrases/numericphrase.h"
|
||||||
|
#include "phrases/datephrase.h"
|
||||||
|
|
||||||
NUT_BEGIN_NAMESPACE
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
|
@ -43,426 +44,29 @@ class AbstractFieldPhrase;
|
||||||
class AssignmentPhrase;
|
class AssignmentPhrase;
|
||||||
class PhraseList;
|
class PhraseList;
|
||||||
|
|
||||||
class PhraseData
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum Condition {
|
|
||||||
NotAssign = 0,
|
|
||||||
Equal,
|
|
||||||
Less,
|
|
||||||
LessEqual,
|
|
||||||
Null,
|
|
||||||
In,
|
|
||||||
Like,
|
|
||||||
|
|
||||||
Not = 10,
|
|
||||||
NotEqual,
|
|
||||||
GreaterEqual,
|
|
||||||
Greater,
|
|
||||||
NotNull,
|
|
||||||
NotIn,
|
|
||||||
NotLike,
|
|
||||||
|
|
||||||
And = 20,
|
|
||||||
Or,
|
|
||||||
|
|
||||||
Add,
|
|
||||||
Minus,
|
|
||||||
Multiple,
|
|
||||||
Divide,
|
|
||||||
Mod,
|
|
||||||
|
|
||||||
Between,
|
|
||||||
|
|
||||||
//date and time
|
|
||||||
AddYears,
|
|
||||||
AddMonths,
|
|
||||||
AddDays,
|
|
||||||
AddHours,
|
|
||||||
AddMinutes,
|
|
||||||
AddSeconds
|
|
||||||
// // special types
|
|
||||||
// Distance
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Type { Field, WithVariant, WithOther, WithoutOperand };
|
|
||||||
|
|
||||||
const char *className;
|
|
||||||
const char *fieldName;
|
|
||||||
|
|
||||||
Type type;
|
|
||||||
|
|
||||||
PhraseData *left;
|
|
||||||
PhraseData *right;
|
|
||||||
|
|
||||||
QVariant operand;
|
|
||||||
Condition operatorCond;
|
|
||||||
bool isNot;
|
|
||||||
quint16 parents;
|
|
||||||
|
|
||||||
PhraseData();
|
|
||||||
PhraseData(const char *className, const char *fieldName);
|
|
||||||
PhraseData(PhraseData *l, Condition o);
|
|
||||||
PhraseData(PhraseData *l, Condition o, PhraseData *r);
|
|
||||||
PhraseData(PhraseData *l, Condition o, QVariant r);
|
|
||||||
// explicit PhraseData(const PhraseData &other);
|
|
||||||
// explicit PhraseData(const PhraseData *other);
|
|
||||||
|
|
||||||
PhraseData *operator =(PhraseData *other);
|
|
||||||
PhraseData &operator =(PhraseData &other);
|
|
||||||
|
|
||||||
QString toString() const;
|
|
||||||
|
|
||||||
~PhraseData();
|
|
||||||
|
|
||||||
void cleanUp();
|
|
||||||
private:
|
|
||||||
void cleanUp(PhraseData *d);
|
|
||||||
};
|
|
||||||
|
|
||||||
class PhraseDataList : public QList<PhraseData*>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PhraseDataList();
|
|
||||||
PhraseDataList(const PhraseDataList &other);
|
|
||||||
void append(PhraseData *d);
|
|
||||||
void append(QList<PhraseData*> &dl);
|
|
||||||
virtual ~PhraseDataList();
|
|
||||||
};
|
|
||||||
|
|
||||||
class AssignmentPhraseList
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QList<PhraseData*> data;
|
|
||||||
explicit AssignmentPhraseList();
|
|
||||||
AssignmentPhraseList(const AssignmentPhrase &l);
|
|
||||||
AssignmentPhraseList(AssignmentPhraseList *l, const AssignmentPhrase *r);
|
|
||||||
AssignmentPhraseList(AssignmentPhrase *l, const AssignmentPhrase *r);
|
|
||||||
AssignmentPhraseList(const AssignmentPhrase &r, const AssignmentPhrase &l);
|
|
||||||
|
|
||||||
AssignmentPhraseList operator &(const AssignmentPhrase &ph);
|
|
||||||
|
|
||||||
~AssignmentPhraseList();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void incAllDataParents();
|
|
||||||
};
|
|
||||||
|
|
||||||
class AssignmentPhrase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PhraseData *data;
|
|
||||||
explicit AssignmentPhrase(PhraseData *d);
|
|
||||||
explicit AssignmentPhrase(AbstractFieldPhrase *l, const QVariant r);
|
|
||||||
explicit AssignmentPhrase(AbstractFieldPhrase *l, const AssignmentPhrase *r);
|
|
||||||
explicit AssignmentPhrase(AssignmentPhrase *ph, const QVariant &v);
|
|
||||||
// explicit AssignmentPhrase(AssignmentPhrase &other);
|
|
||||||
~AssignmentPhrase();
|
|
||||||
// AssignmentPhrase(AssignmentPhrase *l, const AssignmentPhrase *r);
|
|
||||||
|
|
||||||
AssignmentPhraseList operator &(const AssignmentPhrase &other);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
//AssignmentPhraseList operator &(const AssignmentPhrase &l, const AssignmentPhrase &r);
|
//AssignmentPhraseList operator &(const AssignmentPhrase &l, const AssignmentPhrase &r);
|
||||||
//AssignmentPhraseList operator &(const AssignmentPhrase &l, AssignmentPhrase &&r);
|
//AssignmentPhraseList operator &(const AssignmentPhrase &l, AssignmentPhrase &&r);
|
||||||
//AssignmentPhraseList operator &(AssignmentPhrase &&l, const AssignmentPhrase &r);
|
//AssignmentPhraseList operator &(AssignmentPhrase &&l, const AssignmentPhrase &r);
|
||||||
//AssignmentPhraseList operator &(AssignmentPhrase &&l, AssignmentPhrase &&r);
|
//AssignmentPhraseList operator &(AssignmentPhrase &&l, AssignmentPhrase &&r);
|
||||||
|
|
||||||
class PhraseList{
|
|
||||||
public:
|
|
||||||
bool isValid;
|
|
||||||
PhraseDataList data;
|
|
||||||
explicit PhraseList();
|
|
||||||
PhraseList(const PhraseList &other);
|
|
||||||
PhraseList(PhraseList &&other);
|
|
||||||
PhraseList(const AbstractFieldPhrase &other);
|
|
||||||
PhraseList(const AbstractFieldPhrase *left, const AbstractFieldPhrase &right);
|
|
||||||
PhraseList(PhraseList *left, PhraseList *right);
|
|
||||||
PhraseList(PhraseList *left, const AbstractFieldPhrase *right);
|
|
||||||
virtual ~PhraseList();
|
|
||||||
|
|
||||||
PhraseList &operator =(const PhraseList &other);
|
//ConditionalPhrase operator <(AbstractFieldPhrase &l, ConditionalPhrase &&other)
|
||||||
PhraseList operator |(PhraseList &other);
|
//{
|
||||||
PhraseList operator |(const AbstractFieldPhrase &other);
|
// return ConditionalPhrase(&l, PhraseData::Less, other);
|
||||||
|
//}
|
||||||
|
|
||||||
private:
|
//template<typename T>
|
||||||
void incAllDataParents();
|
//class FieldPhrase : public AbstractFieldPhrase
|
||||||
};
|
//{
|
||||||
|
//public:
|
||||||
|
// FieldPhrase(const char *className, const char *s) :
|
||||||
|
// AbstractFieldPhrase(className, s)
|
||||||
|
// {}
|
||||||
|
|
||||||
class ConditionalPhrase
|
// AssignmentPhrase operator =(const QVariant &other) {
|
||||||
{
|
// return AssignmentPhrase(this, other);
|
||||||
public:
|
// }
|
||||||
PhraseData *data;
|
//};
|
||||||
// QSharedPointer<PhraseData> leftDataPointer;
|
|
||||||
// QSharedPointer<PhraseData> rightDataPointer;
|
|
||||||
ConditionalPhrase();
|
|
||||||
ConditionalPhrase(const ConditionalPhrase &other);
|
|
||||||
#ifdef Q_COMPILER_RVALUE_REFS
|
|
||||||
ConditionalPhrase(const ConditionalPhrase &&other);
|
|
||||||
#endif
|
|
||||||
ConditionalPhrase(const PhraseData *data);
|
|
||||||
ConditionalPhrase(AbstractFieldPhrase *, PhraseData::Condition);
|
|
||||||
ConditionalPhrase(AbstractFieldPhrase *, PhraseData::Condition, const QVariant &v);
|
|
||||||
ConditionalPhrase(AbstractFieldPhrase *, PhraseData::Condition, const AbstractFieldPhrase &v);
|
|
||||||
ConditionalPhrase(AbstractFieldPhrase *l, PhraseData::Condition cond, ConditionalPhrase &r);
|
|
||||||
ConditionalPhrase(ConditionalPhrase *l, PhraseData::Condition cond, const AbstractFieldPhrase &r);
|
|
||||||
ConditionalPhrase(ConditionalPhrase *l, PhraseData::Condition cond, const QVariant &r);
|
|
||||||
ConditionalPhrase(ConditionalPhrase *l, PhraseData::Condition cond, ConditionalPhrase &r);
|
|
||||||
virtual ~ConditionalPhrase();
|
|
||||||
|
|
||||||
ConditionalPhrase &operator =(const ConditionalPhrase &other);
|
|
||||||
ConditionalPhrase operator ==(const QVariant &other);
|
|
||||||
// ConditionalPhrase operator ==(const AbstractFieldPhrase &other);
|
|
||||||
// ConditionalPhrase operator &&(const ConditionalPhrase &other);
|
|
||||||
// ConditionalPhrase operator ||(const ConditionalPhrase &other);
|
|
||||||
ConditionalPhrase operator !();
|
|
||||||
|
|
||||||
SPECIALIZATION_NUMERIC_MEMBER(type, <, PhraseData::Less)
|
|
||||||
SPECIALIZATION_NUMERIC_MEMBER(type, <=, PhraseData::LessEqual)
|
|
||||||
SPECIALIZATION_NUMERIC_MEMBER(type, >, PhraseData::Greater)
|
|
||||||
SPECIALIZATION_NUMERIC_MEMBER(type, >=, PhraseData::GreaterEqual)
|
|
||||||
};
|
|
||||||
|
|
||||||
#define DECLARE_CONDITIONALPHRASE_OPERATORS(op) \
|
|
||||||
ConditionalPhrase operator op(const ConditionalPhrase &l, const ConditionalPhrase &r); \
|
|
||||||
ConditionalPhrase operator op(const ConditionalPhrase &l, ConditionalPhrase &&r); \
|
|
||||||
ConditionalPhrase operator op(ConditionalPhrase &&l, const ConditionalPhrase &r); \
|
|
||||||
ConditionalPhrase operator op(ConditionalPhrase &&l, ConditionalPhrase &&r);
|
|
||||||
|
|
||||||
DECLARE_CONDITIONALPHRASE_OPERATORS(==)
|
|
||||||
DECLARE_CONDITIONALPHRASE_OPERATORS(&&)
|
|
||||||
DECLARE_CONDITIONALPHRASE_OPERATORS(||)
|
|
||||||
|
|
||||||
class AbstractFieldPhrase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PhraseData *data;
|
|
||||||
explicit AbstractFieldPhrase(PhraseData *d);
|
|
||||||
AbstractFieldPhrase(const char *className, const char *fieldName);
|
|
||||||
AbstractFieldPhrase(const AbstractFieldPhrase &other);
|
|
||||||
AbstractFieldPhrase(AbstractFieldPhrase &&other);
|
|
||||||
|
|
||||||
virtual ~AbstractFieldPhrase();
|
|
||||||
|
|
||||||
PhraseList operator |(const AbstractFieldPhrase &other);
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
ConditionalPhrase in(QList<T> list)
|
|
||||||
{
|
|
||||||
QVariantList vlist;
|
|
||||||
foreach (T t, list)
|
|
||||||
vlist.append(QVariant::fromValue(t));
|
|
||||||
|
|
||||||
return ConditionalPhrase(this, PhraseData::In, vlist);
|
|
||||||
}
|
|
||||||
#ifdef Q_COMPILER_INITIALIZER_LISTS
|
|
||||||
ConditionalPhrase in(std::initializer_list<int> list) {
|
|
||||||
QVariantList vlist;
|
|
||||||
std::initializer_list<int>::iterator it;
|
|
||||||
for (it = list.begin(); it != list.end(); ++it)
|
|
||||||
vlist.append(*it);
|
|
||||||
return ConditionalPhrase(this, PhraseData::In, vlist);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ConditionalPhrase isNull();
|
|
||||||
|
|
||||||
ConditionalPhrase operator ==(const QVariant &other);
|
|
||||||
ConditionalPhrase operator ==(const ConditionalPhrase &other);
|
|
||||||
ConditionalPhrase operator !=(const QVariant &other);
|
|
||||||
|
|
||||||
ConditionalPhrase operator ==(const AbstractFieldPhrase &other);
|
|
||||||
ConditionalPhrase operator !=(const AbstractFieldPhrase &other);
|
|
||||||
ConditionalPhrase operator <(const AbstractFieldPhrase &other);
|
|
||||||
ConditionalPhrase operator >(const AbstractFieldPhrase &other);
|
|
||||||
ConditionalPhrase operator <=(const AbstractFieldPhrase &other);
|
|
||||||
ConditionalPhrase operator >=(const AbstractFieldPhrase &other);
|
|
||||||
|
|
||||||
AbstractFieldPhrase operator !();
|
|
||||||
AssignmentPhrase operator =(const QVariant &other);
|
|
||||||
AssignmentPhrase operator <<(const QVariant &other);
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class FieldPhrase : public AbstractFieldPhrase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FieldPhrase(const char *className, const char *s) :
|
|
||||||
AbstractFieldPhrase(className, s)
|
|
||||||
{}
|
|
||||||
|
|
||||||
AssignmentPhrase operator =(const QVariant &other) {
|
|
||||||
return AssignmentPhrase(this, 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
AssignmentPhrase operator =(const QVariant &v) {
|
|
||||||
return AssignmentPhrase(this, v);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#define SPECIALIZATION_NUMERIC(type) \
|
|
||||||
template<> \
|
|
||||||
class FieldPhrase<type> : public AbstractFieldPhrase \
|
|
||||||
{ \
|
|
||||||
public: \
|
|
||||||
FieldPhrase(const char *className, const char *s) : \
|
|
||||||
AbstractFieldPhrase(className, s) \
|
|
||||||
{} \
|
|
||||||
SPECIALIZATION_NUMERIC_MEMBER(type, <, PhraseData::Less) \
|
|
||||||
SPECIALIZATION_NUMERIC_MEMBER(type, <=, PhraseData::LessEqual) \
|
|
||||||
SPECIALIZATION_NUMERIC_MEMBER(type, >, PhraseData::Greater) \
|
|
||||||
SPECIALIZATION_NUMERIC_MEMBER(type, >=, PhraseData::GreaterEqual) \
|
|
||||||
SPECIALIZATION_NUMERIC_MEMBER(type, %, PhraseData::Mod) \
|
|
||||||
\
|
|
||||||
SPECIALIZATION_NUMERIC_MEMBER(type, +, PhraseData::Add) \
|
|
||||||
SPECIALIZATION_NUMERIC_MEMBER(type, -, PhraseData::Minus) \
|
|
||||||
SPECIALIZATION_NUMERIC_MEMBER(type, *, PhraseData::Multiple) \
|
|
||||||
SPECIALIZATION_NUMERIC_MEMBER(type, /, PhraseData::Divide) \
|
|
||||||
AssignmentPhrase operator =(const QVariant &other) { \
|
|
||||||
return AssignmentPhrase(this, other); \
|
|
||||||
} \
|
|
||||||
ConditionalPhrase between(const QVariant &min, const QVariant &max) \
|
|
||||||
{ \
|
|
||||||
return ConditionalPhrase(this, PhraseData::Between, \
|
|
||||||
QVariantList() << min << max); \
|
|
||||||
} \
|
|
||||||
};
|
|
||||||
|
|
||||||
SPECIALIZATION_NUMERIC(qint8)
|
|
||||||
SPECIALIZATION_NUMERIC(qint16)
|
|
||||||
SPECIALIZATION_NUMERIC(qint32)
|
|
||||||
SPECIALIZATION_NUMERIC(qint64)
|
|
||||||
|
|
||||||
SPECIALIZATION_NUMERIC(quint8)
|
|
||||||
SPECIALIZATION_NUMERIC(quint16)
|
|
||||||
SPECIALIZATION_NUMERIC(quint32)
|
|
||||||
SPECIALIZATION_NUMERIC(quint64)
|
|
||||||
|
|
||||||
SPECIALIZATION_NUMERIC(qreal)
|
|
||||||
|
|
||||||
//Date and time
|
|
||||||
#define CONDITIONAL_VARIANT_METHOD(name, cond) \
|
|
||||||
ConditionalPhrase name(int val) \
|
|
||||||
{ \
|
|
||||||
return ConditionalPhrase(this, cond, val); \
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
class FieldPhrase<bool> : public AbstractFieldPhrase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FieldPhrase(const char *className, const char *s) :
|
|
||||||
AbstractFieldPhrase(className, s)
|
|
||||||
{}
|
|
||||||
|
|
||||||
AssignmentPhrase operator =(const bool &other) {
|
|
||||||
return AssignmentPhrase(this, other);
|
|
||||||
}
|
|
||||||
|
|
||||||
FieldPhrase<bool> operator !()
|
|
||||||
{
|
|
||||||
FieldPhrase<bool> f(data->className, data->fieldName);
|
|
||||||
// f.data = new PhraseData(data);
|
|
||||||
f.data->isNot = !data->isNot;
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
operator ConditionalPhrase()
|
|
||||||
{
|
|
||||||
return ConditionalPhrase(this, PhraseData::Equal, !data->isNot);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
class FieldPhrase<QDate> : public AbstractFieldPhrase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FieldPhrase(const char *className, const char *s) :
|
|
||||||
AbstractFieldPhrase(className, s)
|
|
||||||
{}
|
|
||||||
SPECIALIZATION_NUMERIC_MEMBER(type, <, PhraseData::Less)
|
|
||||||
SPECIALIZATION_NUMERIC_MEMBER(type, <=, PhraseData::LessEqual)
|
|
||||||
SPECIALIZATION_NUMERIC_MEMBER(type, >, PhraseData::Greater)
|
|
||||||
SPECIALIZATION_NUMERIC_MEMBER(type, >=, PhraseData::GreaterEqual)
|
|
||||||
AssignmentPhrase operator =(const QDate &other) {
|
|
||||||
return AssignmentPhrase(this, other);
|
|
||||||
}
|
|
||||||
ConditionalPhrase between(const QDate &min, const QDate &max)
|
|
||||||
{
|
|
||||||
return ConditionalPhrase(this, PhraseData::Between,
|
|
||||||
QVariantList() << min << max);
|
|
||||||
}
|
|
||||||
CONDITIONAL_VARIANT_METHOD(addYears, PhraseData::AddYears)
|
|
||||||
CONDITIONAL_VARIANT_METHOD(addMonths, PhraseData::AddMonths)
|
|
||||||
CONDITIONAL_VARIANT_METHOD(addDays, PhraseData::AddDays)
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
class FieldPhrase<QTime> : public AbstractFieldPhrase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FieldPhrase(const char *className, const char *s) :
|
|
||||||
AbstractFieldPhrase(className, s)
|
|
||||||
{}
|
|
||||||
SPECIALIZATION_NUMERIC_MEMBER(type, <, PhraseData::Less)
|
|
||||||
SPECIALIZATION_NUMERIC_MEMBER(type, <=, PhraseData::LessEqual)
|
|
||||||
SPECIALIZATION_NUMERIC_MEMBER(type, >, PhraseData::Greater)
|
|
||||||
SPECIALIZATION_NUMERIC_MEMBER(type, >=, PhraseData::GreaterEqual)
|
|
||||||
AssignmentPhrase operator =(const QTime &other) {
|
|
||||||
return AssignmentPhrase(this, other);
|
|
||||||
}
|
|
||||||
ConditionalPhrase between(const QTime &min, const QTime &max)
|
|
||||||
{
|
|
||||||
return ConditionalPhrase(this, PhraseData::Between,
|
|
||||||
QVariantList() << min << max);
|
|
||||||
}
|
|
||||||
|
|
||||||
CONDITIONAL_VARIANT_METHOD(addHours, PhraseData::AddHours)
|
|
||||||
CONDITIONAL_VARIANT_METHOD(addMinutes, PhraseData::AddMinutes)
|
|
||||||
CONDITIONAL_VARIANT_METHOD(addSeconds, PhraseData::AddSeconds)
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
class FieldPhrase<QDateTime> : public AbstractFieldPhrase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FieldPhrase(const char *className, const char *s) :
|
|
||||||
AbstractFieldPhrase(className, s)
|
|
||||||
{}
|
|
||||||
SPECIALIZATION_NUMERIC_MEMBER(type, <, PhraseData::Less)
|
|
||||||
SPECIALIZATION_NUMERIC_MEMBER(type, <=, PhraseData::LessEqual)
|
|
||||||
SPECIALIZATION_NUMERIC_MEMBER(type, >, PhraseData::Greater)
|
|
||||||
SPECIALIZATION_NUMERIC_MEMBER(type, >=, PhraseData::GreaterEqual)
|
|
||||||
AssignmentPhrase operator =(const QDateTime &other) {
|
|
||||||
return AssignmentPhrase(this, other);
|
|
||||||
}
|
|
||||||
ConditionalPhrase between(const QDateTime &min, const QDateTime &max)
|
|
||||||
{
|
|
||||||
return ConditionalPhrase(this, PhraseData::Between,
|
|
||||||
QVariantList() << min << max);
|
|
||||||
}
|
|
||||||
CONDITIONAL_VARIANT_METHOD(addYears, PhraseData::AddYears)
|
|
||||||
CONDITIONAL_VARIANT_METHOD(addMonths, PhraseData::AddMonths)
|
|
||||||
CONDITIONAL_VARIANT_METHOD(addDays, PhraseData::AddDays)
|
|
||||||
|
|
||||||
CONDITIONAL_VARIANT_METHOD(addHours, PhraseData::AddHours)
|
|
||||||
CONDITIONAL_VARIANT_METHOD(addMinutes, PhraseData::AddMinutes)
|
|
||||||
CONDITIONAL_VARIANT_METHOD(addSeconds, PhraseData::AddSeconds)
|
|
||||||
};
|
|
||||||
|
|
||||||
NUT_END_NAMESPACE
|
NUT_END_NAMESPACE
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,126 @@
|
||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "abstractfieldphrase.h"
|
||||||
|
|
||||||
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
AbstractFieldPhrase::AbstractFieldPhrase(PhraseData *d) : data(d)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
AbstractFieldPhrase::AbstractFieldPhrase(const char *className,
|
||||||
|
const char *fieldName)
|
||||||
|
:data(new PhraseData(className, fieldName))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractFieldPhrase::AbstractFieldPhrase(const AbstractFieldPhrase &other)
|
||||||
|
{
|
||||||
|
data = other.data;
|
||||||
|
data->parents++;
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractFieldPhrase::AbstractFieldPhrase(AbstractFieldPhrase &&other)
|
||||||
|
{
|
||||||
|
data = other.data;
|
||||||
|
data->parents++;
|
||||||
|
other.data = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractFieldPhrase::~AbstractFieldPhrase()
|
||||||
|
{
|
||||||
|
if (data) {
|
||||||
|
--data->parents;
|
||||||
|
if (data->parents <= 0)
|
||||||
|
delete data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PhraseList AbstractFieldPhrase::operator |(const AbstractFieldPhrase &other)
|
||||||
|
{
|
||||||
|
return PhraseList(this, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConditionalPhrase AbstractFieldPhrase::isNull()
|
||||||
|
{
|
||||||
|
return ConditionalPhrase(this, PhraseData::Null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ConditionalPhrase AbstractFieldPhrase::operator ==(const ConditionalPhrase
|
||||||
|
&other)
|
||||||
|
{
|
||||||
|
return ConditionalPhrase(this, PhraseData::Equal,
|
||||||
|
const_cast<ConditionalPhrase&>(other));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AssignmentPhrase AbstractFieldPhrase::operator =(const QVariant &other)
|
||||||
|
{
|
||||||
|
return AssignmentPhrase(this, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
AssignmentPhrase AbstractFieldPhrase::operator =(const ConditionalPhrase &other)
|
||||||
|
{
|
||||||
|
return AssignmentPhrase(new PhraseData(data, PhraseData::Equal, other.data));
|
||||||
|
}
|
||||||
|
|
||||||
|
AssignmentPhrase AbstractFieldPhrase::operator <<(const QVariant &other)
|
||||||
|
{
|
||||||
|
return AssignmentPhrase(this, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define AbstractFieldPhraseOperatorVariant(class, op, cond) \
|
||||||
|
ConditionalPhrase class::operator op(const QVariant &other) \
|
||||||
|
{ \
|
||||||
|
return ConditionalPhrase(this, cond, other); \
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractFieldPhraseOperatorVariant(AbstractFieldPhrase, ==, PhraseData::Equal)
|
||||||
|
AbstractFieldPhraseOperatorVariant(AbstractFieldPhrase, !=, PhraseData::NotEqual)
|
||||||
|
|
||||||
|
#define AbstractFieldPhraseOperatorField(op, cond) \
|
||||||
|
ConditionalPhrase AbstractFieldPhrase::operator op(const AbstractFieldPhrase &other) \
|
||||||
|
{ \
|
||||||
|
return ConditionalPhrase(this, cond, other); \
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractFieldPhraseOperatorField(==, PhraseData::Equal)
|
||||||
|
AbstractFieldPhraseOperatorField(!=, PhraseData::NotEqual)
|
||||||
|
AbstractFieldPhraseOperatorField(< , PhraseData::Less)
|
||||||
|
AbstractFieldPhraseOperatorField(<=, PhraseData::LessEqual)
|
||||||
|
AbstractFieldPhraseOperatorField(> , PhraseData::Greater)
|
||||||
|
AbstractFieldPhraseOperatorField(>=, PhraseData::GreaterEqual)
|
||||||
|
|
||||||
|
AbstractFieldPhrase AbstractFieldPhrase::operator ~()
|
||||||
|
{
|
||||||
|
AbstractFieldPhrase f(data->className, data->fieldName);
|
||||||
|
f.data->isNot = !data->isNot;
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractFieldPhrase AbstractFieldPhrase::operator !()
|
||||||
|
{
|
||||||
|
AbstractFieldPhrase f(data->className, data->fieldName);
|
||||||
|
f.data->isNot = !data->isNot;
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
NUT_END_NAMESPACE
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** 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 ABSTRACTFIELDPHRASE_H
|
||||||
|
#define ABSTRACTFIELDPHRASE_H
|
||||||
|
|
||||||
|
#include "../defines.h"
|
||||||
|
|
||||||
|
#include "assignmentphrase.h"
|
||||||
|
#include "conditionalphrase.h"
|
||||||
|
#include "phraselist.h"
|
||||||
|
|
||||||
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class PhraseData;
|
||||||
|
class NUT_EXPORT AbstractFieldPhrase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PhraseData *data;
|
||||||
|
explicit AbstractFieldPhrase(PhraseData *d);
|
||||||
|
AbstractFieldPhrase(const char *className, const char *fieldName);
|
||||||
|
AbstractFieldPhrase(const AbstractFieldPhrase &other);
|
||||||
|
AbstractFieldPhrase(AbstractFieldPhrase &&other);
|
||||||
|
|
||||||
|
virtual ~AbstractFieldPhrase();
|
||||||
|
|
||||||
|
PhraseList operator |(const AbstractFieldPhrase &other);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
ConditionalPhrase in(QList<T> list)
|
||||||
|
{
|
||||||
|
QVariantList vlist;
|
||||||
|
foreach (T t, list)
|
||||||
|
vlist.append(QVariant::fromValue(t));
|
||||||
|
|
||||||
|
return ConditionalPhrase(this, PhraseData::In, vlist);
|
||||||
|
}
|
||||||
|
#ifdef Q_COMPILER_INITIALIZER_LISTS
|
||||||
|
ConditionalPhrase in(std::initializer_list<int> list) {
|
||||||
|
QVariantList vlist;
|
||||||
|
std::initializer_list<int>::iterator it;
|
||||||
|
for (it = list.begin(); it != list.end(); ++it)
|
||||||
|
vlist.append(*it);
|
||||||
|
return ConditionalPhrase(this, PhraseData::In, vlist);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ConditionalPhrase isNull();
|
||||||
|
|
||||||
|
ConditionalPhrase operator ==(const QVariant &other);
|
||||||
|
ConditionalPhrase operator ==(const ConditionalPhrase &other);
|
||||||
|
//why?
|
||||||
|
ConditionalPhrase operator !=(const QVariant &other);
|
||||||
|
|
||||||
|
ConditionalPhrase operator ==(const AbstractFieldPhrase &other);
|
||||||
|
ConditionalPhrase operator !=(const AbstractFieldPhrase &other);
|
||||||
|
ConditionalPhrase operator <(const AbstractFieldPhrase &other);
|
||||||
|
ConditionalPhrase operator >(const AbstractFieldPhrase &other);
|
||||||
|
ConditionalPhrase operator <=(const AbstractFieldPhrase &other);
|
||||||
|
ConditionalPhrase operator >=(const AbstractFieldPhrase &other);
|
||||||
|
|
||||||
|
AbstractFieldPhrase operator ~();
|
||||||
|
AbstractFieldPhrase operator !();
|
||||||
|
AssignmentPhrase operator =(const QVariant &other);
|
||||||
|
AssignmentPhrase operator =(const ConditionalPhrase &other);
|
||||||
|
AssignmentPhrase operator <<(const QVariant &other);
|
||||||
|
};
|
||||||
|
|
||||||
|
NUT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // ABSTRACTFIELDPHRASE_H
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "abstractfieldphrase.h"
|
||||||
|
#include "assignmentphrase.h"
|
||||||
|
#include "phrasedata.h"
|
||||||
|
|
||||||
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
AssignmentPhrase::AssignmentPhrase(PhraseData *d) : data(d)
|
||||||
|
{
|
||||||
|
d->parents++;
|
||||||
|
}
|
||||||
|
|
||||||
|
AssignmentPhrase::AssignmentPhrase(AbstractFieldPhrase *l, const QVariant r)
|
||||||
|
{
|
||||||
|
|
||||||
|
data = new PhraseData(l->data, PhraseData::Equal, r);
|
||||||
|
// l->data = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
AssignmentPhrase::AssignmentPhrase(AbstractFieldPhrase *l,
|
||||||
|
const AssignmentPhrase *r)
|
||||||
|
{
|
||||||
|
data = new PhraseData(l->data, PhraseData::Equal, r->data);
|
||||||
|
// l->data = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
AssignmentPhrase::AssignmentPhrase(AssignmentPhrase *ph, const QVariant &v)
|
||||||
|
{
|
||||||
|
data = new PhraseData(ph->data, PhraseData::Equal, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
//AssignmentPhrase::AssignmentPhrase(AssignmentPhrase &other)
|
||||||
|
//{
|
||||||
|
// data = other.data;
|
||||||
|
// other.data = 0;
|
||||||
|
//}
|
||||||
|
|
||||||
|
AssignmentPhrase::~AssignmentPhrase()
|
||||||
|
{
|
||||||
|
if (data)
|
||||||
|
if (!--data->parents)
|
||||||
|
delete data;
|
||||||
|
}
|
||||||
|
|
||||||
|
NUT_END_NAMESPACE
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** 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 ASSIGNMENTPHRASE_H
|
||||||
|
#define ASSIGNMENTPHRASE_H
|
||||||
|
|
||||||
|
#include "../defines.h"
|
||||||
|
|
||||||
|
#include "assignmentphraselist.h"
|
||||||
|
|
||||||
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class PhraseData;
|
||||||
|
class AbstractFieldPhrase;
|
||||||
|
class NUT_EXPORT AssignmentPhrase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PhraseData *data;
|
||||||
|
explicit AssignmentPhrase(PhraseData *d);
|
||||||
|
explicit AssignmentPhrase(AbstractFieldPhrase *l, const QVariant r);
|
||||||
|
explicit AssignmentPhrase(AbstractFieldPhrase *l, const AssignmentPhrase *r);
|
||||||
|
explicit AssignmentPhrase(AssignmentPhrase *ph, const QVariant &v);
|
||||||
|
// explicit AssignmentPhrase(AssignmentPhrase &other);
|
||||||
|
~AssignmentPhrase();
|
||||||
|
// AssignmentPhrase(AssignmentPhrase *l, const AssignmentPhrase *r);
|
||||||
|
|
||||||
|
AssignmentPhraseList operator &(const AssignmentPhrase &other);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
NUT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // ASSIGNMENTPHRASE_H
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "assignmentphraselist.h"
|
||||||
|
#include "phrasedata.h"
|
||||||
|
#include "assignmentphrase.h"
|
||||||
|
|
||||||
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
|
||||||
|
AssignmentPhraseList AssignmentPhrase::operator &(const AssignmentPhrase &other)
|
||||||
|
{
|
||||||
|
return AssignmentPhraseList(this, &other);
|
||||||
|
}
|
||||||
|
|
||||||
|
AssignmentPhraseList::AssignmentPhraseList(const AssignmentPhrase &l)
|
||||||
|
{
|
||||||
|
data.append(l.data);
|
||||||
|
incAllDataParents();
|
||||||
|
}
|
||||||
|
|
||||||
|
AssignmentPhraseList::AssignmentPhraseList(AssignmentPhraseList *l,
|
||||||
|
const AssignmentPhrase *r)
|
||||||
|
{
|
||||||
|
data.append(l->data);
|
||||||
|
data.append(r->data);
|
||||||
|
incAllDataParents();
|
||||||
|
}
|
||||||
|
|
||||||
|
AssignmentPhraseList::AssignmentPhraseList(AssignmentPhrase *l,
|
||||||
|
const AssignmentPhrase *r)
|
||||||
|
{
|
||||||
|
data.append(l->data);
|
||||||
|
data.append(r->data);
|
||||||
|
incAllDataParents();
|
||||||
|
}
|
||||||
|
|
||||||
|
AssignmentPhraseList::AssignmentPhraseList(const AssignmentPhrase &r,
|
||||||
|
const AssignmentPhrase &l)
|
||||||
|
{
|
||||||
|
data.append(l.data);
|
||||||
|
data.append(r.data);
|
||||||
|
incAllDataParents();
|
||||||
|
}
|
||||||
|
|
||||||
|
AssignmentPhraseList AssignmentPhraseList::operator &(const AssignmentPhrase
|
||||||
|
&ph)
|
||||||
|
{
|
||||||
|
return AssignmentPhraseList(this, &ph);
|
||||||
|
}
|
||||||
|
|
||||||
|
AssignmentPhraseList::~AssignmentPhraseList()
|
||||||
|
{
|
||||||
|
foreach (PhraseData *d, data)
|
||||||
|
if (!--d->parents)
|
||||||
|
delete d;
|
||||||
|
// qDeleteAll(data);
|
||||||
|
// data.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssignmentPhraseList::incAllDataParents()
|
||||||
|
{
|
||||||
|
foreach (PhraseData *d, data)
|
||||||
|
d->parents++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NUT_END_NAMESPACE
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** 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 ASSIGNMENTPHRASELIST_H
|
||||||
|
#define ASSIGNMENTPHRASELIST_H
|
||||||
|
|
||||||
|
#include "../defines.h"
|
||||||
|
|
||||||
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class PhraseData;
|
||||||
|
class AssignmentPhrase;
|
||||||
|
class NUT_EXPORT AssignmentPhraseList
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QList<PhraseData*> data;
|
||||||
|
explicit AssignmentPhraseList() = default;
|
||||||
|
AssignmentPhraseList(const AssignmentPhrase &l);
|
||||||
|
AssignmentPhraseList(AssignmentPhraseList *l, const AssignmentPhrase *r);
|
||||||
|
AssignmentPhraseList(AssignmentPhrase *l, const AssignmentPhrase *r);
|
||||||
|
AssignmentPhraseList(const AssignmentPhrase &r, const AssignmentPhrase &l);
|
||||||
|
|
||||||
|
AssignmentPhraseList operator &(const AssignmentPhrase &ph);
|
||||||
|
|
||||||
|
~AssignmentPhraseList();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void incAllDataParents();
|
||||||
|
};
|
||||||
|
|
||||||
|
NUT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // ASSIGNMENTPHRASELIST_H
|
||||||
|
|
@ -0,0 +1,245 @@
|
||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "abstractfieldphrase.h"
|
||||||
|
#include "conditionalphrase.h"
|
||||||
|
#include "phrasedata.h"
|
||||||
|
|
||||||
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
ConditionalPhrase::ConditionalPhrase() : data(nullptr)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
ConditionalPhrase::ConditionalPhrase(const ConditionalPhrase &other)
|
||||||
|
{
|
||||||
|
data = other.data;
|
||||||
|
data->parents++;
|
||||||
|
// const_cast<ConditionalPhrase&>(other).data = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef Q_COMPILER_RVALUE_REFS
|
||||||
|
ConditionalPhrase::ConditionalPhrase(const ConditionalPhrase &&other)
|
||||||
|
{
|
||||||
|
this->data = qMove(other.data);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ConditionalPhrase::ConditionalPhrase(const PhraseData *data)
|
||||||
|
{
|
||||||
|
this->data = const_cast<PhraseData*>(data);
|
||||||
|
this->data->parents++;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConditionalPhrase::ConditionalPhrase(AbstractFieldPhrase *l,
|
||||||
|
PhraseData::Condition cond)
|
||||||
|
{
|
||||||
|
data = new PhraseData(l->data, cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConditionalPhrase::ConditionalPhrase(AbstractFieldPhrase *l,
|
||||||
|
PhraseData::Condition cond,
|
||||||
|
const QVariant &v)
|
||||||
|
{
|
||||||
|
data = new PhraseData(l->data, cond, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConditionalPhrase::ConditionalPhrase(AbstractFieldPhrase *l,
|
||||||
|
PhraseData::Condition cond,
|
||||||
|
const AbstractFieldPhrase &other)
|
||||||
|
{
|
||||||
|
data = new PhraseData(l->data, cond, other.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConditionalPhrase::ConditionalPhrase(AbstractFieldPhrase *l,
|
||||||
|
PhraseData::Condition cond,
|
||||||
|
ConditionalPhrase &r)
|
||||||
|
{
|
||||||
|
data = new PhraseData(l->data, cond, r.data);
|
||||||
|
r.data = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConditionalPhrase::ConditionalPhrase(ConditionalPhrase *l,
|
||||||
|
PhraseData::Condition cond,
|
||||||
|
const AbstractFieldPhrase &r)
|
||||||
|
{
|
||||||
|
data = new PhraseData(l->data, cond, r.data);
|
||||||
|
l->data = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConditionalPhrase::ConditionalPhrase(ConditionalPhrase *l,
|
||||||
|
PhraseData::Condition cond,
|
||||||
|
const QVariant &r)
|
||||||
|
{
|
||||||
|
data = new PhraseData(l->data, cond, r);
|
||||||
|
l->data = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConditionalPhrase::ConditionalPhrase(ConditionalPhrase *l,
|
||||||
|
PhraseData::Condition cond,
|
||||||
|
ConditionalPhrase &r)
|
||||||
|
{
|
||||||
|
data = new PhraseData(l->data, cond, r.data);
|
||||||
|
l->data = nullptr;
|
||||||
|
r.data = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConditionalPhrase::~ConditionalPhrase()
|
||||||
|
{
|
||||||
|
if (data) {
|
||||||
|
data->cleanUp();
|
||||||
|
if (!--data->parents)
|
||||||
|
delete data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ConditionalPhrase &ConditionalPhrase::operator =(const ConditionalPhrase &other)
|
||||||
|
{
|
||||||
|
data = other.data;
|
||||||
|
data->parents++;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) \
|
||||||
|
{ \
|
||||||
|
ConditionalPhrase p; \
|
||||||
|
p.data = new PhraseData; \
|
||||||
|
p.data->type = PhraseData::WithOther; \
|
||||||
|
p.data->operatorCond = cond; \
|
||||||
|
p.data->left = l.data; \
|
||||||
|
p.data->right = r.data; \
|
||||||
|
l.data->parents++; \
|
||||||
|
r.data->parents++; \
|
||||||
|
return p; \
|
||||||
|
} \
|
||||||
|
ConditionalPhrase operator op(const ConditionalPhrase &l, \
|
||||||
|
ConditionalPhrase &&r) \
|
||||||
|
{ \
|
||||||
|
ConditionalPhrase p; \
|
||||||
|
p.data = new PhraseData; \
|
||||||
|
p.data->type = PhraseData::WithOther; \
|
||||||
|
p.data->operatorCond = cond; \
|
||||||
|
p.data->left = l.data; \
|
||||||
|
p.data->right = r.data; \
|
||||||
|
l.data->parents++; \
|
||||||
|
r.data->parents++; \
|
||||||
|
return p; \
|
||||||
|
} \
|
||||||
|
ConditionalPhrase operator op(ConditionalPhrase &&l, \
|
||||||
|
const ConditionalPhrase &r) \
|
||||||
|
{ \
|
||||||
|
ConditionalPhrase p; \
|
||||||
|
p.data = new PhraseData; \
|
||||||
|
p.data->type = PhraseData::WithOther; \
|
||||||
|
p.data->operatorCond = cond; \
|
||||||
|
p.data->left = l.data; \
|
||||||
|
p.data->right = r.data; \
|
||||||
|
l.data->parents++; \
|
||||||
|
r.data->parents++; \
|
||||||
|
return p; \
|
||||||
|
} \
|
||||||
|
ConditionalPhrase operator op(ConditionalPhrase &&l, ConditionalPhrase &&r) \
|
||||||
|
{ \
|
||||||
|
ConditionalPhrase p; \
|
||||||
|
p.data = new PhraseData; \
|
||||||
|
p.data->type = PhraseData::WithOther; \
|
||||||
|
p.data->operatorCond = cond; \
|
||||||
|
p.data->left = l.data; \
|
||||||
|
p.data->right = r.data; \
|
||||||
|
l.data->parents++; \
|
||||||
|
r.data->parents++; \
|
||||||
|
return p; \
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_CONDITIONALPHRASE_OPERATORS_IMPL(==, PhraseData::Equal)
|
||||||
|
DECLARE_CONDITIONALPHRASE_OPERATORS_IMPL(||, PhraseData::Or)
|
||||||
|
DECLARE_CONDITIONALPHRASE_OPERATORS_IMPL(&&, PhraseData::And)
|
||||||
|
|
||||||
|
ConditionalPhrase ConditionalPhrase::operator !()
|
||||||
|
{
|
||||||
|
ConditionalPhrase f(data);
|
||||||
|
f.data->isNot = !data->isNot;
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConditionalPhrase operator <(AbstractFieldPhrase &l, ConditionalPhrase &&r)
|
||||||
|
{
|
||||||
|
return ConditionalPhrase(&l, PhraseData::Less, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConditionalPhrase operator <=(AbstractFieldPhrase &l, ConditionalPhrase &&r)
|
||||||
|
{
|
||||||
|
return ConditionalPhrase(&l, PhraseData::LessEqual, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConditionalPhrase operator >(AbstractFieldPhrase &l, ConditionalPhrase &&r)
|
||||||
|
{
|
||||||
|
return ConditionalPhrase(&l, PhraseData::Greater, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConditionalPhrase operator >=(AbstractFieldPhrase &l, ConditionalPhrase &&r)
|
||||||
|
{
|
||||||
|
return ConditionalPhrase(&l, PhraseData::GreaterEqual, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConditionalPhrase operator <(ConditionalPhrase &&l, ConditionalPhrase &&r)
|
||||||
|
{
|
||||||
|
return ConditionalPhrase(&l, PhraseData::Less, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConditionalPhrase operator <=(ConditionalPhrase &&l, ConditionalPhrase &&r)
|
||||||
|
{
|
||||||
|
return ConditionalPhrase(&l, PhraseData::LessEqual, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConditionalPhrase operator >(ConditionalPhrase &&l, ConditionalPhrase &&r)
|
||||||
|
{
|
||||||
|
return ConditionalPhrase(&l, PhraseData::Greater, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConditionalPhrase operator >=(ConditionalPhrase &&l, ConditionalPhrase &&r)
|
||||||
|
{
|
||||||
|
return ConditionalPhrase(&l, PhraseData::GreaterEqual, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
NUT_END_NAMESPACE
|
||||||
|
|
@ -0,0 +1,94 @@
|
||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** 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 CONDITIONALPHRASE_H
|
||||||
|
#define CONDITIONALPHRASE_H
|
||||||
|
|
||||||
|
#include "phrasedata.h"
|
||||||
|
|
||||||
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class PhraseData;
|
||||||
|
class AbstractFieldPhrase;
|
||||||
|
|
||||||
|
#define SPECIALIZATION_NUMERIC_MEMBER(type, op, cond) \
|
||||||
|
ConditionalPhrase operator op(const QVariant &other) \
|
||||||
|
{ \
|
||||||
|
return ConditionalPhrase(this, cond, other); \
|
||||||
|
}
|
||||||
|
class NUT_EXPORT ConditionalPhrase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PhraseData *data;
|
||||||
|
// QSharedPointer<PhraseData> leftDataPointer;
|
||||||
|
// QSharedPointer<PhraseData> rightDataPointer;
|
||||||
|
ConditionalPhrase();
|
||||||
|
ConditionalPhrase(const ConditionalPhrase &other);
|
||||||
|
#ifdef Q_COMPILER_RVALUE_REFS
|
||||||
|
ConditionalPhrase(const ConditionalPhrase &&other);
|
||||||
|
#endif
|
||||||
|
explicit ConditionalPhrase(const PhraseData *data);
|
||||||
|
ConditionalPhrase(AbstractFieldPhrase *, PhraseData::Condition);
|
||||||
|
ConditionalPhrase(AbstractFieldPhrase *, PhraseData::Condition, const QVariant &v);
|
||||||
|
ConditionalPhrase(AbstractFieldPhrase *, PhraseData::Condition, const AbstractFieldPhrase &v);
|
||||||
|
ConditionalPhrase(AbstractFieldPhrase *l, PhraseData::Condition cond, ConditionalPhrase &r);
|
||||||
|
ConditionalPhrase(ConditionalPhrase *l, PhraseData::Condition cond, const AbstractFieldPhrase &r);
|
||||||
|
ConditionalPhrase(ConditionalPhrase *l, PhraseData::Condition cond, const QVariant &r);
|
||||||
|
ConditionalPhrase(ConditionalPhrase *l, PhraseData::Condition cond, ConditionalPhrase &r);
|
||||||
|
virtual ~ConditionalPhrase();
|
||||||
|
|
||||||
|
ConditionalPhrase &operator =(const ConditionalPhrase &other);
|
||||||
|
ConditionalPhrase operator ==(const QVariant &other);
|
||||||
|
// ConditionalPhrase operator ==(const AbstractFieldPhrase &other);
|
||||||
|
// ConditionalPhrase operator &&(const ConditionalPhrase &other);
|
||||||
|
// ConditionalPhrase operator ||(const ConditionalPhrase &other);
|
||||||
|
ConditionalPhrase operator !();
|
||||||
|
|
||||||
|
SPECIALIZATION_NUMERIC_MEMBER(type, <, PhraseData::Less)
|
||||||
|
SPECIALIZATION_NUMERIC_MEMBER(type, <=, PhraseData::LessEqual)
|
||||||
|
SPECIALIZATION_NUMERIC_MEMBER(type, >, PhraseData::Greater)
|
||||||
|
SPECIALIZATION_NUMERIC_MEMBER(type, >=, PhraseData::GreaterEqual)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define DECLARE_CONDITIONALPHRASE_OPERATORS(op) \
|
||||||
|
ConditionalPhrase operator op(const ConditionalPhrase &l, const ConditionalPhrase &r); \
|
||||||
|
ConditionalPhrase operator op(const ConditionalPhrase &l, ConditionalPhrase &&r); \
|
||||||
|
ConditionalPhrase operator op(ConditionalPhrase &&l, const ConditionalPhrase &r); \
|
||||||
|
ConditionalPhrase operator op(ConditionalPhrase &&l, ConditionalPhrase &&r);
|
||||||
|
|
||||||
|
DECLARE_CONDITIONALPHRASE_OPERATORS(==)
|
||||||
|
DECLARE_CONDITIONALPHRASE_OPERATORS(&&)
|
||||||
|
DECLARE_CONDITIONALPHRASE_OPERATORS(||)
|
||||||
|
|
||||||
|
ConditionalPhrase operator <(AbstractFieldPhrase &l, ConditionalPhrase &&r);
|
||||||
|
ConditionalPhrase operator <=(AbstractFieldPhrase &l, ConditionalPhrase &&r);
|
||||||
|
ConditionalPhrase operator >(AbstractFieldPhrase &l, ConditionalPhrase &&r);
|
||||||
|
ConditionalPhrase operator >=(AbstractFieldPhrase &l, ConditionalPhrase &&r);
|
||||||
|
|
||||||
|
ConditionalPhrase operator <(ConditionalPhrase &&l, ConditionalPhrase &&r);
|
||||||
|
ConditionalPhrase operator <=(ConditionalPhrase &&l, ConditionalPhrase &&r);
|
||||||
|
ConditionalPhrase operator >(ConditionalPhrase &&l, ConditionalPhrase &&r);
|
||||||
|
ConditionalPhrase operator >=(ConditionalPhrase &&l, ConditionalPhrase &&r);
|
||||||
|
|
||||||
|
|
||||||
|
NUT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // CONDITIONALPHRASE_H
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "datephrase.h"
|
||||||
|
|
||||||
|
|
@ -0,0 +1,173 @@
|
||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** 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 DATEPHRASE_H
|
||||||
|
#define DATEPHRASE_H
|
||||||
|
|
||||||
|
#include "fieldphrase.h"
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
|
||||||
|
template<typename>
|
||||||
|
struct __is_date_helper
|
||||||
|
: public std::false_type { };
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct __is_date_helper<QTime>
|
||||||
|
: public std::true_type { };
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct __is_date_helper<QDate>
|
||||||
|
: public std::true_type { };
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct __is_date_helper<QDateTime>
|
||||||
|
: public std::true_type { };
|
||||||
|
|
||||||
|
template<typename _Tp>
|
||||||
|
struct is_date
|
||||||
|
: public __is_date_helper<typename std::remove_cv<_Tp>::type>::type
|
||||||
|
{ };
|
||||||
|
|
||||||
|
|
||||||
|
template <class T, class P>
|
||||||
|
inline bool is_valid_template() {return false;}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline bool is_valid_template<QDateTime, QTime>() {return true;}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline bool is_valid_template<QDateTime, QDate>() {return true;}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline bool is_valid_template<QDate, QDate>() {return true;}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline bool is_valid_template<QTime, QTime>() {return true;}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class NUT_EXPORT FieldPhrase<T, typename std::enable_if<is_date<T>::value>::type>
|
||||||
|
: public AbstractFieldPhrase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FieldPhrase(const char *className, const char *s) :
|
||||||
|
AbstractFieldPhrase(className, s)
|
||||||
|
{}
|
||||||
|
|
||||||
|
AssignmentPhrase operator =(const T &other) {
|
||||||
|
return AssignmentPhrase(this, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConditionalPhrase operator <(const QVariant &other) {
|
||||||
|
return ConditionalPhrase(this, PhraseData::Less, other);
|
||||||
|
}
|
||||||
|
ConditionalPhrase operator <=(const QVariant &other) {
|
||||||
|
return ConditionalPhrase(this, PhraseData::LessEqual, other);
|
||||||
|
}
|
||||||
|
ConditionalPhrase operator >(const QVariant &other) {
|
||||||
|
return ConditionalPhrase(this, PhraseData::Greater, other);
|
||||||
|
}
|
||||||
|
ConditionalPhrase operator >=(const QVariant &other) {
|
||||||
|
return ConditionalPhrase(this, PhraseData::GreaterEqual, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConditionalPhrase between(const QVariant &min, const QVariant &max)
|
||||||
|
{
|
||||||
|
return ConditionalPhrase(this, PhraseData::Between,
|
||||||
|
QVariantList() << min << max);
|
||||||
|
}
|
||||||
|
|
||||||
|
// template<class P = T,
|
||||||
|
// class std::enable_if<std::is_same<P, QDateTime>::value, int>::type = 0>
|
||||||
|
ConditionalPhrase addYears(int val) {
|
||||||
|
if (!is_valid_template<T, QDate>())
|
||||||
|
return ConditionalPhrase();
|
||||||
|
return ConditionalPhrase(this, PhraseData::AddYears, val);
|
||||||
|
}
|
||||||
|
ConditionalPhrase addMonths(int val) {
|
||||||
|
if (!is_valid_template<T, QDate>())
|
||||||
|
return ConditionalPhrase();
|
||||||
|
return ConditionalPhrase(this, PhraseData::AddMonths, val);
|
||||||
|
}
|
||||||
|
ConditionalPhrase addDays(int val) {
|
||||||
|
if (!is_valid_template<T, QDate>())
|
||||||
|
return ConditionalPhrase();
|
||||||
|
return ConditionalPhrase(this, PhraseData::AddDays, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConditionalPhrase addHours(int val) {
|
||||||
|
if (!is_valid_template<T, QTime>())
|
||||||
|
return ConditionalPhrase();
|
||||||
|
return ConditionalPhrase(this, PhraseData::AddHours, val);
|
||||||
|
}
|
||||||
|
ConditionalPhrase addMinutes(int val) {
|
||||||
|
if (!is_valid_template<T, QTime>())
|
||||||
|
return ConditionalPhrase();
|
||||||
|
return ConditionalPhrase(this, PhraseData::AddMinutes, val);
|
||||||
|
}
|
||||||
|
ConditionalPhrase addSeconds(int val) {
|
||||||
|
if (!is_valid_template<T, QTime>())
|
||||||
|
return ConditionalPhrase();
|
||||||
|
return ConditionalPhrase(this, PhraseData::AddSeconds, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConditionalPhrase year() {
|
||||||
|
if (!is_valid_template<T, QDate>())
|
||||||
|
return ConditionalPhrase();
|
||||||
|
return ConditionalPhrase(this, PhraseData::DatePartYear);
|
||||||
|
}
|
||||||
|
ConditionalPhrase month() {
|
||||||
|
if (!is_valid_template<T, QDate>())
|
||||||
|
return ConditionalPhrase();
|
||||||
|
return ConditionalPhrase(this, PhraseData::DatePartMonth);
|
||||||
|
}
|
||||||
|
ConditionalPhrase day() {
|
||||||
|
if (!is_valid_template<T, QDate>())
|
||||||
|
return ConditionalPhrase();
|
||||||
|
return ConditionalPhrase(this, PhraseData::DatePartDay);
|
||||||
|
}
|
||||||
|
ConditionalPhrase hour() {
|
||||||
|
if (!is_valid_template<T, QTime>())
|
||||||
|
return ConditionalPhrase();
|
||||||
|
return ConditionalPhrase(this, PhraseData::DatePartHour);
|
||||||
|
}
|
||||||
|
ConditionalPhrase minute() {
|
||||||
|
if (!is_valid_template<T, QTime>())
|
||||||
|
return ConditionalPhrase();
|
||||||
|
return ConditionalPhrase(this, PhraseData::DatePartMinute);
|
||||||
|
}
|
||||||
|
ConditionalPhrase second() {
|
||||||
|
if (!is_valid_template<T, QTime>())
|
||||||
|
return ConditionalPhrase();
|
||||||
|
return ConditionalPhrase(this, PhraseData::DatePartSecond);
|
||||||
|
}
|
||||||
|
ConditionalPhrase msec() {
|
||||||
|
if (!is_valid_template<T, QTime>())
|
||||||
|
return ConditionalPhrase();
|
||||||
|
return ConditionalPhrase(this, PhraseData::DatePartMilisecond);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
NUT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // DATEPHRASE_H
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "fieldphrase.h"
|
||||||
|
|
@ -0,0 +1,105 @@
|
||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** 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 FIELDPHRASE_H
|
||||||
|
#define FIELDPHRASE_H
|
||||||
|
|
||||||
|
#include "../defines.h"
|
||||||
|
|
||||||
|
#include "abstractfieldphrase.h"
|
||||||
|
|
||||||
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
template<typename T, typename enable = void>
|
||||||
|
class NUT_EXPORT FieldPhrase : public AbstractFieldPhrase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FieldPhrase(const char *className, const char *s) :
|
||||||
|
AbstractFieldPhrase(className, s)
|
||||||
|
{}
|
||||||
|
|
||||||
|
AssignmentPhrase operator =(const QVariant &other) {
|
||||||
|
return AssignmentPhrase(this, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConditionalPhrase operator ==(const QVariant &other) {
|
||||||
|
return ConditionalPhrase(this, PhraseData::Equal, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class NUT_EXPORT 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) \
|
||||||
|
{ \
|
||||||
|
return ConditionalPhrase(this, cond, val); \
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class NUT_EXPORT 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 // FIELDPHRASE_H
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
#include "numericphrase.h"
|
||||||
|
|
||||||
|
|
@ -0,0 +1,90 @@
|
||||||
|
#ifndef NUMERICPHRASE_H
|
||||||
|
#define NUMERICPHRASE_H
|
||||||
|
|
||||||
|
#include "fieldphrase.h"
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
#define SPECIALIZATION_NUMERIC_MEMBER(type, op, cond) \
|
||||||
|
ConditionalPhrase operator op(const QVariant &other) \
|
||||||
|
{ \
|
||||||
|
return ConditionalPhrase(this, cond, other); \
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class FieldPhrase<T, typename std::enable_if<
|
||||||
|
std::is_floating_point<T>::value || std::is_integral<T>::value
|
||||||
|
>::type>
|
||||||
|
: public AbstractFieldPhrase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FieldPhrase(const char *className, const char *s) :
|
||||||
|
AbstractFieldPhrase(className, s)
|
||||||
|
{}
|
||||||
|
|
||||||
|
AssignmentPhrase operator =(const QVariant &other) {
|
||||||
|
return AssignmentPhrase(this, other);
|
||||||
|
}
|
||||||
|
AssignmentPhrase operator =(ConditionalPhrase &&other) {
|
||||||
|
return AssignmentPhrase(new PhraseData(data, PhraseData::Equal, other.data));
|
||||||
|
}
|
||||||
|
ConditionalPhrase between(const QVariant &min, const QVariant &max)
|
||||||
|
{
|
||||||
|
return ConditionalPhrase(this, PhraseData::Between,
|
||||||
|
QVariantList() << min << max);
|
||||||
|
}
|
||||||
|
ConditionalPhrase operator ++()
|
||||||
|
{
|
||||||
|
return ConditionalPhrase(this, PhraseData::Add, 1);
|
||||||
|
}
|
||||||
|
ConditionalPhrase operator --()
|
||||||
|
{
|
||||||
|
return ConditionalPhrase(this, PhraseData::Minus, 1);
|
||||||
|
}
|
||||||
|
ConditionalPhrase operator ++(int)
|
||||||
|
{
|
||||||
|
return ConditionalPhrase(this, PhraseData::Add, 1);
|
||||||
|
}
|
||||||
|
ConditionalPhrase operator --(int)
|
||||||
|
{
|
||||||
|
return ConditionalPhrase(this, PhraseData::Minus, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
SPECIALIZATION_NUMERIC_MEMBER(type, <, PhraseData::Less)
|
||||||
|
SPECIALIZATION_NUMERIC_MEMBER(type, <=, PhraseData::LessEqual)
|
||||||
|
SPECIALIZATION_NUMERIC_MEMBER(type, >, PhraseData::Greater)
|
||||||
|
SPECIALIZATION_NUMERIC_MEMBER(type, >=, PhraseData::GreaterEqual)
|
||||||
|
SPECIALIZATION_NUMERIC_MEMBER(type, %, PhraseData::Mod)
|
||||||
|
|
||||||
|
SPECIALIZATION_NUMERIC_MEMBER(type, +, PhraseData::Add)
|
||||||
|
SPECIALIZATION_NUMERIC_MEMBER(type, -, PhraseData::Minus)
|
||||||
|
SPECIALIZATION_NUMERIC_MEMBER(type, *, PhraseData::Multiple)
|
||||||
|
SPECIALIZATION_NUMERIC_MEMBER(type, /, PhraseData::Divide)
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SPECIALIZATION_NUMERIC_TYPE(type) \
|
||||||
|
template<> \
|
||||||
|
class FieldPhrase<type> : public NumericPhrase \
|
||||||
|
{ \
|
||||||
|
public: \
|
||||||
|
FieldPhrase(const char *className, const char *s) : \
|
||||||
|
NumericPhrase(className, s) \
|
||||||
|
{} \
|
||||||
|
};
|
||||||
|
|
||||||
|
//SPECIALIZATION_NUMERIC_TYPE(qint8)
|
||||||
|
//SPECIALIZATION_NUMERIC_TYPE(qint16)
|
||||||
|
//SPECIALIZATION_NUMERIC_TYPE(qint32)
|
||||||
|
//SPECIALIZATION_NUMERIC_TYPE(qint64)
|
||||||
|
|
||||||
|
//SPECIALIZATION_NUMERIC_TYPE(quint8)
|
||||||
|
//SPECIALIZATION_NUMERIC_TYPE(quint16)
|
||||||
|
//SPECIALIZATION_NUMERIC_TYPE(quint32)
|
||||||
|
//SPECIALIZATION_NUMERIC_TYPE(quint64)
|
||||||
|
|
||||||
|
//SPECIALIZATION_NUMERIC_TYPE(qreal)
|
||||||
|
|
||||||
|
NUT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // NUMERICPHRASE_H
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "phrasedata.h"
|
||||||
|
|
||||||
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
PhraseData::PhraseData() :
|
||||||
|
className(""), fieldName(""),
|
||||||
|
type(Field), operatorCond(NotAssign),
|
||||||
|
left(nullptr), right(nullptr), operand(QVariant::Invalid), isNot(false), parents(1)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
PhraseData::PhraseData(const char *className, const char *fieldName) :
|
||||||
|
className(className), fieldName(fieldName),
|
||||||
|
type(Field), operatorCond(NotAssign),
|
||||||
|
left(nullptr), right(nullptr), operand(QVariant::Invalid), isNot(false), parents(1)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
PhraseData::PhraseData(PhraseData *l, PhraseData::Condition o)
|
||||||
|
: className(nullptr), fieldName(nullptr),
|
||||||
|
type(WithoutOperand), operatorCond(o), left(l), right(nullptr),
|
||||||
|
isNot(false), parents(1)
|
||||||
|
{
|
||||||
|
l->parents++;
|
||||||
|
}
|
||||||
|
|
||||||
|
PhraseData::PhraseData(PhraseData *l, PhraseData::Condition o,
|
||||||
|
PhraseData *r)
|
||||||
|
: className(nullptr), fieldName(nullptr),
|
||||||
|
type(WithOther), operatorCond(o),
|
||||||
|
left(l), right(r),
|
||||||
|
isNot(false), parents(1)
|
||||||
|
{
|
||||||
|
l->parents++;
|
||||||
|
r->parents++;
|
||||||
|
}
|
||||||
|
|
||||||
|
PhraseData::PhraseData(PhraseData *l, PhraseData::Condition o, QVariant r)
|
||||||
|
: className(nullptr), fieldName(nullptr),
|
||||||
|
type(WithVariant), operatorCond(o), left(l),
|
||||||
|
right(nullptr), operand(r), isNot(false), parents(1)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
PhraseData *PhraseData::operator =(PhraseData *other)
|
||||||
|
{
|
||||||
|
other->parents++;
|
||||||
|
return other;
|
||||||
|
}
|
||||||
|
|
||||||
|
PhraseData &PhraseData::operator =(PhraseData &other)
|
||||||
|
{
|
||||||
|
other.parents++;
|
||||||
|
return other;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PhraseData::toString() const
|
||||||
|
{
|
||||||
|
return QString("[%1].%2").arg(className, fieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhraseData::cleanUp()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhraseData::cleanUp(PhraseData *d)
|
||||||
|
{
|
||||||
|
if (d->left)
|
||||||
|
cleanUp(d->left);
|
||||||
|
if (d->right)
|
||||||
|
cleanUp(d->right);
|
||||||
|
}
|
||||||
|
|
||||||
|
NUT_END_NAMESPACE
|
||||||
|
|
@ -0,0 +1,116 @@
|
||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** 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 PHRASEDATA_H
|
||||||
|
#define PHRASEDATA_H
|
||||||
|
|
||||||
|
#include "../defines.h"
|
||||||
|
|
||||||
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class NUT_EXPORT PhraseData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Condition {
|
||||||
|
NotAssign = 0,
|
||||||
|
Equal,
|
||||||
|
Less,
|
||||||
|
LessEqual,
|
||||||
|
Null,
|
||||||
|
In,
|
||||||
|
Like,
|
||||||
|
|
||||||
|
Not = 10,
|
||||||
|
NotEqual,
|
||||||
|
GreaterEqual,
|
||||||
|
Greater,
|
||||||
|
NotNull,
|
||||||
|
NotIn,
|
||||||
|
NotLike,
|
||||||
|
|
||||||
|
And = 20,
|
||||||
|
Or,
|
||||||
|
|
||||||
|
Add,
|
||||||
|
Minus,
|
||||||
|
Multiple,
|
||||||
|
Divide,
|
||||||
|
Mod,
|
||||||
|
|
||||||
|
Between,
|
||||||
|
|
||||||
|
//date and time
|
||||||
|
AddYears,
|
||||||
|
AddMonths,
|
||||||
|
AddDays,
|
||||||
|
AddHours,
|
||||||
|
AddMinutes,
|
||||||
|
AddSeconds,
|
||||||
|
|
||||||
|
DatePartYear,
|
||||||
|
DatePartMonth,
|
||||||
|
DatePartDay,
|
||||||
|
DatePartHour,
|
||||||
|
DatePartMinute,
|
||||||
|
DatePartSecond,
|
||||||
|
DatePartMilisecond
|
||||||
|
// // special types
|
||||||
|
// Distance
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Type { Field, WithVariant, WithOther, WithoutOperand };
|
||||||
|
|
||||||
|
const char *className;
|
||||||
|
const char *fieldName;
|
||||||
|
|
||||||
|
Type type;
|
||||||
|
|
||||||
|
Condition operatorCond;
|
||||||
|
|
||||||
|
PhraseData *left;
|
||||||
|
PhraseData *right;
|
||||||
|
|
||||||
|
QVariant operand;
|
||||||
|
bool isNot;
|
||||||
|
quint16 parents;
|
||||||
|
|
||||||
|
PhraseData();
|
||||||
|
PhraseData(const char *className, const char *fieldName);
|
||||||
|
PhraseData(PhraseData *l, Condition o);
|
||||||
|
PhraseData(PhraseData *l, Condition o, PhraseData *r);
|
||||||
|
PhraseData(PhraseData *l, Condition o, QVariant r);
|
||||||
|
// explicit PhraseData(const PhraseData &other);
|
||||||
|
// explicit PhraseData(const PhraseData *other);
|
||||||
|
|
||||||
|
PhraseData *operator =(PhraseData *other);
|
||||||
|
PhraseData &operator =(PhraseData &other);
|
||||||
|
|
||||||
|
QString toString() const;
|
||||||
|
|
||||||
|
~PhraseData() = default;
|
||||||
|
|
||||||
|
void cleanUp();
|
||||||
|
private:
|
||||||
|
void cleanUp(PhraseData *d);
|
||||||
|
};
|
||||||
|
|
||||||
|
NUT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // PHRASEDATA_H
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "phrasedatalist.h"
|
||||||
|
|
||||||
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
PhraseDataList::PhraseDataList() : QList<PhraseData*>()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
PhraseDataList::PhraseDataList(const PhraseDataList &other) : QList<PhraseData*>()
|
||||||
|
{
|
||||||
|
// auto &o = const_cast<PhraseDataList&>(other);
|
||||||
|
PhraseDataList::const_iterator i;
|
||||||
|
for (i = other.constBegin(); i != other.constEnd(); ++i)
|
||||||
|
append(*i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhraseDataList::append(PhraseData *d)
|
||||||
|
{
|
||||||
|
d->parents++;
|
||||||
|
QList<PhraseData*>::append(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhraseDataList::append(QList<PhraseData *> &dl)
|
||||||
|
{
|
||||||
|
foreach (PhraseData *d, dl)
|
||||||
|
d->parents++;
|
||||||
|
QList<PhraseData*>::append(dl);
|
||||||
|
}
|
||||||
|
|
||||||
|
PhraseDataList::~PhraseDataList()
|
||||||
|
{
|
||||||
|
QList<PhraseData*>::iterator i;
|
||||||
|
for (i = begin(); i != end(); ++i) {
|
||||||
|
(*i)->cleanUp();
|
||||||
|
if (!--(*i)->parents)
|
||||||
|
delete *i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NUT_END_NAMESPACE
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** 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 PHRASEDATALIST_H
|
||||||
|
#define PHRASEDATALIST_H
|
||||||
|
|
||||||
|
#include "phrasedata.h"
|
||||||
|
|
||||||
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class NUT_EXPORT PhraseDataList : public QList<PhraseData*>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PhraseDataList();
|
||||||
|
PhraseDataList(const PhraseDataList &other);
|
||||||
|
void append(PhraseData *d);
|
||||||
|
void append(QList<PhraseData*> &dl);
|
||||||
|
virtual ~PhraseDataList();
|
||||||
|
};
|
||||||
|
|
||||||
|
NUT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // PHRASEDATALIST_H
|
||||||
|
|
@ -0,0 +1,94 @@
|
||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "abstractfieldphrase.h"
|
||||||
|
#include "phraselist.h"
|
||||||
|
|
||||||
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
PhraseList::PhraseList() : isValid(false)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
PhraseList::PhraseList(const PhraseList &other) : isValid(true)
|
||||||
|
{
|
||||||
|
data = qMove(other.data);
|
||||||
|
const_cast<PhraseList&>(other).data.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
PhraseList::PhraseList(PhraseList &&other)
|
||||||
|
{
|
||||||
|
data = other.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
PhraseList::PhraseList(const AbstractFieldPhrase &other) : isValid(true)
|
||||||
|
{
|
||||||
|
data.append(other.data);
|
||||||
|
incAllDataParents();
|
||||||
|
}
|
||||||
|
|
||||||
|
PhraseList::PhraseList(const AbstractFieldPhrase *left,
|
||||||
|
const AbstractFieldPhrase &right)
|
||||||
|
: isValid(true)
|
||||||
|
{
|
||||||
|
data.append(left->data);
|
||||||
|
data.append(right.data);
|
||||||
|
incAllDataParents();
|
||||||
|
}
|
||||||
|
|
||||||
|
PhraseList::PhraseList(PhraseList *left, PhraseList *right) : isValid(true)
|
||||||
|
{
|
||||||
|
// data = qMove(left->data + right->data);
|
||||||
|
data.append(left->data);
|
||||||
|
data.append(right->data);
|
||||||
|
// left->data.clear();
|
||||||
|
// right->data.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
PhraseList::PhraseList(PhraseList *left, const AbstractFieldPhrase *right)
|
||||||
|
: isValid(true)
|
||||||
|
{
|
||||||
|
data.append(left->data);
|
||||||
|
data.append(right->data);
|
||||||
|
incAllDataParents();
|
||||||
|
}
|
||||||
|
|
||||||
|
PhraseList &PhraseList::operator =(const PhraseList &other)
|
||||||
|
{
|
||||||
|
data.append(const_cast<PhraseList&>(other).data);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
PhraseList PhraseList::operator |(const AbstractFieldPhrase &other) {
|
||||||
|
return PhraseList(this, &other);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhraseList::incAllDataParents()
|
||||||
|
{
|
||||||
|
// foreach (PhraseData *d, data)
|
||||||
|
// d->parents++;
|
||||||
|
}
|
||||||
|
|
||||||
|
PhraseList PhraseList::operator |(PhraseList &other) {
|
||||||
|
return PhraseList(this, &other);
|
||||||
|
}
|
||||||
|
|
||||||
|
NUT_END_NAMESPACE
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** 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 PHRASELIST_H
|
||||||
|
#define PHRASELIST_H
|
||||||
|
|
||||||
|
#include "../defines.h"
|
||||||
|
|
||||||
|
#include "phrasedatalist.h"
|
||||||
|
|
||||||
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class AbstractFieldPhrase;
|
||||||
|
class NUT_EXPORT PhraseList
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool isValid;
|
||||||
|
PhraseDataList data;
|
||||||
|
explicit PhraseList();
|
||||||
|
PhraseList(const PhraseList &other);
|
||||||
|
PhraseList(PhraseList &&other);
|
||||||
|
PhraseList(const AbstractFieldPhrase &other);
|
||||||
|
PhraseList(const AbstractFieldPhrase *left, const AbstractFieldPhrase &right);
|
||||||
|
PhraseList(PhraseList *left, PhraseList *right);
|
||||||
|
PhraseList(PhraseList *left, const AbstractFieldPhrase *right);
|
||||||
|
virtual ~PhraseList() = default;
|
||||||
|
|
||||||
|
PhraseList &operator =(const PhraseList &other);
|
||||||
|
PhraseList operator |(PhraseList &other);
|
||||||
|
PhraseList operator |(const AbstractFieldPhrase &other);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void incAllDataParents();
|
||||||
|
};
|
||||||
|
|
||||||
|
NUT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // PHRASELIST_H
|
||||||
|
|
@ -23,15 +23,11 @@
|
||||||
NUT_BEGIN_NAMESPACE
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
QueryPrivate::QueryPrivate(QueryBase *parent) : q_ptr(parent),
|
QueryPrivate::QueryPrivate(QueryBase *parent) : q_ptr(parent),
|
||||||
database(0), tableSet(0), skip(-1), take(-1)
|
database(nullptr), tableSet(nullptr), skip(-1), take(-1)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QueryPrivate::~QueryPrivate()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \class Query
|
* \class Query
|
||||||
* \brief This class hold a query. A query can be used for getting database rows, editing or deleting without row fetching.
|
* \brief This class hold a query. A query can be used for getting database rows, editing or deleting without row fetching.
|
||||||
|
|
|
||||||
160
src/query.h
160
src/query.h
|
|
@ -29,7 +29,13 @@
|
||||||
#include <QtSql/QSqlResult>
|
#include <QtSql/QSqlResult>
|
||||||
#include <QtSql/QSqlError>
|
#include <QtSql/QSqlError>
|
||||||
#include <QtSql/QSqlQueryModel>
|
#include <QtSql/QSqlQueryModel>
|
||||||
|
#include <QtSql/QSqlQuery>
|
||||||
|
|
||||||
|
#ifdef NUT_SHARED_POINTER
|
||||||
|
#include <QtCore/QSharedPointer>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "table.h"
|
||||||
#include "query_p.h"
|
#include "query_p.h"
|
||||||
#include "database.h"
|
#include "database.h"
|
||||||
#include "databasemodel.h"
|
#include "databasemodel.h"
|
||||||
|
|
@ -38,6 +44,7 @@
|
||||||
#include "querybase_p.h"
|
#include "querybase_p.h"
|
||||||
#include "phrase.h"
|
#include "phrase.h"
|
||||||
#include "tablemodel.h"
|
#include "tablemodel.h"
|
||||||
|
#include "sqlmodel.h"
|
||||||
|
|
||||||
NUT_BEGIN_NAMESPACE
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
|
@ -50,6 +57,14 @@ template <class T>
|
||||||
bool m_autoDelete;
|
bool m_autoDelete;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
//#ifdef NUT_SHARED_POINTER
|
||||||
|
// typedef QList<QSharedPointer<T>> RowList;
|
||||||
|
// typedef QSharedPointer<T> Row;
|
||||||
|
//#else
|
||||||
|
// typedef QList<T*> RowList;
|
||||||
|
// typedef T* Row;
|
||||||
|
//#endif
|
||||||
|
|
||||||
explicit Query(Database *database, TableSetBase *tableSet, bool autoDelete);
|
explicit Query(Database *database, TableSetBase *tableSet, bool autoDelete);
|
||||||
~Query();
|
~Query();
|
||||||
|
|
||||||
|
|
@ -74,16 +89,20 @@ public:
|
||||||
Query<T> *setWhere(const ConditionalPhrase &ph);
|
Query<T> *setWhere(const ConditionalPhrase &ph);
|
||||||
|
|
||||||
//data selecting
|
//data selecting
|
||||||
T *first();
|
Row<T> first();
|
||||||
QList<T*> toList(int count = -1);
|
RowList<T> toList(int count = -1);
|
||||||
template <typename F>
|
template <typename F>
|
||||||
QList<F> select(const FieldPhrase<F> f);
|
QList<F> select(const FieldPhrase<F> f);
|
||||||
|
|
||||||
|
template<typename O>
|
||||||
|
QList<O> select(const std::function<O(const QSqlQuery &q)> allocator);
|
||||||
|
|
||||||
int count();
|
int count();
|
||||||
QVariant max(const FieldPhrase<int> &f);
|
QVariant max(const FieldPhrase<int> &f);
|
||||||
QVariant min(const FieldPhrase<int> &f);
|
QVariant min(const FieldPhrase<int> &f);
|
||||||
QVariant average(const FieldPhrase<int> &f);
|
QVariant average(const FieldPhrase<int> &f);
|
||||||
|
|
||||||
QVariant insert(AssignmentPhraseList p);
|
QVariant insert(const AssignmentPhraseList &p);
|
||||||
|
|
||||||
//data mailpulation
|
//data mailpulation
|
||||||
int update(const AssignmentPhraseList &ph);
|
int update(const AssignmentPhraseList &ph);
|
||||||
|
|
@ -91,17 +110,46 @@ public:
|
||||||
int remove();
|
int remove();
|
||||||
|
|
||||||
QSqlQueryModel *toModel();
|
QSqlQueryModel *toModel();
|
||||||
|
void toModel(QSqlQueryModel *model);
|
||||||
|
void toModel(SqlModel *model);
|
||||||
|
|
||||||
//debug purpose
|
//debug purpose
|
||||||
QString sqlCommand() const;
|
QString sqlCommand() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template<typename T>
|
||||||
inline Query<T> *createQuery(TableSet<T> *tableSet)
|
template<typename O>
|
||||||
|
Q_OUTOFLINE_TEMPLATE QList<O> Query<T>::select(const std::function<O (const QSqlQuery &)> allocator)
|
||||||
{
|
{
|
||||||
return tableSet->query();
|
Q_D(Query);
|
||||||
|
QList<O> ret;
|
||||||
|
|
||||||
|
d->joins.prepend(d->tableName);
|
||||||
|
d->sql = d->database->sqlGenertor()->selectCommand(
|
||||||
|
d->tableName,
|
||||||
|
SqlGeneratorBase::SignleField, "*",
|
||||||
|
d->wherePhrase,
|
||||||
|
d->relations,
|
||||||
|
d->skip, d->take);
|
||||||
|
|
||||||
|
QSqlQuery q = d->database->exec(d->sql);
|
||||||
|
|
||||||
|
while (q.next()) {
|
||||||
|
O obj = allocator(q);
|
||||||
|
ret.append(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_autoDelete)
|
||||||
|
deleteLater();
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//template <typename T>
|
||||||
|
//inline Query<T> *createQuery(TableSet<T> *tableSet)
|
||||||
|
//{
|
||||||
|
// return tableSet->query();
|
||||||
|
//}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
Q_OUTOFLINE_TEMPLATE Query<T>::Query(Database *database, TableSetBase *tableSet,
|
Q_OUTOFLINE_TEMPLATE Query<T>::Query(Database *database, TableSetBase *tableSet,
|
||||||
bool autoDelete)
|
bool autoDelete)
|
||||||
|
|
@ -115,7 +163,7 @@ Q_OUTOFLINE_TEMPLATE Query<T>::Query(Database *database, TableSetBase *tableSet,
|
||||||
d->className = T::staticMetaObject.className();
|
d->className = T::staticMetaObject.className();
|
||||||
d->tableName =
|
d->tableName =
|
||||||
d->database->model()
|
d->database->model()
|
||||||
.tableByClassName(T::staticMetaObject.className())
|
.tableByClassName(d->className)
|
||||||
->name();
|
->name();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,17 +175,17 @@ Q_OUTOFLINE_TEMPLATE Query<T>::~Query()
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
Q_OUTOFLINE_TEMPLATE QList<T *> Query<T>::toList(int count)
|
Q_OUTOFLINE_TEMPLATE RowList<T> Query<T>::toList(int count)
|
||||||
{
|
{
|
||||||
Q_UNUSED(count);
|
Q_UNUSED(count);
|
||||||
Q_D(Query);
|
Q_D(Query);
|
||||||
QList<T*> returnList;
|
RowList<T> returnList;
|
||||||
d->select = "*";
|
d->select = "*";
|
||||||
|
|
||||||
d->sql = d->database->sqlGenertor()->selectCommand(
|
d->sql = d->database->sqlGenertor()->selectCommand(
|
||||||
d->tableName, d->fieldPhrase, d->wherePhrase, d->orderPhrase,
|
d->tableName, d->fieldPhrase, d->wherePhrase, d->orderPhrase,
|
||||||
d->relations, d->skip, d->take);
|
d->relations, d->skip, d->take);
|
||||||
|
qDebug()<<d->sql;
|
||||||
QSqlQuery q = d->database->exec(d->sql);
|
QSqlQuery q = d->database->exec(d->sql);
|
||||||
if (q.lastError().isValid()) {
|
if (q.lastError().isValid()) {
|
||||||
qDebug() << q.lastError().text();
|
qDebug() << q.lastError().text();
|
||||||
|
|
@ -217,7 +265,6 @@ Q_OUTOFLINE_TEMPLATE QList<T *> Query<T>::toList(int count)
|
||||||
|
|
||||||
int p = levels.count();
|
int p = levels.count();
|
||||||
int n = -1;
|
int n = -1;
|
||||||
int lastP = p;
|
|
||||||
|
|
||||||
while (p) {
|
while (p) {
|
||||||
// Q_ASSERT(p != lastP);
|
// Q_ASSERT(p != lastP);
|
||||||
|
|
@ -252,24 +299,29 @@ Q_OUTOFLINE_TEMPLATE QList<T *> Query<T>::toList(int count)
|
||||||
Table *table;
|
Table *table;
|
||||||
if (data.table->className() == d->className) {
|
if (data.table->className() == d->className) {
|
||||||
table = new T();
|
table = new T();
|
||||||
table->setParentTableSet(d->tableSet);
|
#ifdef NUT_SHARED_POINTER
|
||||||
|
auto shp = QSharedPointer<T>(qobject_cast<T*>(table));
|
||||||
|
returnList.append(shp);
|
||||||
|
#else
|
||||||
returnList.append(dynamic_cast<T*>(table));
|
returnList.append(dynamic_cast<T*>(table));
|
||||||
|
#endif
|
||||||
|
table->setParentTableSet(d->tableSet);
|
||||||
} else {
|
} else {
|
||||||
const QMetaObject *childMetaObject
|
const QMetaObject *childMetaObject
|
||||||
= QMetaType::metaObjectForType(data.table->typeId());
|
= QMetaType::metaObjectForType(data.table->typeId());
|
||||||
table = qobject_cast<Table *>(childMetaObject->newInstance());
|
table = qobject_cast<Table *>(childMetaObject->newInstance());
|
||||||
|
|
||||||
if (!table)
|
if (!table)
|
||||||
qFatal("Could not create instance of %s",
|
qFatal("Could not create instance of %s",
|
||||||
qPrintable(data.table->name()));
|
qPrintable(data.table->name()));
|
||||||
|
|
||||||
qDebug() << data.table->name() << "created";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList childFields = data.table->fieldsNames();
|
QList<FieldModel*> childFields = data.table->fields();
|
||||||
foreach (QString field, childFields)
|
foreach (FieldModel *field, childFields)
|
||||||
table->setProperty(field.toLatin1().data(),
|
table->setProperty(field->name.toLatin1().data(),
|
||||||
q.value(data.table->name() + "." + field));
|
d->database->sqlGenertor()->unescapeValue(
|
||||||
|
field->type,
|
||||||
|
q.value(data.table->name() + "." + field->name)));
|
||||||
|
|
||||||
for (int i = 0; i < data.masters.count(); ++i) {
|
for (int i = 0; i < data.masters.count(); ++i) {
|
||||||
int master = data.masters[i];
|
int master = data.masters[i];
|
||||||
|
|
@ -287,13 +339,13 @@ Q_OUTOFLINE_TEMPLATE QList<T *> Query<T>::toList(int count)
|
||||||
|
|
||||||
//set last created row
|
//set last created row
|
||||||
data.lastRow = table;
|
data.lastRow = table;
|
||||||
|
|
||||||
lastP = p;
|
|
||||||
} //while
|
} //while
|
||||||
} // while
|
} // while
|
||||||
|
|
||||||
|
#ifndef NUT_SHARED_POINTER
|
||||||
if (m_autoDelete)
|
if (m_autoDelete)
|
||||||
deleteLater();
|
deleteLater();
|
||||||
|
#endif
|
||||||
return returnList;
|
return returnList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -325,11 +377,11 @@ Q_OUTOFLINE_TEMPLATE QList<F> Query<T>::select(const FieldPhrase<F> f)
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
Q_OUTOFLINE_TEMPLATE T *Query<T>::first()
|
Q_OUTOFLINE_TEMPLATE Row<T> Query<T>::first()
|
||||||
{
|
{
|
||||||
skip(0);
|
skip(0);
|
||||||
take(1);
|
take(1);
|
||||||
QList<T*> list = toList(1);
|
RowList<T> list = toList(1);
|
||||||
|
|
||||||
if (list.count())
|
if (list.count())
|
||||||
return list.first();
|
return list.first();
|
||||||
|
|
@ -412,7 +464,7 @@ Q_OUTOFLINE_TEMPLATE QVariant Query<T>::average(const FieldPhrase<int> &f)
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::insert(AssignmentPhraseList p)
|
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::insert(const AssignmentPhraseList &p)
|
||||||
{
|
{
|
||||||
Q_D(Query);
|
Q_D(Query);
|
||||||
d->sql = d->database->sqlGenertor()
|
d->sql = d->database->sqlGenertor()
|
||||||
|
|
@ -520,6 +572,7 @@ Q_OUTOFLINE_TEMPLATE int Query<T>::update(const AssignmentPhraseList &ph)
|
||||||
d->tableName,
|
d->tableName,
|
||||||
ph,
|
ph,
|
||||||
d->wherePhrase);
|
d->wherePhrase);
|
||||||
|
|
||||||
QSqlQuery q = d->database->exec(d->sql);
|
QSqlQuery q = d->database->exec(d->sql);
|
||||||
|
|
||||||
if (m_autoDelete)
|
if (m_autoDelete)
|
||||||
|
|
@ -543,6 +596,14 @@ Q_OUTOFLINE_TEMPLATE int Query<T>::remove()
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
Q_OUTOFLINE_TEMPLATE QSqlQueryModel *Query<T>::toModel()
|
Q_OUTOFLINE_TEMPLATE QSqlQueryModel *Query<T>::toModel()
|
||||||
|
{
|
||||||
|
QSqlQueryModel *model = new QSqlQueryModel;
|
||||||
|
toModel(model);
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
Q_OUTOFLINE_TEMPLATE void Query<T>::toModel(QSqlQueryModel *model)
|
||||||
{
|
{
|
||||||
Q_D(Query);
|
Q_D(Query);
|
||||||
|
|
||||||
|
|
@ -551,9 +612,8 @@ Q_OUTOFLINE_TEMPLATE QSqlQueryModel *Query<T>::toModel()
|
||||||
d->fieldPhrase,
|
d->fieldPhrase,
|
||||||
d->wherePhrase, d->orderPhrase, d->relations,
|
d->wherePhrase, d->orderPhrase, d->relations,
|
||||||
d->skip, d->take);
|
d->skip, d->take);
|
||||||
qDebug() << d->sql;
|
|
||||||
DatabaseModel dbModel = d->database->model();
|
DatabaseModel dbModel = d->database->model();
|
||||||
QSqlQueryModel *model = new QSqlQueryModel;
|
|
||||||
model->setQuery(d->sql, d->database->database());
|
model->setQuery(d->sql, d->database->database());
|
||||||
|
|
||||||
int fieldIndex = 0;
|
int fieldIndex = 0;
|
||||||
|
|
@ -563,8 +623,6 @@ qDebug() << d->sql;
|
||||||
QString displayName = dbModel.tableByClassName(pd->className)
|
QString displayName = dbModel.tableByClassName(pd->className)
|
||||||
->field(pd->fieldName)->displayName;
|
->field(pd->fieldName)->displayName;
|
||||||
|
|
||||||
qDebug() << "Display name for"<<pd->className<<pd->fieldName
|
|
||||||
<<"="<<displayName;
|
|
||||||
model->setHeaderData(fieldIndex++,
|
model->setHeaderData(fieldIndex++,
|
||||||
Qt::Horizontal,
|
Qt::Horizontal,
|
||||||
displayName);
|
displayName);
|
||||||
|
|
@ -577,8 +635,43 @@ qDebug() << d->sql;
|
||||||
f->displayName);
|
f->displayName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return model;
|
template<class T>
|
||||||
|
Q_OUTOFLINE_TEMPLATE void Query<T>::toModel(SqlModel *model)
|
||||||
|
{
|
||||||
|
Q_D(Query);
|
||||||
|
|
||||||
|
d->sql = d->database->sqlGenertor()->selectCommand(
|
||||||
|
d->tableName,
|
||||||
|
d->fieldPhrase,
|
||||||
|
d->wherePhrase, d->orderPhrase, d->relations,
|
||||||
|
d->skip, d->take);
|
||||||
|
|
||||||
|
model->setTable(toList());
|
||||||
|
/*
|
||||||
|
DatabaseModel dbModel = d->database->model();
|
||||||
|
model->setQuery(d->sql, d->database->database());
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
model->setHeaderData(fieldIndex++,
|
||||||
|
Qt::Horizontal,
|
||||||
|
displayName);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
TableModel *tbl = d->database->model().tableByName(d->tableName);
|
||||||
|
foreach (FieldModel *f, tbl->fields()) {
|
||||||
|
model->setHeaderData(fieldIndex++,
|
||||||
|
Qt::Horizontal,
|
||||||
|
f->displayName);
|
||||||
|
}
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
|
@ -588,6 +681,15 @@ Q_OUTOFLINE_TEMPLATE QString Query<T>::sqlCommand() const
|
||||||
return d->sql;
|
return d->sql;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: complete this class later
|
||||||
|
//class RawQuery : public Query<void>
|
||||||
|
//{
|
||||||
|
//public:
|
||||||
|
// void setRawCommand(const QString &sql) {
|
||||||
|
|
||||||
|
// }
|
||||||
|
//};
|
||||||
|
|
||||||
NUT_END_NAMESPACE
|
NUT_END_NAMESPACE
|
||||||
|
|
||||||
#endif // QUERY_H
|
#endif // QUERY_H
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,9 @@
|
||||||
|
|
||||||
#include "phrase.h"
|
#include "phrase.h"
|
||||||
|
|
||||||
#include <QList>
|
#include <QtCore/QList>
|
||||||
#include <QString>
|
#include <QtCore/QString>
|
||||||
|
#include <QtCore/QSharedData>
|
||||||
|
|
||||||
NUT_BEGIN_NAMESPACE
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
|
@ -32,13 +33,13 @@ class Database;
|
||||||
class TableSetBase;
|
class TableSetBase;
|
||||||
class QueryBase;
|
class QueryBase;
|
||||||
struct RelationModel;
|
struct RelationModel;
|
||||||
class QueryPrivate{
|
class QueryPrivate : public QSharedData {
|
||||||
QueryBase *q_ptr;
|
QueryBase *q_ptr;
|
||||||
Q_DECLARE_PUBLIC(QueryBase)
|
Q_DECLARE_PUBLIC(QueryBase)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit QueryPrivate(QueryBase *parent);
|
explicit QueryPrivate(QueryBase *parent);
|
||||||
~QueryPrivate();
|
~QueryPrivate() = default;
|
||||||
|
|
||||||
QString sql;
|
QString sql;
|
||||||
QString className;
|
QString className;
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,9 @@ QueryBase::QueryBase(QObject *parent) : QObject(parent)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QueryBase::addTableToSet(TableSetBase *set, Table *table)
|
//void QueryBase::addTableToSet(TableSetBase *set, Table *table)
|
||||||
{
|
//{
|
||||||
set->add(table);
|
// set->add(table);
|
||||||
}
|
//}
|
||||||
|
|
||||||
NUT_END_NAMESPACE
|
NUT_END_NAMESPACE
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,10 @@
|
||||||
|
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
#include <QtCore/qglobal.h>
|
#include <QtCore/qglobal.h>
|
||||||
|
#include <QtCore/QExplicitlySharedDataPointer>
|
||||||
|
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
|
#include "query_p.h"
|
||||||
|
|
||||||
NUT_BEGIN_NAMESPACE
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
|
@ -33,11 +36,15 @@ class TableSetBase;
|
||||||
class QueryBase : public QObject
|
class QueryBase : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QExplicitlySharedDataPointer<QueryPrivate> d;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit QueryBase(QObject *parent = 0);
|
explicit QueryBase(QObject *parent = 0);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void addTableToSet(TableSetBase *set, Table *table);
|
// void addTableToSet(TableSetBase *set, Table *table);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,2 @@
|
||||||
#include "serializableobject.h"
|
#include "serializableobject.h"
|
||||||
|
|
||||||
SerializableObject::SerializableObject()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
class SerializableObject
|
class SerializableObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SerializableObject();
|
SerializableObject() = default;
|
||||||
|
|
||||||
virtual void load(const QVariant &value) = 0;
|
virtual void load(const QVariant &value) = 0;
|
||||||
virtual QVariant save() = 0;
|
virtual QVariant save() = 0;
|
||||||
|
|
|
||||||
|
|
@ -21,20 +21,33 @@
|
||||||
#include "database.h"
|
#include "database.h"
|
||||||
#include "tablesetbase_p.h"
|
#include "tablesetbase_p.h"
|
||||||
#include "databasemodel.h"
|
#include "databasemodel.h"
|
||||||
|
#include "tablemodel.h"
|
||||||
|
#include "table.h"
|
||||||
#include "sqlmodel_p.h"
|
#include "sqlmodel_p.h"
|
||||||
#include "sqlmodel.h"
|
#include "sqlmodel.h"
|
||||||
|
#include "query.h"
|
||||||
|
|
||||||
NUT_BEGIN_NAMESPACE
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
//SqlModel::SqlModel(Query *q) : QAbstractItemModel(q.)
|
||||||
|
//{
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
void SqlModel::setRenderer(const std::function<QVariant (int, QVariant)> &renderer)
|
||||||
|
{
|
||||||
|
_renderer = renderer;
|
||||||
|
}
|
||||||
|
|
||||||
SqlModel::SqlModel(Database *database, TableSetBase *tableSet, QObject *parent) :
|
SqlModel::SqlModel(Database *database, TableSetBase *tableSet, QObject *parent) :
|
||||||
QAbstractTableModel(parent)
|
QAbstractTableModel(parent), d_ptr(new SqlModelPrivate(this)), _renderer(nullptr)
|
||||||
{
|
{
|
||||||
Q_D(SqlModel);
|
Q_D(SqlModel);
|
||||||
d->model = database->model()
|
d->model = database->model()
|
||||||
.tableByClassName(tableSet->childClassName());
|
.tableByClassName(tableSet->childClassName());
|
||||||
d->tableName = d->model->name();
|
d->tableName = d->model->name();
|
||||||
|
|
||||||
|
|
||||||
// setQuery("SELECT * FROM " + d->tableName, database->databaseName());
|
// setQuery("SELECT * FROM " + d->tableName, database->databaseName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -62,8 +75,12 @@ QVariant SqlModel::data(const QModelIndex &index, int role) const
|
||||||
return QVariant("-");
|
return QVariant("-");
|
||||||
|
|
||||||
if (role == Qt::DisplayRole) {
|
if (role == Qt::DisplayRole) {
|
||||||
Table *t = d->rows.at(index.row());
|
Row<Table> t = d->rows.at(index.row());
|
||||||
return t->property(d->model->field(index.column())->name.toLocal8Bit().data());
|
QVariant v = t->property(d->model->field(index.column())->name.toLocal8Bit().data());
|
||||||
|
// emit beforeShowText(index.column(), v);
|
||||||
|
if (_renderer != nullptr)
|
||||||
|
v = _renderer(index.column(), v);
|
||||||
|
return v;
|
||||||
// LogData *d = dataList.at(index.row());
|
// LogData *d = dataList.at(index.row());
|
||||||
|
|
||||||
// switch (index.column()) {
|
// switch (index.column()) {
|
||||||
|
|
@ -85,9 +102,49 @@ QVariant SqlModel::data(const QModelIndex &index, int role) const
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
SqlModelPrivate::SqlModelPrivate()
|
void SqlModel::setRows(RowList<Table> rows)
|
||||||
|
{
|
||||||
|
Q_D(SqlModel);
|
||||||
|
beginRemoveRows(QModelIndex(), 0, d->rows.count());
|
||||||
|
d->rows.clear();
|
||||||
|
endRemoveRows();
|
||||||
|
beginInsertRows(QModelIndex(), 0, rows.count());
|
||||||
|
d->rows = rows;
|
||||||
|
endInsertRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SqlModel::append(Row<Table> table)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
{
|
||||||
|
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
||||||
|
Q_D(const SqlModel);
|
||||||
|
return d->model->field(section)->displayName;
|
||||||
|
}
|
||||||
|
return QAbstractItemModel::headerData(section, orientation, role);
|
||||||
|
}
|
||||||
|
|
||||||
|
Row<Table> SqlModel::at(const int &i) const
|
||||||
|
{
|
||||||
|
Q_D(const SqlModel);
|
||||||
|
return d->rows.at(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
SqlModelPrivate::SqlModelPrivate(SqlModel *parent) : q_ptr(parent)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NUT_END_NAMESPACE
|
NUT_END_NAMESPACE
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
|
|
||||||
#include <QtCore/QAbstractTableModel>
|
#include <QtCore/QAbstractTableModel>
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
|
#include <QList>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
NUT_BEGIN_NAMESPACE
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
|
@ -31,22 +33,52 @@ class TableSetBase;
|
||||||
class SqlModelPrivate;
|
class SqlModelPrivate;
|
||||||
class Table;
|
class Table;
|
||||||
class TableModel;
|
class TableModel;
|
||||||
class SqlModel : public QAbstractTableModel
|
|
||||||
|
class NUT_EXPORT SqlModel : public QAbstractTableModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
std::function <QVariant(int, QVariant)> _renderer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
// explicit SqlModel(Query *q);
|
||||||
explicit SqlModel(Database *database, TableSetBase *tableSet, QObject *parent = Q_NULLPTR);
|
explicit SqlModel(Database *database, TableSetBase *tableSet, QObject *parent = Q_NULLPTR);
|
||||||
|
|
||||||
int rowCount(const QModelIndex &parent) const;
|
int rowCount(const QModelIndex &parent) const;
|
||||||
int columnCount(const QModelIndex &parent) const;
|
int columnCount(const QModelIndex &parent) const;
|
||||||
QVariant data(const QModelIndex &index, int role) const;
|
QVariant data(const QModelIndex &index, int role) const;
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void setTable(RowList<T> rows);
|
||||||
|
|
||||||
|
void setRows(RowList<Table> rows);
|
||||||
|
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;
|
||||||
|
|
||||||
|
void setRenderer(const std::function<QVariant (int, QVariant)> &renderer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SqlModelPrivate *d_ptr;
|
SqlModelPrivate *d_ptr;
|
||||||
Q_DECLARE_PRIVATE(SqlModel)
|
Q_DECLARE_PRIVATE(SqlModel)
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void beforeShowText(int col, QVariant &value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
Q_OUTOFLINE_TEMPLATE void SqlModel::setTable(RowList<T> rows)
|
||||||
|
{
|
||||||
|
Q_D(SqlModel);
|
||||||
|
|
||||||
|
RowList<Table> tab;
|
||||||
|
foreach (auto t, rows)
|
||||||
|
tab.append(t);
|
||||||
|
setRows(tab);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
NUT_END_NAMESPACE
|
NUT_END_NAMESPACE
|
||||||
|
|
||||||
#endif // SQLMODEL_H
|
#endif // SQLMODEL_H
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef SQLMODEL_P_H
|
#ifndef SQLMODEL_P_H
|
||||||
#define SQLMODEL_P_H
|
#define SQLMODEL_P_H
|
||||||
|
|
||||||
|
#include <QSharedPointer>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
|
|
||||||
|
|
@ -13,11 +14,11 @@ class SqlModelPrivate {
|
||||||
SqlModel *q_ptr;
|
SqlModel *q_ptr;
|
||||||
Q_DECLARE_PUBLIC(SqlModel)
|
Q_DECLARE_PUBLIC(SqlModel)
|
||||||
public:
|
public:
|
||||||
explicit SqlModelPrivate();
|
explicit SqlModelPrivate(SqlModel *parent);
|
||||||
|
|
||||||
QString tableName;
|
QString tableName;
|
||||||
|
|
||||||
QList<Table*> rows;
|
RowList<Table> rows;
|
||||||
TableModel *model;
|
TableModel *model;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
DEFINES += NUT_SHARED_POINTER
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
$$PWD/generators/sqlgeneratorbase_p.h \
|
||||||
|
$$PWD/generators/postgresqlgenerator.h \
|
||||||
|
$$PWD/generators/mysqlgenerator.h \
|
||||||
|
$$PWD/generators/sqlitegenerator.h \
|
||||||
|
$$PWD/generators/sqlservergenerator.h \
|
||||||
|
$$PWD/tablesetbasedata.h \
|
||||||
|
$$PWD/types/dbgeography.h \
|
||||||
|
$$PWD/tableset.h \
|
||||||
|
$$PWD/defines_p.h \
|
||||||
|
$$PWD/defines.h \
|
||||||
|
$$PWD/query.h \
|
||||||
|
$$PWD/databasemodel.h \
|
||||||
|
$$PWD/changelogtable.h \
|
||||||
|
$$PWD/tablesetbase_p.h \
|
||||||
|
$$PWD/querybase_p.h \
|
||||||
|
$$PWD/tablemodel.h \
|
||||||
|
$$PWD/query_p.h \
|
||||||
|
$$PWD/table.h \
|
||||||
|
$$PWD/database.h \
|
||||||
|
$$PWD/database_p.h \
|
||||||
|
$$PWD/serializableobject.h \
|
||||||
|
$$PWD/sqlmodel.h \
|
||||||
|
$$PWD/sqlmodel_p.h \
|
||||||
|
$$PWD/phrase.h \
|
||||||
|
$$PWD/phrases/abstractfieldphrase.h \
|
||||||
|
$$PWD/phrases/assignmentphrase.h \
|
||||||
|
$$PWD/phrases/assignmentphraselist.h \
|
||||||
|
$$PWD/phrases/conditionalphrase.h \
|
||||||
|
$$PWD/phrases/fieldphrase.h \
|
||||||
|
$$PWD/phrases/phrasedata.h \
|
||||||
|
$$PWD/phrases/phrasedatalist.h \
|
||||||
|
$$PWD/phrases/phraselist.h \
|
||||||
|
$$PWD/phrases/datephrase.h \
|
||||||
|
$$PWD/table_p.h
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
$$PWD/generators/sqlgeneratorbase.cpp \
|
||||||
|
$$PWD/generators/postgresqlgenerator.cpp \
|
||||||
|
$$PWD/generators/mysqlgenerator.cpp \
|
||||||
|
$$PWD/generators/sqlitegenerator.cpp \
|
||||||
|
$$PWD/generators/sqlservergenerator.cpp \
|
||||||
|
$$PWD/types/dbgeography.cpp \
|
||||||
|
$$PWD/tableset.cpp \
|
||||||
|
$$PWD/query.cpp \
|
||||||
|
$$PWD/databasemodel.cpp \
|
||||||
|
$$PWD/tablesetbase.cpp \
|
||||||
|
$$PWD/changelogtable.cpp \
|
||||||
|
$$PWD/querybase.cpp \
|
||||||
|
$$PWD/tablemodel.cpp \
|
||||||
|
$$PWD/table.cpp \
|
||||||
|
$$PWD/database.cpp \
|
||||||
|
$$PWD/serializableobject.cpp \
|
||||||
|
$$PWD/sqlmodel.cpp \
|
||||||
|
$$PWD/phrase.cpp \
|
||||||
|
$$PWD/phrases/abstractfieldphrase.cpp \
|
||||||
|
$$PWD/phrases/assignmentphrase.cpp \
|
||||||
|
$$PWD/phrases/assignmentphraselist.cpp \
|
||||||
|
$$PWD/phrases/conditionalphrase.cpp \
|
||||||
|
$$PWD/phrases/fieldphrase.cpp \
|
||||||
|
$$PWD/phrases/phrasedata.cpp \
|
||||||
|
$$PWD/phrases/phrasedatalist.cpp \
|
||||||
|
$$PWD/phrases/phraselist.cpp \
|
||||||
|
$$PWD/phrases/datephrase.cpp
|
||||||
|
|
||||||
|
|
||||||
|
include($$PWD/../3rdparty/serializer/src/src.pri)
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
QT += sql gui
|
||||||
|
|
||||||
|
TARGET = nut
|
||||||
|
TEMPLATE = lib
|
||||||
|
CONFIG += c++11
|
||||||
|
CONFIG += staticlib
|
||||||
|
|
||||||
|
DEFINES += QT_DEPRECATED_WARNINGS NUT_COMPILE_STATIC
|
||||||
|
|
||||||
|
include($$PWD/src.pri)
|
||||||
|
include($$PWD/../ci-test-init.pri)
|
||||||
154
src/table.cpp
154
src/table.cpp
|
|
@ -20,10 +20,14 @@
|
||||||
|
|
||||||
#include <QMetaMethod>
|
#include <QMetaMethod>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
#include <QSqlQuery>
|
||||||
|
|
||||||
#include "table.h"
|
#include "table.h"
|
||||||
|
#include "table_p.h"
|
||||||
#include "database.h"
|
#include "database.h"
|
||||||
#include "databasemodel.h"
|
#include "databasemodel.h"
|
||||||
#include "generators/sqlgeneratorbase_p.h"
|
#include "generators/sqlgeneratorbase_p.h"
|
||||||
|
#include "tablesetbase_p.h"
|
||||||
|
|
||||||
NUT_BEGIN_NAMESPACE
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
|
@ -39,73 +43,100 @@ NUT_BEGIN_NAMESPACE
|
||||||
* This should be fixed to v1.2
|
* This should be fixed to v1.2
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Table::Table(QObject *parent) : QObject(parent), myModel(0), _parentTableSet(0)
|
Table::Table(QObject *parent) : QObject(parent),
|
||||||
|
d_ptr(new TablePrivate(this))
|
||||||
|
{ }
|
||||||
|
|
||||||
|
Table::~Table()
|
||||||
{
|
{
|
||||||
setStatus(NewCreated);
|
Q_D(Table);
|
||||||
|
|
||||||
|
if (d->parentTableSet)
|
||||||
|
d->parentTableSet->remove(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Table::add(TableSetBase *t)
|
void Table::add(TableSetBase *t)
|
||||||
{
|
{
|
||||||
this->childTableSets.insert(t);
|
Q_D(Table);
|
||||||
|
d->childTableSets.insert(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//QString Table::primaryKey() const
|
||||||
|
//{
|
||||||
|
// Q_D(const Table);
|
||||||
|
// return d->model->primaryKey();
|
||||||
|
//}
|
||||||
|
|
||||||
QString Table::primaryKey() const
|
//bool Table::isPrimaryKeyAutoIncrement() const
|
||||||
|
//{
|
||||||
|
// Q_D(const Table);
|
||||||
|
// FieldModel *pk = d->model->field(d->model->primaryKey());
|
||||||
|
// if (!pk)
|
||||||
|
// return false;
|
||||||
|
// return pk->isAutoIncrement;
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
//QVariant Table::primaryValue() const
|
||||||
|
//{
|
||||||
|
// return property(primaryKey().toLatin1().data());
|
||||||
|
//}
|
||||||
|
|
||||||
|
void Table::propertyChanged(const QString &propName)
|
||||||
{
|
{
|
||||||
return myModel->primaryKey();
|
Q_D(Table);
|
||||||
|
// if (!d->model)
|
||||||
|
// d->model = TableModel::findByClassName(metaObject()->className());
|
||||||
|
|
||||||
|
// if (!d->model)
|
||||||
|
// qFatal ("model for class '%s' not found", qPrintable(metaObject()->className()));
|
||||||
|
|
||||||
|
// foreach (FieldModel *f, d->model->fields())
|
||||||
|
// if(f->isPrimaryKey && propName == f->name && f->isAutoIncrement)
|
||||||
|
// return;
|
||||||
|
|
||||||
|
d->changedProperties.insert(propName);
|
||||||
|
if (d->status == FeatchedFromDB)
|
||||||
|
d->status = Modified;
|
||||||
|
|
||||||
|
if (d->status == NewCreated)
|
||||||
|
d->status = Added;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Table::isPrimaryKeyAutoIncrement() const
|
void Table::setModel(TableModel *model)
|
||||||
{
|
{
|
||||||
return myModel->field(myModel->primaryKey())->isAutoIncrement;
|
Q_D(Table);
|
||||||
}
|
d->model = model;
|
||||||
|
|
||||||
|
|
||||||
QVariant Table::primaryValue() const
|
|
||||||
{
|
|
||||||
return property(primaryKey().toLatin1().data());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Table::propertyChanged(QString propName)
|
|
||||||
{
|
|
||||||
if (!myModel)
|
|
||||||
myModel = TableModel::findByClassName(metaObject()->className());
|
|
||||||
|
|
||||||
if (!myModel)
|
|
||||||
qFatal ("model for this class not found");
|
|
||||||
|
|
||||||
foreach (FieldModel *f, myModel->fields())
|
|
||||||
if(f->isPrimaryKey && propName == f->name && f->isAutoIncrement)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_changedProperties.insert(propName);
|
|
||||||
if (_status == FeatchedFromDB)
|
|
||||||
_status = Modified;
|
|
||||||
|
|
||||||
if (_status == NewCreated)
|
|
||||||
_status = Added;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Table::clear()
|
void Table::clear()
|
||||||
{
|
{
|
||||||
_changedProperties.clear();
|
Q_D(Table);
|
||||||
|
d->changedProperties.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
QSet<QString> Table::changedProperties() const
|
QSet<QString> Table::changedProperties() const
|
||||||
{
|
{
|
||||||
return _changedProperties;
|
Q_D(const Table);
|
||||||
|
return d->changedProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Table::setParentTable(Table *master)
|
bool Table::setParentTable(Table *master, TableModel *masterModel, TableModel *model)
|
||||||
{
|
{
|
||||||
QString masterClassName = master->metaObject()->className();
|
Q_D(Table);
|
||||||
|
|
||||||
foreach (RelationModel *r, myModel->foregionKeys())
|
QString masterClassName = master->metaObject()->className();
|
||||||
|
d->refreshModel();
|
||||||
|
|
||||||
|
// if (!d->model)
|
||||||
|
// d->model = TableModel::findByClassName(metaObject()->className());
|
||||||
|
|
||||||
|
foreach (RelationModel *r, model->foregionKeys())
|
||||||
if(r->masterClassName == masterClassName)
|
if(r->masterClassName == masterClassName)
|
||||||
{
|
{
|
||||||
setProperty(QString(r->localColumn).toLatin1().data(),
|
setProperty(QString(r->localColumn).toLatin1().data(),
|
||||||
master->primaryValue());
|
master->property(masterModel->primaryKey().toUtf8().data()));
|
||||||
_changedProperties.insert(r->localColumn);
|
d->changedProperties.insert(r->localColumn);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -114,18 +145,23 @@ bool Table::setParentTable(Table *master)
|
||||||
|
|
||||||
TableSetBase *Table::parentTableSet() const
|
TableSetBase *Table::parentTableSet() const
|
||||||
{
|
{
|
||||||
return _parentTableSet;
|
Q_D(const Table);
|
||||||
|
return d->parentTableSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Table::setParentTableSet(TableSetBase *parent)
|
void Table::setParentTableSet(TableSetBase *parent)
|
||||||
{
|
{
|
||||||
_parentTableSet = parent;
|
Q_D(Table);
|
||||||
_parentTableSet->add(this);
|
d->parentTableSet = parent;
|
||||||
|
|
||||||
|
if (parent)
|
||||||
|
d->parentTableSet->add(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
TableSetBase *Table::childTableSet(const QString &name) const
|
TableSetBase *Table::childTableSet(const QString &name) const
|
||||||
{
|
{
|
||||||
foreach (TableSetBase *t, childTableSets)
|
Q_D(const Table);
|
||||||
|
foreach (TableSetBase *t, d->childTableSets)
|
||||||
if (t->childClassName() == name)
|
if (t->childClassName() == name)
|
||||||
return t;
|
return t;
|
||||||
return Q_NULLPTR;
|
return Q_NULLPTR;
|
||||||
|
|
@ -133,12 +169,15 @@ TableSetBase *Table::childTableSet(const QString &name) const
|
||||||
|
|
||||||
int Table::save(Database *db)
|
int Table::save(Database *db)
|
||||||
{
|
{
|
||||||
|
Q_D(Table);
|
||||||
|
|
||||||
QSqlQuery q = db->exec(db->sqlGenertor()->saveRecord(this, db->tableName(metaObject()->className())));
|
QSqlQuery q = db->exec(db->sqlGenertor()->saveRecord(this, db->tableName(metaObject()->className())));
|
||||||
|
|
||||||
if(status() == Added && isPrimaryKeyAutoIncrement())
|
auto model = db->model().tableByClassName(metaObject()->className());
|
||||||
setProperty(primaryKey().toLatin1().data(), q.lastInsertId());
|
if(status() == Added && model->isPrimaryKeyAutoIncrement())
|
||||||
|
setProperty(model->primaryKey().toLatin1().data(), q.lastInsertId());
|
||||||
|
|
||||||
foreach(TableSetBase *ts, childTableSets)
|
foreach(TableSetBase *ts, d->childTableSets)
|
||||||
ts->save(db);
|
ts->save(db);
|
||||||
setStatus(FeatchedFromDB);
|
setStatus(FeatchedFromDB);
|
||||||
|
|
||||||
|
|
@ -147,12 +186,29 @@ int Table::save(Database *db)
|
||||||
|
|
||||||
Table::Status Table::status() const
|
Table::Status Table::status() const
|
||||||
{
|
{
|
||||||
return _status;
|
Q_D(const Table);
|
||||||
|
return static_cast<Status>(d->status);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Table::setStatus(const Status &status)
|
void Table::setStatus(const Status &status)
|
||||||
{
|
{
|
||||||
_status = status;
|
Q_D(Table);
|
||||||
|
d->status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TablePrivate::TablePrivate(Table *parent) : q_ptr(parent),
|
||||||
|
model(nullptr), status(Table::NewCreated), parentTableSet(nullptr)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TablePrivate::refreshModel()
|
||||||
|
{
|
||||||
|
Q_Q(Table);
|
||||||
|
// if (!model)
|
||||||
|
// model = TableModel::findByClassName(q->metaObject()->className());
|
||||||
}
|
}
|
||||||
|
|
||||||
NUT_END_NAMESPACE
|
NUT_END_NAMESPACE
|
||||||
|
|
|
||||||
33
src/table.h
33
src/table.h
|
|
@ -34,12 +34,16 @@ NUT_BEGIN_NAMESPACE
|
||||||
class Database;
|
class Database;
|
||||||
class TableSetBase;
|
class TableSetBase;
|
||||||
class TableModel;
|
class TableModel;
|
||||||
|
class TablePrivate;
|
||||||
class NUT_EXPORT Table : public QObject
|
class NUT_EXPORT Table : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
TablePrivate *d_ptr;
|
||||||
|
Q_DECLARE_PRIVATE(Table)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Table(QObject *parentTableSet = nullptr);
|
explicit Table(QObject *parentTableSet = nullptr);
|
||||||
|
virtual ~Table();
|
||||||
|
|
||||||
enum Status{
|
enum Status{
|
||||||
NewCreated,
|
NewCreated,
|
||||||
|
|
@ -51,9 +55,15 @@ public:
|
||||||
|
|
||||||
int save(Database *db);
|
int save(Database *db);
|
||||||
|
|
||||||
QString primaryKey() const;
|
// Q_DECL_DEPRECATED
|
||||||
bool isPrimaryKeyAutoIncrement() const;
|
// QString primaryKey() const;
|
||||||
QVariant primaryValue() const;
|
|
||||||
|
// Q_DECL_DEPRECATED
|
||||||
|
// bool isPrimaryKeyAutoIncrement() const;
|
||||||
|
|
||||||
|
// Q_DECL_DEPRECATED
|
||||||
|
// QVariant primaryValue() const;
|
||||||
|
|
||||||
Status status() const;
|
Status status() const;
|
||||||
void setStatus(const Status &status);
|
void setStatus(const Status &status);
|
||||||
|
|
||||||
|
|
@ -64,28 +74,31 @@ public:
|
||||||
|
|
||||||
QSet<QString> changedProperties() const;
|
QSet<QString> changedProperties() const;
|
||||||
|
|
||||||
bool setParentTable(Table *master);
|
bool setParentTable(Table *master, TableModel *masterModel, TableModel *model);
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void propertyChanged(QString propName);
|
void propertyChanged(const QString &propName);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TableModel *myModel;
|
void setModel(TableModel *model);
|
||||||
Status _status;
|
// TableModel *myModel;
|
||||||
QSet<QString> _changedProperties;
|
// Status _status;
|
||||||
|
// QSet<QString> _changedProperties;
|
||||||
//TODO: is this removable?
|
//TODO: is this removable?
|
||||||
TableSetBase *_parentTableSet;
|
// TableSetBase *_parentTableSet;
|
||||||
|
|
||||||
QSet<TableSetBase*> childTableSets;
|
// QSet<TableSetBase*> childTableSets;
|
||||||
void clear();
|
void clear();
|
||||||
void add(TableSetBase *);
|
void add(TableSetBase *);
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
friend class Query;
|
friend class Query;
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
friend class TableSet;
|
||||||
friend class TableSetBase;
|
friend class TableSetBase;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef TABLEPRIVATE_H
|
||||||
|
#define TABLEPRIVATE_H
|
||||||
|
|
||||||
|
#include "defines.h"
|
||||||
|
|
||||||
|
#include <QtCore/QSet>
|
||||||
|
|
||||||
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class TableModel;
|
||||||
|
class Table;
|
||||||
|
class TableSetBase;
|
||||||
|
class TablePrivate {
|
||||||
|
Table *q_ptr;
|
||||||
|
Q_DECLARE_PUBLIC(Table)
|
||||||
|
|
||||||
|
public:
|
||||||
|
TablePrivate(Table *parent);
|
||||||
|
|
||||||
|
|
||||||
|
TableModel *model;
|
||||||
|
int status;
|
||||||
|
QSet<QString> changedProperties;
|
||||||
|
TableSetBase *parentTableSet;
|
||||||
|
QSet<TableSetBase*> childTableSets;
|
||||||
|
|
||||||
|
void refreshModel();
|
||||||
|
};
|
||||||
|
|
||||||
|
NUT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // TABLEPRIVATE_H
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**
|
**
|
||||||
** This file is part of Nut project.
|
** This file is part of Nut project.
|
||||||
** https://github.com/HamedMasafi/Nut
|
** https://github.com/HamedMasafi/Nut
|
||||||
|
|
@ -69,18 +69,18 @@ void TableModel::setTypeId(const int &typeId)
|
||||||
FieldModel *TableModel::field(int n) const
|
FieldModel *TableModel::field(int n) const
|
||||||
{
|
{
|
||||||
if (n < 0 || n >= _fields.count())
|
if (n < 0 || n >= _fields.count())
|
||||||
return 0;
|
return nullptr;
|
||||||
|
|
||||||
return _fields.at(n);
|
return _fields.at(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
FieldModel *TableModel::field(QString name) const
|
FieldModel *TableModel::field(const QString &name) const
|
||||||
{
|
{
|
||||||
foreach (FieldModel *f, _fields)
|
foreach (FieldModel *f, _fields)
|
||||||
if(f->name == name)
|
if(f->name == name)
|
||||||
return f;
|
return f;
|
||||||
|
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<FieldModel *> TableModel::fields() const
|
QList<FieldModel *> TableModel::fields() const
|
||||||
|
|
@ -101,37 +101,6 @@ QStringList TableModel::fieldsNames() const
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSet<TableModel *> TableModel::allModels()
|
|
||||||
{
|
|
||||||
return _allModels;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is not used anywhere
|
|
||||||
*/
|
|
||||||
TableModel *TableModel::findByTypeId(int typeId)
|
|
||||||
{
|
|
||||||
foreach (TableModel *model, _allModels)
|
|
||||||
if(model->typeId() == typeId)
|
|
||||||
return model;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief TableModel::findByClassName
|
|
||||||
* Find a table model by class name
|
|
||||||
* @param className
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
TableModel *TableModel::findByClassName(QString className)
|
|
||||||
{
|
|
||||||
foreach (TableModel *model, _allModels)
|
|
||||||
if(model->className() == className)
|
|
||||||
return model;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TableModel::operator ==(const TableModel &t) const{
|
bool TableModel::operator ==(const TableModel &t) const{
|
||||||
if(_name != t.name())
|
if(_name != t.name())
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -156,24 +125,7 @@ bool TableModel::operator !=(const TableModel &t) const
|
||||||
return !(*this == t);
|
return !(*this == t);
|
||||||
}
|
}
|
||||||
|
|
||||||
//bool TableModel::checkClassInfo(const QMetaClassInfo &classInfo,
|
TableModel::TableModel(int typeId, const QString &tableName)
|
||||||
// QString &type, QString &name, QString &value)
|
|
||||||
//{
|
|
||||||
// if (!QString(classInfo.name()).startsWith(__nut_NAME_PERFIX)) {
|
|
||||||
// return false;
|
|
||||||
// } else {
|
|
||||||
// QStringList parts = QString(classInfo.value()).split("\n");
|
|
||||||
// if (parts.count() != 3)
|
|
||||||
// return false;
|
|
||||||
|
|
||||||
// type = parts[0];
|
|
||||||
// name = parts[1];
|
|
||||||
// value = parts[2];
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
TableModel::TableModel(int typeId, QString tableName)
|
|
||||||
{
|
{
|
||||||
//TODO: check that
|
//TODO: check that
|
||||||
// if (findByTypeId(typeId))
|
// if (findByTypeId(typeId))
|
||||||
|
|
@ -202,7 +154,7 @@ TableModel::TableModel(int typeId, QString tableName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(type == __nut_FIELD){
|
if(type == __nut_FIELD){
|
||||||
FieldModel *f = new FieldModel;
|
auto *f = new FieldModel;
|
||||||
f->name = f->displayName = name;
|
f->name = f->displayName = name;
|
||||||
_fields.append(f);
|
_fields.append(f);
|
||||||
}
|
}
|
||||||
|
|
@ -217,7 +169,7 @@ TableModel::TableModel(int typeId, QString tableName)
|
||||||
f = fieldObj;
|
f = fieldObj;
|
||||||
if(!fieldObj)
|
if(!fieldObj)
|
||||||
continue;
|
continue;
|
||||||
fieldObj->type = fieldProperty.type();
|
fieldObj->type = static_cast<QMetaType::Type>(fieldProperty.type());
|
||||||
fieldObj->typeName = QString(fieldProperty.typeName());
|
fieldObj->typeName = QString(fieldProperty.typeName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -233,7 +185,7 @@ TableModel::TableModel(int typeId, QString tableName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(type == __nut_FOREGION_KEY){
|
if(type == __nut_FOREGION_KEY){
|
||||||
RelationModel *fk = new RelationModel;
|
auto *fk = new RelationModel;
|
||||||
fk->slaveTable = this;
|
fk->slaveTable = this;
|
||||||
fk->localColumn = name + "Id";
|
fk->localColumn = name + "Id";
|
||||||
fk->localProperty = name;
|
fk->localProperty = name;
|
||||||
|
|
@ -270,9 +222,6 @@ TableModel::TableModel(int typeId, QString tableName)
|
||||||
f->isAutoIncrement = true;
|
f->isAutoIncrement = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!findByTypeId(typeId) && !tableName.isNull())
|
|
||||||
_allModels.insert(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -291,7 +240,7 @@ TableModel::TableModel(int typeId, QString tableName)
|
||||||
"primary_key": "id"
|
"primary_key": "id"
|
||||||
},
|
},
|
||||||
*/
|
*/
|
||||||
TableModel::TableModel(QJsonObject json, QString tableName)
|
TableModel::TableModel(const QJsonObject &json, const QString &tableName) : _typeId(0)
|
||||||
{
|
{
|
||||||
_name = tableName;
|
_name = tableName;
|
||||||
|
|
||||||
|
|
@ -299,9 +248,11 @@ TableModel::TableModel(QJsonObject json, QString tableName)
|
||||||
QJsonObject relations = json.value(__FOREIGN_KEYS).toObject();
|
QJsonObject relations = json.value(__FOREIGN_KEYS).toObject();
|
||||||
foreach (QString key, fields.keys()) {
|
foreach (QString key, fields.keys()) {
|
||||||
QJsonObject fieldObject = fields.value(key).toObject();
|
QJsonObject fieldObject = fields.value(key).toObject();
|
||||||
FieldModel *f = new FieldModel;
|
//TODO: use FieldModel(QJsonObject) ctor
|
||||||
|
auto *f = new FieldModel;
|
||||||
f->name = fieldObject.value(__NAME).toString();
|
f->name = fieldObject.value(__NAME).toString();
|
||||||
f->type = QVariant::nameToType(fieldObject.value(__TYPE).toString().toLatin1().data());
|
f->type = static_cast<QMetaType::Type>(QMetaType::type(fieldObject.value(__TYPE).toString().toLatin1().data()));
|
||||||
|
f->typeName = QMetaType::typeName(f->type);
|
||||||
|
|
||||||
if(fieldObject.contains(__nut_NOT_NULL))
|
if(fieldObject.contains(__nut_NOT_NULL))
|
||||||
f->notNull = fieldObject.value(__nut_NOT_NULL).toBool();
|
f->notNull = fieldObject.value(__nut_NOT_NULL).toBool();
|
||||||
|
|
@ -377,7 +328,7 @@ RelationModel *TableModel::foregionKey(const QString &otherTable) const
|
||||||
if(fk->masterClassName == otherTable)
|
if(fk->masterClassName == otherTable)
|
||||||
return fk;
|
return fk;
|
||||||
|
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
RelationModel *TableModel::foregionKeyByField(const QString &fieldName) const
|
RelationModel *TableModel::foregionKeyByField(const QString &fieldName) const
|
||||||
|
|
@ -386,7 +337,7 @@ RelationModel *TableModel::foregionKeyByField(const QString &fieldName) const
|
||||||
if(fk->localColumn == fieldName)
|
if(fk->localColumn == fieldName)
|
||||||
return fk;
|
return fk;
|
||||||
|
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString TableModel::toString() const
|
QString TableModel::toString() const
|
||||||
|
|
@ -396,8 +347,7 @@ QString TableModel::toString() const
|
||||||
sl.append(f->name + " " + QVariant::typeToName(f->type));
|
sl.append(f->name + " " + QVariant::typeToName(f->type));
|
||||||
|
|
||||||
QString ret = QString("%1 (%2)")
|
QString ret = QString("%1 (%2)")
|
||||||
.arg(_name)
|
.arg(_name, sl.join(", "));
|
||||||
.arg(sl.join(", "));
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -409,10 +359,18 @@ QString TableModel::primaryKey() const
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TableModel::isPrimaryKeyAutoIncrement() const
|
||||||
|
{
|
||||||
|
FieldModel *pk = field(primaryKey());
|
||||||
|
if (!pk)
|
||||||
|
return false;
|
||||||
|
return pk->isAutoIncrement;
|
||||||
|
}
|
||||||
|
|
||||||
FieldModel::FieldModel(const QJsonObject &json)
|
FieldModel::FieldModel(const QJsonObject &json)
|
||||||
{
|
{
|
||||||
name = json.value(__NAME).toString();
|
name = json.value(__NAME).toString();
|
||||||
type = static_cast<QVariant::Type>(json.value(__TYPE).toInt());
|
type = static_cast<QMetaType::Type>(json.value(__TYPE).toInt());
|
||||||
length = json.value(__nut_LEN).toInt();
|
length = json.value(__nut_LEN).toInt();
|
||||||
notNull = json.value(__nut_NOT_NULL).toBool();
|
notNull = json.value(__nut_NOT_NULL).toBool();
|
||||||
isAutoIncrement = json.value(__nut_AUTO_INCREMENT).toBool();
|
isAutoIncrement = json.value(__nut_AUTO_INCREMENT).toBool();
|
||||||
|
|
@ -440,7 +398,7 @@ RelationModel::RelationModel(const QJsonObject &obj)
|
||||||
localProperty = obj.value("localProperty").toString();
|
localProperty = obj.value("localProperty").toString();
|
||||||
masterClassName = obj.value("masterClassName").toString();
|
masterClassName = obj.value("masterClassName").toString();
|
||||||
foreignColumn = obj.value("foreignColumn").toString();
|
foreignColumn = obj.value("foreignColumn").toString();
|
||||||
slaveTable = masterTable = 0;
|
slaveTable = masterTable = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject RelationModel::toJson() const
|
QJsonObject RelationModel::toJson() const
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,7 @@ struct FieldModel{
|
||||||
explicit FieldModel(const QJsonObject &json);
|
explicit FieldModel(const QJsonObject &json);
|
||||||
|
|
||||||
QString name;
|
QString name;
|
||||||
//TODO: QMetaType::Type??
|
QMetaType::Type type;
|
||||||
QVariant::Type type;
|
|
||||||
QString typeName;
|
QString typeName;
|
||||||
int length;
|
int length;
|
||||||
QString defaultValue;
|
QString defaultValue;
|
||||||
|
|
@ -70,8 +69,9 @@ struct FieldModel{
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RelationModel{
|
struct RelationModel{
|
||||||
RelationModel() : localColumn(QString()), localProperty(QString()), slaveTable(0),
|
RelationModel() : localColumn(QString()), localProperty(QString()),
|
||||||
foreignColumn(QString()), masterTable(0), masterClassName(QString())
|
slaveTable(nullptr), foreignColumn(QString()), masterTable(nullptr),
|
||||||
|
masterClassName(QString())
|
||||||
{}
|
{}
|
||||||
explicit RelationModel(const QJsonObject &obj);
|
explicit RelationModel(const QJsonObject &obj);
|
||||||
|
|
||||||
|
|
@ -87,29 +87,28 @@ struct RelationModel{
|
||||||
|
|
||||||
QJsonObject toJson() const;
|
QJsonObject toJson() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool operator ==(const RelationModel &l, const RelationModel &r);
|
bool operator ==(const RelationModel &l, const RelationModel &r);
|
||||||
bool operator !=(const RelationModel &l, const RelationModel &r);
|
bool operator !=(const RelationModel &l, const RelationModel &r);
|
||||||
class TableModel
|
|
||||||
|
class NUT_EXPORT TableModel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit TableModel(int typeId, QString tableName = QString());
|
explicit TableModel(int typeId, const QString &tableName = QString());
|
||||||
explicit TableModel(QJsonObject json, QString tableName);
|
explicit TableModel(const QJsonObject &json, const QString &tableName);
|
||||||
virtual ~TableModel();
|
virtual ~TableModel();
|
||||||
|
|
||||||
QJsonObject toJson() const;
|
QJsonObject toJson() const;
|
||||||
|
|
||||||
// static TableScheema *registerTable(int typeId, QString tableName);
|
|
||||||
// static void createForegionKeys();
|
|
||||||
// static TableModel* model(QString className);
|
|
||||||
|
|
||||||
FieldModel *field(int n) const;
|
FieldModel *field(int n) const;
|
||||||
FieldModel *field(QString name) const;
|
FieldModel *field(const QString &name) const;
|
||||||
RelationModel *foregionKey(const QString &otherTable) const;
|
RelationModel *foregionKey(const QString &otherTable) const;
|
||||||
RelationModel *foregionKeyByField(const QString &fieldName) const;
|
RelationModel *foregionKeyByField(const QString &fieldName) const;
|
||||||
|
|
||||||
QString toString() const;
|
QString toString() const;
|
||||||
|
|
||||||
QString primaryKey() const;
|
QString primaryKey() const;
|
||||||
|
bool isPrimaryKeyAutoIncrement() const;
|
||||||
|
|
||||||
QString name() const;
|
QString name() const;
|
||||||
void setName(const QString &name);
|
void setName(const QString &name);
|
||||||
|
|
@ -123,11 +122,6 @@ public:
|
||||||
QList<RelationModel *> foregionKeys() const;
|
QList<RelationModel *> foregionKeys() const;
|
||||||
QStringList fieldsNames() const;
|
QStringList fieldsNames() const;
|
||||||
|
|
||||||
static QSet<TableModel *> allModels();
|
|
||||||
static TableModel *findByTypeId(int typeId);
|
|
||||||
// static TableModel *findByName(QString name);
|
|
||||||
static TableModel *findByClassName(QString className);
|
|
||||||
|
|
||||||
bool operator ==(const TableModel &t) const;
|
bool operator ==(const TableModel &t) const;
|
||||||
bool operator !=(const TableModel &t) const;
|
bool operator !=(const TableModel &t) const;
|
||||||
|
|
||||||
|
|
@ -137,9 +131,9 @@ private:
|
||||||
int _typeId;
|
int _typeId;
|
||||||
QList<FieldModel*> _fields;
|
QList<FieldModel*> _fields;
|
||||||
QList<RelationModel*> _foreignKeys;
|
QList<RelationModel*> _foreignKeys;
|
||||||
|
|
||||||
|
Q_DECL_DEPRECATED
|
||||||
static QSet<TableModel*>_allModels;
|
static QSet<TableModel*>_allModels;
|
||||||
// bool checkClassInfo(const QMetaClassInfo &classInfo,
|
|
||||||
// QString &type, QString &name, QString &value);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
NUT_END_NAMESPACE
|
NUT_END_NAMESPACE
|
||||||
|
|
|
||||||
|
|
@ -29,102 +29,117 @@
|
||||||
|
|
||||||
#include "tablesetbase_p.h"
|
#include "tablesetbase_p.h"
|
||||||
#include "table.h"
|
#include "table.h"
|
||||||
|
#include "bulkinserter.h"
|
||||||
|
#include "databasemodel.h"
|
||||||
|
#include "tablesetbasedata.h"
|
||||||
|
|
||||||
NUT_BEGIN_NAMESPACE
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
class Query;
|
class Query;
|
||||||
|
|
||||||
|
class BulkInserter;
|
||||||
|
class Database;
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
class NUT_EXPORT TableSet : public TableSetBase
|
class NUT_EXPORT TableSet : public TableSetBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
typedef T value_type;
|
||||||
|
typedef T *pointer;
|
||||||
|
typedef T &reference;
|
||||||
|
|
||||||
explicit TableSet(Database *parent);
|
explicit TableSet(Database *parent);
|
||||||
explicit TableSet(Table *parent);
|
explicit TableSet(Table *parent);
|
||||||
|
|
||||||
void append(T *t);
|
void append(Row<T> t);
|
||||||
void append(QList<T *> t);
|
void append(RowList<T> t);
|
||||||
void remove(T *t);
|
void remove(T *t);
|
||||||
void remove(QList<T *> t);
|
void remove(QList<T *> t);
|
||||||
|
|
||||||
inline T *type() const {}
|
|
||||||
|
|
||||||
int length() const;
|
int length() const;
|
||||||
T *at(int i) const;
|
T *at(int i) const;
|
||||||
const T &operator[](int i) const;
|
const T &operator[](int i) const;
|
||||||
|
|
||||||
Query<T> *query();
|
Query<T> *query(bool autoDelete = true);
|
||||||
Query<T> *query(bool autoDelete);
|
BulkInserter *bulkInserter();
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
Q_OUTOFLINE_TEMPLATE TableSet<T>::TableSet(Database *parent) : TableSetBase(parent)
|
Q_OUTOFLINE_TEMPLATE TableSet<T>::TableSet(Database *parent) : TableSetBase(parent)
|
||||||
{
|
{
|
||||||
_childClassName = T::staticMetaObject.className();
|
data->childClassName = T::staticMetaObject.className();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
Q_OUTOFLINE_TEMPLATE TableSet<T>::TableSet(Table *parent) : TableSetBase(parent)
|
Q_OUTOFLINE_TEMPLATE TableSet<T>::TableSet(Table *parent) : TableSetBase(parent)
|
||||||
{
|
{
|
||||||
_childClassName = T::staticMetaObject.className();
|
data->childClassName = T::staticMetaObject.className();
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
Q_OUTOFLINE_TEMPLATE Query<T> *TableSet<T>::query()
|
|
||||||
{
|
|
||||||
Query<T> *q = new Query<T>(_database, this, true);
|
|
||||||
|
|
||||||
return q;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
Q_OUTOFLINE_TEMPLATE Query<T> *TableSet<T>::query(bool autoDelete)
|
Q_OUTOFLINE_TEMPLATE Query<T> *TableSet<T>::query(bool autoDelete)
|
||||||
{
|
{
|
||||||
Query<T> *q = new Query<T>(_database, this, autoDelete);
|
Query<T> *q = new Query<T>(data->database, this, autoDelete);
|
||||||
|
|
||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
Q_OUTOFLINE_TEMPLATE BulkInserter *TableSet<T>::bulkInserter()
|
||||||
|
{
|
||||||
|
BulkInserter *bi = new BulkInserter(data->database, data->childClassName);
|
||||||
|
return bi;
|
||||||
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
Q_OUTOFLINE_TEMPLATE int TableSet<T>::length() const
|
Q_OUTOFLINE_TEMPLATE int TableSet<T>::length() const
|
||||||
{
|
{
|
||||||
return _tables.count();
|
return data->tables.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
Q_OUTOFLINE_TEMPLATE T *TableSet<T >::at(int i) const
|
Q_OUTOFLINE_TEMPLATE T *TableSet<T >::at(int i) const
|
||||||
{
|
{
|
||||||
return (T*)_tablesList.at(i);
|
//TODO: check
|
||||||
|
return reinterpret_cast<T*>(data->childRows.at(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
Q_OUTOFLINE_TEMPLATE const T &TableSet<T>::operator[](int i) const
|
Q_OUTOFLINE_TEMPLATE const T &TableSet<T>::operator[](int i) const
|
||||||
{
|
{
|
||||||
return _tablesList[i];
|
return data->childRows[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
Q_OUTOFLINE_TEMPLATE void TableSet<T>::append(T *t)
|
Q_OUTOFLINE_TEMPLATE void TableSet<T>::append(Row<T> t)
|
||||||
{
|
{
|
||||||
_tables.insert(t);
|
data.detach();
|
||||||
_tablesList.append(t);
|
data->childs.append(t);
|
||||||
// rows.append(t);
|
data->tables.insert(t.data());
|
||||||
|
data->childRows.append(t.data());
|
||||||
|
|
||||||
|
// if (_database)
|
||||||
|
// t->setModel(_database->model().tableByClassName(t->metaObject()->className()));
|
||||||
|
|
||||||
t->setParentTableSet(this);
|
t->setParentTableSet(this);
|
||||||
if(t->status() != Table::FeatchedFromDB)
|
if(t->status() != Table::FeatchedFromDB)
|
||||||
t->setStatus(Table::Added);
|
t->setStatus(Table::Added);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
Q_OUTOFLINE_TEMPLATE void TableSet<T>::append(QList<T *> t)
|
Q_OUTOFLINE_TEMPLATE void TableSet<T>::append(RowList<T> t)
|
||||||
{
|
{
|
||||||
foreach (T* i, t)
|
foreach (Row<T> i, t)
|
||||||
append(i);
|
append(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
Q_OUTOFLINE_TEMPLATE void TableSet<T>::remove(T *t)
|
Q_OUTOFLINE_TEMPLATE void TableSet<T>::remove(T *t)
|
||||||
{
|
{
|
||||||
_tables.remove(t);
|
data.detach();
|
||||||
|
data->childs.removeOne(t);
|
||||||
|
data->tables.remove(t);
|
||||||
t->setStatus(Table::Deleted);
|
t->setStatus(Table::Deleted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,27 +22,40 @@
|
||||||
#include "database.h"
|
#include "database.h"
|
||||||
#include "tablesetbase_p.h"
|
#include "tablesetbase_p.h"
|
||||||
#include "databasemodel.h"
|
#include "databasemodel.h"
|
||||||
|
#include "tablesetbasedata.h"
|
||||||
|
|
||||||
NUT_BEGIN_NAMESPACE
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
TableSetBase::TableSetBase(Database *parent) : QObject(parent), _database(parent), _table(0),
|
TableSetBase::TableSetBase(Database *parent) : QObject(parent),
|
||||||
_tableName(QString())
|
data(new TableSetBaseData(parent))
|
||||||
{
|
{
|
||||||
parent->add(this);
|
parent->add(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
TableSetBase::TableSetBase(Table *parent) : QObject(parent), _database(0), _table(parent),
|
TableSetBase::TableSetBase(Table *parent) : QObject(parent),
|
||||||
_tableName(QString())
|
data(new TableSetBaseData(parent))
|
||||||
{
|
{
|
||||||
parent->add(this);
|
parent->add(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TableSetBase::~TableSetBase()
|
||||||
|
{
|
||||||
|
foreach (Table *t, data->tables)
|
||||||
|
t->setParentTableSet(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
int TableSetBase::save(Database *db, bool cleanUp)
|
int TableSetBase::save(Database *db, bool cleanUp)
|
||||||
{
|
{
|
||||||
int rowsAffected = 0;
|
int rowsAffected = 0;
|
||||||
foreach (Table *t, _tablesList) {
|
TableModel *masterModel = nullptr;
|
||||||
if(_table)
|
if (data->table)
|
||||||
t->setParentTable(_table);
|
masterModel = db->model().tableByClassName(data->table->metaObject()->className());
|
||||||
|
|
||||||
|
foreach (Table *t, data->childRows) {
|
||||||
|
if(data->table)
|
||||||
|
t->setParentTable(data->table,
|
||||||
|
masterModel,
|
||||||
|
db->model().tableByClassName(t->metaObject()->className()));
|
||||||
|
|
||||||
if(t->status() == Table::Added
|
if(t->status() == Table::Added
|
||||||
|| t->status() == Table::Modified
|
|| t->status() == Table::Modified
|
||||||
|
|
@ -55,39 +68,50 @@ int TableSetBase::save(Database *db, bool cleanUp)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cleanUp)
|
if (cleanUp)
|
||||||
_tablesList.clear();
|
data->childRows.clear();
|
||||||
|
|
||||||
return rowsAffected;
|
return rowsAffected;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TableSetBase::clearChilds()
|
void TableSetBase::clearChilds()
|
||||||
{
|
{
|
||||||
foreach (Table *t, _tablesList)
|
#ifndef NUT_SHARED_POINTER
|
||||||
|
foreach (Table *t, data->_childRows)
|
||||||
t->deleteLater();
|
t->deleteLater();
|
||||||
_tablesList.clear();
|
#endif
|
||||||
|
data->childRows.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TableSetBase::add(Table *t)
|
void TableSetBase::add(Table *t)
|
||||||
{
|
{
|
||||||
if(!_tables.contains(t)){
|
if(!data->tables.contains(get(t))){
|
||||||
_tables.insert(t);
|
data.detach();
|
||||||
_tablesList.append(t);
|
data->tables.insert(get(t));
|
||||||
|
data->childRows.append(get(t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TableSetBase::remove(Table *t)
|
||||||
|
{
|
||||||
|
data.detach();
|
||||||
|
data->tables.remove(get(t));
|
||||||
|
data->childRows.removeOne(get(t));
|
||||||
|
}
|
||||||
|
|
||||||
QString TableSetBase::childClassName() const
|
QString TableSetBase::childClassName() const
|
||||||
{
|
{
|
||||||
return _childClassName;
|
return data->childClassName;
|
||||||
}
|
}
|
||||||
|
|
||||||
Database *TableSetBase::database() const
|
Database *TableSetBase::database() const
|
||||||
{
|
{
|
||||||
return _database;
|
return data->database;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TableSetBase::setDatabase(Database *database)
|
void TableSetBase::setDatabase(Database *database)
|
||||||
{
|
{
|
||||||
_database = database;
|
data.detach();
|
||||||
|
data->database = database;
|
||||||
}
|
}
|
||||||
|
|
||||||
NUT_END_NAMESPACE
|
NUT_END_NAMESPACE
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
#include <QtCore/qglobal.h>
|
#include <QtCore/qglobal.h>
|
||||||
#include <QtCore/QSet>
|
#include <QtCore/QSet>
|
||||||
|
#include <QExplicitlySharedDataPointer>
|
||||||
|
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
|
|
||||||
|
|
@ -31,12 +32,14 @@ NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class Table;
|
class Table;
|
||||||
class Database;
|
class Database;
|
||||||
|
class TableSetBaseData;
|
||||||
class TableSetBase : public QObject
|
class TableSetBase : public QObject
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit TableSetBase(Database *parent);
|
explicit TableSetBase(Database *parent);
|
||||||
explicit TableSetBase(Table *parent);
|
explicit TableSetBase(Table *parent);
|
||||||
|
virtual ~TableSetBase();
|
||||||
|
|
||||||
virtual int save(Database *db, bool cleanUp = false);
|
virtual int save(Database *db, bool cleanUp = false);
|
||||||
void clearChilds();
|
void clearChilds();
|
||||||
|
|
@ -46,15 +49,17 @@ public:
|
||||||
void setDatabase(Database *database);
|
void setDatabase(Database *database);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QSet<Table*> _tables;
|
// QSet<Table*> _tables;
|
||||||
QList<Table*> _tablesList;
|
// RowList<Table> _childRows;
|
||||||
QString _tableName;
|
// Database *_database;
|
||||||
Database *_database;
|
// Table *_table;
|
||||||
Table *_table;
|
//// QString _tableName;
|
||||||
QString _childClassName;
|
// QString _childClassName;
|
||||||
|
QExplicitlySharedDataPointer<TableSetBaseData> data;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void add(Table* t);
|
void add(Table* t);
|
||||||
|
void remove(Table *t);
|
||||||
|
|
||||||
friend class Table;
|
friend class Table;
|
||||||
friend class QueryBase;
|
friend class QueryBase;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** 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 TABLESETBASEDATA_H
|
||||||
|
#define TABLESETBASEDATA_H
|
||||||
|
|
||||||
|
#include <QSharedData>
|
||||||
|
#include "defines.h"
|
||||||
|
|
||||||
|
NUT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class Table;
|
||||||
|
class Database;
|
||||||
|
class TableSetBaseData : public QSharedData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TableSetBaseData(Database *parent) :
|
||||||
|
database(parent), table(nullptr)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
TableSetBaseData(Table *parent) :
|
||||||
|
database(nullptr), table(parent)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
QSet<Table*> tables;
|
||||||
|
QList<Table*> childRows;
|
||||||
|
RowList<Table> childs;
|
||||||
|
|
||||||
|
Database *database;
|
||||||
|
Table *table;
|
||||||
|
QString childClassName;
|
||||||
|
};
|
||||||
|
|
||||||
|
NUT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // TABLESETBASEDATA_H
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
#include "tuple.h"
|
||||||
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef TUPLE_H
|
||||||
|
#define TUPLE_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
//class AbstractTuple
|
||||||
|
//{
|
||||||
|
// Q_GADGET
|
||||||
|
//};
|
||||||
|
|
||||||
|
//template <typename T>
|
||||||
|
//class Tuple
|
||||||
|
//{
|
||||||
|
//public:
|
||||||
|
// T _1;
|
||||||
|
//};
|
||||||
|
|
||||||
|
#endif // TUPLE_H
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
QT += qml quick testlib sql
|
|
||||||
|
|
||||||
QT -= gui
|
|
||||||
|
|
||||||
TARGET = tst_nut
|
|
||||||
CONFIG += warn_on qmltestcase c++11
|
|
||||||
INCLUDEPATH += $$PWD/../../src $$PWD/../common
|
|
||||||
include(../../nut.pri)
|
|
||||||
TEMPLATE = app
|
|
||||||
IMPORTPATH += $$OUT_PWD/../src/imports
|
|
||||||
SOURCES += \
|
|
||||||
maintest.cpp \
|
|
||||||
../common/comment.cpp \
|
|
||||||
../common/post.cpp \
|
|
||||||
../common/weblogdatabase.cpp
|
|
||||||
|
|
||||||
HEADERS += \
|
|
||||||
maintest.h \
|
|
||||||
../common/comment.h \
|
|
||||||
../common/post.h \
|
|
||||||
../common/weblogdatabase.h
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
#include <QtCore/qglobal.h>
|
#include <QtCore/qglobal.h>
|
||||||
#include <QtCore/QDateTime>
|
#include <QtCore/QDateTime>
|
||||||
#include <QtCore/QUuid>
|
|
||||||
#include "table.h"
|
#include "table.h"
|
||||||
|
|
||||||
#ifdef NUT_NAMESPACE
|
#ifdef NUT_NAMESPACE
|
||||||
|
|
@ -16,14 +15,14 @@ class Comment : public Table
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
NUT_PRIMARY_KEY(id)
|
NUT_PRIMARY_AUTO_INCREMENT(id)
|
||||||
NUT_DECLARE_FIELD(QUuid, id, id, setId)
|
NUT_DECLARE_FIELD(int, id, id, setId)
|
||||||
NUT_DECLARE_FIELD(QString, message, message, setMessage)
|
NUT_DECLARE_FIELD(QString, message, message, setMessage)
|
||||||
NUT_DECLARE_FIELD(QDateTime, saveDate, saveDate, setSaveDate)
|
NUT_DECLARE_FIELD(QDateTime, saveDate, saveDate, setSaveDate)
|
||||||
NUT_DECLARE_FIELD(qreal, point, point, setPoint)
|
NUT_DECLARE_FIELD(qreal, point, point, setPoint)
|
||||||
|
|
||||||
NUT_FOREGION_KEY(Post, int, post, post, setPost)
|
NUT_FOREGION_KEY(Post, int, post, post, setPost)
|
||||||
NUT_FOREGION_KEY(User, QUuid, author, author, setAuthor)
|
NUT_FOREGION_KEY(User, int, author, author, setAuthor)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Q_INVOKABLE explicit Comment(QObject *parentTableSet = nullptr);
|
Q_INVOKABLE explicit Comment(QObject *parentTableSet = nullptr);
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,21 @@
|
||||||
#ifndef CONSTS_H
|
#ifndef CONSTS_H
|
||||||
#define CONSTS_H
|
#define CONSTS_H
|
||||||
|
|
||||||
#define PRINT(x) qDebug() << #x "=" << x;
|
#include <qsystemdetection.h>
|
||||||
|
|
||||||
|
#define REGISTER(x) qDebug() << (#x) << "type id:" << qMetaTypeId<x*>()
|
||||||
|
#define PRINT(x)
|
||||||
|
//qDebug() << (#x "=") << (x);
|
||||||
#define TIC() QElapsedTimer timer; timer.start()
|
#define TIC() QElapsedTimer timer; timer.start()
|
||||||
#define TOC() qDebug() << QString("Elapsed time: %1ms for %2") \
|
#define TOC() qDebug() << QString("Elapsed time: %1ms for %2") \
|
||||||
.arg(timer.elapsed() / 1000.) \
|
.arg(timer.elapsed() / 1000.) \
|
||||||
.arg(__func__)
|
.arg(__func__)
|
||||||
|
|
||||||
//#define DRIVER "QPSQL"
|
|
||||||
//#define HOST "127.0.0.1"
|
|
||||||
//#define DATABASE "nutdb2"
|
|
||||||
//#define USERNAME "postgres"
|
|
||||||
//#define PASSWORD "856856"
|
|
||||||
|
|
||||||
#define DRIVER "QSQLITE"
|
#define DRIVER "QSQLITE"
|
||||||
|
#define DATABASE QString("nut_test_%1_db").arg(metaObject()->className()).toLower()
|
||||||
#define HOST "127.0.0.1"
|
#define HOST "127.0.0.1"
|
||||||
#define DATABASE "nutdb1"
|
#define USERNAME "postgres"
|
||||||
#define USERNAME "root"
|
#define PASSWORD "856856"
|
||||||
#define PASSWORD "onlyonlyi"
|
|
||||||
|
|
||||||
//#define DRIVER "QODBC"
|
|
||||||
//#define HOST "127.0.0.1"
|
|
||||||
//#define DATABASE "DRIVER={SQL Server};Server=.;Database=Nut2;Uid=sa;Port=1433;Pwd=qwe123!@#;WSID=."
|
|
||||||
//#define USERNAME "sa"
|
|
||||||
//#define PASSWORD "qwe123!@#"
|
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
# define OS "Linux"
|
# define OS "Linux"
|
||||||
|
|
@ -46,4 +38,5 @@
|
||||||
<< "\n\tTest:" << metaObject()->className() \
|
<< "\n\tTest:" << metaObject()->className() \
|
||||||
<< "\n****************************\n";
|
<< "\n****************************\n";
|
||||||
|
|
||||||
|
|
||||||
#endif // CONSTS_H
|
#endif // CONSTS_H
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
win32 {
|
||||||
|
CONFIG(debug,debug|release): LIBDIR = $$absolute_path($$OUT_PWD/../../src/debug)
|
||||||
|
CONFIG(release,debug|release): LIBDIR = $$absolute_path($$OUT_PWD/../../src/release)
|
||||||
|
} else {
|
||||||
|
LIBDIR = $$absolute_path($$OUT_PWD/../../src)
|
||||||
|
}
|
||||||
|
|
||||||
|
LIBS += -L$$LIBDIR -lnut
|
||||||
|
INCLUDEPATH += $$PWD/../../src $$PWD/../common
|
||||||
|
#include(../../src/src.pri)
|
||||||
|
|
||||||
|
DEFINES += NUT_SHARED_POINTER
|
||||||
|
|
@ -33,7 +33,7 @@ class Post : public Table
|
||||||
NUT_DECLARE_CHILD_TABLE(Score, scores)
|
NUT_DECLARE_CHILD_TABLE(Score, scores)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Q_INVOKABLE Post(QObject *parentTableSet = 0);
|
Q_INVOKABLE Post(QObject *parentTableSet = nullptr);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@ class User : public Nut::Table
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
NUT_PRIMARY_KEY(id)
|
NUT_PRIMARY_AUTO_INCREMENT(id)
|
||||||
NUT_DECLARE_FIELD(QUuid, id, id, setId)
|
NUT_DECLARE_FIELD(int, id, id, setId)
|
||||||
|
|
||||||
NUT_NOT_NULL(username)
|
NUT_NOT_NULL(username)
|
||||||
NUT_LEN(username, 50)
|
NUT_LEN(username, 50)
|
||||||
|
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
#include <QtTest>
|
|
||||||
#include <QDate>
|
|
||||||
|
|
||||||
#include "maintest.h"
|
|
||||||
#include "phrase.h"
|
|
||||||
|
|
||||||
using namespace Nut;
|
|
||||||
|
|
||||||
MainTest::MainTest(QObject *parent) : QObject(parent)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainTest::initTestCase()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainTest::no1()
|
|
||||||
{
|
|
||||||
FieldPhrase<int> id("main", "id");
|
|
||||||
FieldPhrase<QString> name("main", "name");
|
|
||||||
FieldPhrase<QString> last_name("main", "last_name");
|
|
||||||
FieldPhrase<QDate> date("main", "date");
|
|
||||||
auto w = (id == 4 && name == "hi");
|
|
||||||
}
|
|
||||||
|
|
||||||
QTEST_MAIN(MainTest)
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
#ifndef MAINTEST_H
|
|
||||||
#define MAINTEST_H
|
|
||||||
|
|
||||||
#include <QtCore/QObject>
|
|
||||||
#include <QtCore/qglobal.h>
|
|
||||||
|
|
||||||
class Post;
|
|
||||||
class User;
|
|
||||||
class MainTest : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit MainTest(QObject *parent = nullptr);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void initTestCase();
|
|
||||||
void no1();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // MAINTEST_H
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
QT += qml quick testlib sql
|
|
||||||
QT -= gui
|
|
||||||
|
|
||||||
TARGET = tst_phrases
|
|
||||||
TEMPLATE = app
|
|
||||||
|
|
||||||
CONFIG += warn_on qmltestcase c++11
|
|
||||||
INCLUDEPATH += $$PWD/../../src $$PWD/../common
|
|
||||||
include(../../nut.pri)
|
|
||||||
IMPORTPATH += $$OUT_PWD/../src/imports
|
|
||||||
SOURCES += \
|
|
||||||
maintest.cpp
|
|
||||||
|
|
||||||
HEADERS += \
|
|
||||||
maintest.h
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
#include <QtTest>
|
|
||||||
#include <QJsonDocument>
|
|
||||||
#include <QSqlError>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QElapsedTimer>
|
|
||||||
|
|
||||||
#include "consts.h"
|
|
||||||
|
|
||||||
#include "maintest.h"
|
|
||||||
#include "query.h"
|
|
||||||
#include "tableset.h"
|
|
||||||
#include "tablemodel.h"
|
|
||||||
|
|
||||||
#include "test.h"
|
|
||||||
|
|
||||||
MainTest::MainTest(QObject *parent) : QObject(parent)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainTest::initTestCase()
|
|
||||||
{
|
|
||||||
qDebug() << "Test type id:" << qRegisterMetaType<Test*>();
|
|
||||||
qDebug() << "DB type id:" << qRegisterMetaType<TestDatabase*>();
|
|
||||||
|
|
||||||
db.setDriver(DRIVER);
|
|
||||||
db.setHostName(HOST);
|
|
||||||
db.setDatabaseName("nut_tst_quuid");
|
|
||||||
db.setUserName(USERNAME);
|
|
||||||
db.setPassword(PASSWORD);
|
|
||||||
|
|
||||||
bool ok = db.open();
|
|
||||||
|
|
||||||
db.tests()->query()->remove();
|
|
||||||
|
|
||||||
QTEST_ASSERT(ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainTest::add()
|
|
||||||
{
|
|
||||||
TIC();
|
|
||||||
QUuid uuid = QUuid::createUuid();
|
|
||||||
Test t;
|
|
||||||
t.setId(uuid);
|
|
||||||
t.setUsername("test username");
|
|
||||||
db.tests()->append(&t);
|
|
||||||
db.saveChanges();
|
|
||||||
TOC();
|
|
||||||
|
|
||||||
Test *t2 = db.tests()->query()
|
|
||||||
->where(Test::idField() == uuid)
|
|
||||||
->first();
|
|
||||||
|
|
||||||
TOC();
|
|
||||||
QTEST_ASSERT(t2->id() == uuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainTest::cleanupTestCase()
|
|
||||||
{
|
|
||||||
qDeleteAll(Nut::TableModel::allModels());
|
|
||||||
// Nut::DatabaseModel::deleteAllModels();
|
|
||||||
}
|
|
||||||
|
|
||||||
QTEST_MAIN(MainTest)
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
QT += qml quick testlib sql
|
|
||||||
QT -= gui
|
|
||||||
|
|
||||||
TARGET = tst_nut
|
|
||||||
TEMPLATE = app
|
|
||||||
|
|
||||||
CONFIG += warn_on qmltestcase c++11
|
|
||||||
INCLUDEPATH += $$PWD/../../src $$PWD/../common
|
|
||||||
include(../../nut.pri)
|
|
||||||
IMPORTPATH += $$OUT_PWD/../src/imports
|
|
||||||
SOURCES += \
|
|
||||||
maintest.cpp \
|
|
||||||
testdatabase.cpp \
|
|
||||||
test.cpp
|
|
||||||
|
|
||||||
HEADERS += \
|
|
||||||
maintest.h \
|
|
||||||
../common/consts.h \
|
|
||||||
testdatabase.h \
|
|
||||||
test.h
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
TEMPLATE = subdirs
|
||||||
|
|
||||||
|
SUBDIRS += \
|
||||||
|
tst_basic \
|
||||||
|
tst_benckmark \
|
||||||
|
# tst_commands \
|
||||||
|
tst_datatypes \
|
||||||
|
#tst_join \
|
||||||
|
tst_phrases \
|
||||||
|
tst_quuid \
|
||||||
|
tst_generators \
|
||||||
|
tst_upgrades \
|
||||||
|
tst_json
|
||||||
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
#include "consts.h"
|
#include "consts.h"
|
||||||
|
|
||||||
#include "maintest.h"
|
#include "tst_basic.h"
|
||||||
#include "query.h"
|
#include "query.h"
|
||||||
#include "tableset.h"
|
#include "tableset.h"
|
||||||
#include "tablemodel.h"
|
#include "tablemodel.h"
|
||||||
|
|
@ -16,19 +16,11 @@
|
||||||
#include "comment.h"
|
#include "comment.h"
|
||||||
#include "score.h"
|
#include "score.h"
|
||||||
|
|
||||||
#define PRINT(x) qDebug() << #x "=" << x;
|
BasicTest::BasicTest(QObject *parent) : QObject(parent)
|
||||||
#define TIC() QElapsedTimer timer; timer.start()
|
|
||||||
#define TOC() qDebug() << QString("Elapsed time: %1ms for %2") \
|
|
||||||
.arg(timer.elapsed() / 1000.) \
|
|
||||||
.arg(__func__)
|
|
||||||
|
|
||||||
#define REGISTER(x) qDebug() << #x << "type id:" << qRegisterMetaType<x*>()
|
|
||||||
|
|
||||||
MainTest::MainTest(QObject *parent) : QObject(parent)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainTest::initTestCase()
|
void BasicTest::initTestCase()
|
||||||
{
|
{
|
||||||
//register all entities with Qt-MetaType mechanism
|
//register all entities with Qt-MetaType mechanism
|
||||||
REGISTER(User);
|
REGISTER(User);
|
||||||
|
|
@ -39,7 +31,7 @@ void MainTest::initTestCase()
|
||||||
|
|
||||||
db.setDriver(DRIVER);
|
db.setDriver(DRIVER);
|
||||||
db.setHostName(HOST);
|
db.setHostName(HOST);
|
||||||
db.setDatabaseName("nut_tst_basic");
|
db.setDatabaseName(DATABASE);
|
||||||
db.setUserName(USERNAME);
|
db.setUserName(USERNAME);
|
||||||
db.setPassword(PASSWORD);
|
db.setPassword(PASSWORD);
|
||||||
|
|
||||||
|
|
@ -52,7 +44,7 @@ void MainTest::initTestCase()
|
||||||
db.scores()->query()->remove();
|
db.scores()->query()->remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainTest::dataScheema()
|
void BasicTest::dataScheema()
|
||||||
{
|
{
|
||||||
// auto json = db.model().toJson();
|
// auto json = db.model().toJson();
|
||||||
// auto model = DatabaseModel::fromJson(json);
|
// auto model = DatabaseModel::fromJson(json);
|
||||||
|
|
@ -62,20 +54,19 @@ void MainTest::dataScheema()
|
||||||
// QTEST_ASSERT(model == db.model());
|
// QTEST_ASSERT(model == db.model());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainTest::createUser()
|
void BasicTest::createUser()
|
||||||
{
|
{
|
||||||
user = new User;
|
user = Nut::create<User>();
|
||||||
user->setId(QUuid::createUuid());
|
|
||||||
user->setUsername("admin");
|
user->setUsername("admin");
|
||||||
user->setPassword("123456");
|
user->setPassword("123456");
|
||||||
db.users()->append(user);
|
db.users()->append(user);
|
||||||
db.saveChanges();
|
db.saveChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainTest::createPost()
|
void BasicTest::createPost()
|
||||||
{
|
{
|
||||||
TIC();
|
TIC();
|
||||||
Post *newPost = new Post;
|
auto newPost = Nut::create<Post>();
|
||||||
newPost->setTitle("post title");
|
newPost->setTitle("post title");
|
||||||
newPost->setSaveDate(QDateTime::currentDateTime());
|
newPost->setSaveDate(QDateTime::currentDateTime());
|
||||||
newPost->setPublic(false);
|
newPost->setPublic(false);
|
||||||
|
|
@ -83,15 +74,14 @@ void MainTest::createPost()
|
||||||
db.posts()->append(newPost);
|
db.posts()->append(newPost);
|
||||||
|
|
||||||
for(int i = 0 ; i < 3; i++){
|
for(int i = 0 ; i < 3; i++){
|
||||||
Comment *comment = new Comment;
|
auto comment = Nut::create<Comment>();
|
||||||
comment->setId(QUuid::createUuid());
|
|
||||||
comment->setMessage("comment #" + QString::number(i));
|
comment->setMessage("comment #" + QString::number(i));
|
||||||
comment->setSaveDate(QDateTime::currentDateTime());
|
comment->setSaveDate(QDateTime::currentDateTime());
|
||||||
comment->setAuthorId(user->id());
|
comment->setAuthorId(user->id());
|
||||||
newPost->comments()->append(comment);
|
db.comments()->append(comment);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < 10; ++i) {
|
for (int i = 0; i < 10; ++i) {
|
||||||
Score *score = new Score;
|
auto score = Nut::create<Score>();
|
||||||
score->setScore(i % 5);
|
score->setScore(i % 5);
|
||||||
newPost->scores()->append(score);
|
newPost->scores()->append(score);
|
||||||
}
|
}
|
||||||
|
|
@ -105,19 +95,18 @@ void MainTest::createPost()
|
||||||
qDebug() << "New post inserted with id:" << newPost->id();
|
qDebug() << "New post inserted with id:" << newPost->id();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainTest::createPost2()
|
void BasicTest::createPost2()
|
||||||
{
|
{
|
||||||
//create post on the fly
|
//create post on the fly
|
||||||
QVariant postIdVar = db.posts()->query()->insert(
|
QVariant postIdVar = db.posts()->query()->insert(
|
||||||
(Post::titleField() = "This is a sample")
|
(Post::titleField() = "This is a sample")
|
||||||
& (Post::isPublicField() = true));
|
& (Post::isPublicField() = true));
|
||||||
|
|
||||||
QTEST_ASSERT(postIdVar.type() == QVariant::LongLong);
|
QTEST_ASSERT(postIdVar.type() == QVariant::LongLong || postIdVar.type() == QVariant::ULongLong);
|
||||||
int postId = postIdVar.toInt();
|
int postId = postIdVar.toInt();
|
||||||
|
|
||||||
for(int i = 0 ; i < 3; i++){
|
for(int i = 0 ; i < 3; i++){
|
||||||
Comment *comment = new Comment;
|
auto comment = Nut::create<Comment>();
|
||||||
comment->setId(QUuid::createUuid());
|
|
||||||
comment->setMessage("comment #" + QString::number(i + 2));
|
comment->setMessage("comment #" + QString::number(i + 2));
|
||||||
comment->setSaveDate(QDateTime::currentDateTime());
|
comment->setSaveDate(QDateTime::currentDateTime());
|
||||||
comment->setAuthor(user);
|
comment->setAuthor(user);
|
||||||
|
|
@ -130,7 +119,7 @@ void MainTest::createPost2()
|
||||||
QTEST_ASSERT(postId != 0);
|
QTEST_ASSERT(postId != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainTest::updatePostOnTheFly()
|
void BasicTest::updatePostOnTheFly()
|
||||||
{
|
{
|
||||||
auto c = db.posts()->query()
|
auto c = db.posts()->query()
|
||||||
->where(Post::idField() == postId)
|
->where(Post::idField() == postId)
|
||||||
|
|
@ -139,7 +128,7 @@ void MainTest::updatePostOnTheFly()
|
||||||
QTEST_ASSERT(c == 1);
|
QTEST_ASSERT(c == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainTest::selectPublicts()
|
void BasicTest::selectPublicts()
|
||||||
{
|
{
|
||||||
auto q = db.posts()->query()
|
auto q = db.posts()->query()
|
||||||
->where(Post::isPublicField())
|
->where(Post::isPublicField())
|
||||||
|
|
@ -153,7 +142,7 @@ void MainTest::selectPublicts()
|
||||||
QTEST_ASSERT(q2 == 1);
|
QTEST_ASSERT(q2 == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainTest::selectPosts()
|
void BasicTest::selectPosts()
|
||||||
{
|
{
|
||||||
auto q = db.posts()->query()
|
auto q = db.posts()->query()
|
||||||
->join<Comment>()
|
->join<Comment>()
|
||||||
|
|
@ -177,7 +166,7 @@ void MainTest::selectPosts()
|
||||||
db.cleanUp();
|
db.cleanUp();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainTest::selectScoreAverage()
|
void BasicTest::selectScoreAverage()
|
||||||
{
|
{
|
||||||
auto a = db.scores()->query()
|
auto a = db.scores()->query()
|
||||||
->join<Post>()
|
->join<Post>()
|
||||||
|
|
@ -186,7 +175,7 @@ void MainTest::selectScoreAverage()
|
||||||
qDebug() << a;
|
qDebug() << a;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainTest::selectFirst()
|
void BasicTest::selectFirst()
|
||||||
{
|
{
|
||||||
auto posts = db.posts()->query()
|
auto posts = db.posts()->query()
|
||||||
->first();
|
->first();
|
||||||
|
|
@ -194,7 +183,7 @@ void MainTest::selectFirst()
|
||||||
QTEST_ASSERT(posts != Q_NULLPTR);
|
QTEST_ASSERT(posts != Q_NULLPTR);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainTest::selectPostsWithoutTitle()
|
void BasicTest::selectPostsWithoutTitle()
|
||||||
{
|
{
|
||||||
auto q = db.posts()->query();
|
auto q = db.posts()->query();
|
||||||
q->setWhere(Post::titleField().isNull());
|
q->setWhere(Post::titleField().isNull());
|
||||||
|
|
@ -202,7 +191,7 @@ void MainTest::selectPostsWithoutTitle()
|
||||||
QTEST_ASSERT(count == 0);
|
QTEST_ASSERT(count == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainTest::selectPostIds()
|
void BasicTest::selectPostIds()
|
||||||
{
|
{
|
||||||
auto q = db.posts()->query();
|
auto q = db.posts()->query();
|
||||||
auto ids = q->select(Post::idField());
|
auto ids = q->select(Post::idField());
|
||||||
|
|
@ -210,13 +199,13 @@ qDebug() << ids.count();
|
||||||
QTEST_ASSERT(ids.count() == 2);
|
QTEST_ASSERT(ids.count() == 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainTest::testDate()
|
void BasicTest::testDate()
|
||||||
{
|
{
|
||||||
QDateTime d = QDateTime::currentDateTime();
|
QDateTime d = QDateTime::currentDateTime();
|
||||||
QTime t = QTime(d.time().hour(), d.time().minute(), d.time().second());
|
QTime t = QTime(d.time().hour(), d.time().minute(), d.time().second());
|
||||||
d.setTime(t);
|
d.setTime(t);
|
||||||
|
|
||||||
Post *newPost = new Post;
|
auto newPost = Nut::create<Post>();
|
||||||
newPost->setTitle("post title");
|
newPost->setTitle("post title");
|
||||||
newPost->setSaveDate(d);
|
newPost->setSaveDate(d);
|
||||||
|
|
||||||
|
|
@ -228,38 +217,39 @@ void MainTest::testDate()
|
||||||
->setWhere(Post::idField() == newPost->id())
|
->setWhere(Post::idField() == newPost->id())
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
|
qDebug() << q->saveDate() << d;
|
||||||
QTEST_ASSERT(q->saveDate() == d);
|
QTEST_ASSERT(q->saveDate() == d);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainTest::join()
|
void BasicTest::join()
|
||||||
{
|
{
|
||||||
TIC();
|
// TIC();
|
||||||
auto q = db.comments()->query()
|
// auto q = db.comments()->query()
|
||||||
->join<User>()
|
// ->join<User>()
|
||||||
->join<Post>();
|
// ->join<Post>();
|
||||||
|
|
||||||
auto comments = q->toList();
|
// auto comments = q->toList();
|
||||||
|
|
||||||
TOC();
|
// TOC();
|
||||||
QTEST_ASSERT(comments.length());
|
// QTEST_ASSERT(comments.length());
|
||||||
QTEST_ASSERT(comments[0]->author());
|
// QTEST_ASSERT(comments[0]->author());
|
||||||
QTEST_ASSERT(comments[0]->author()->username() == "admin");
|
// QTEST_ASSERT(comments[0]->author()->username() == "admin");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MainTest::selectWithInvalidRelation()
|
void BasicTest::selectWithInvalidRelation()
|
||||||
{
|
{
|
||||||
auto q = db.posts()->query();
|
auto q = db.posts()->query();
|
||||||
q->join("Invalid_Class_Name");
|
q->join("Invalid_Class_Name");
|
||||||
q->toList();
|
q->toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainTest::modifyPost()
|
void BasicTest::modifyPost()
|
||||||
{
|
{
|
||||||
auto q = db.posts()->query();
|
auto q = db.posts()->query();
|
||||||
q->setWhere(Post::idField() == postId);
|
q->setWhere(Post::idField() == postId);
|
||||||
|
|
||||||
Post *post = q->first();
|
Nut::Row<Post> post = q->first();
|
||||||
|
|
||||||
QTEST_ASSERT(post != nullptr);
|
QTEST_ASSERT(post != nullptr);
|
||||||
|
|
||||||
|
|
@ -274,7 +264,7 @@ void MainTest::modifyPost()
|
||||||
QTEST_ASSERT(post->title() == "new name");
|
QTEST_ASSERT(post->title() == "new name");
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainTest::emptyDatabase()
|
void BasicTest::emptyDatabase()
|
||||||
{
|
{
|
||||||
// auto commentsCount = db.comments()->query()->remove();
|
// auto commentsCount = db.comments()->query()->remove();
|
||||||
// auto postsCount = db.posts()->query()->remove();
|
// auto postsCount = db.posts()->query()->remove();
|
||||||
|
|
@ -282,15 +272,18 @@ void MainTest::emptyDatabase()
|
||||||
// QTEST_ASSERT(commentsCount == 6);
|
// QTEST_ASSERT(commentsCount == 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainTest::cleanupTestCase()
|
void BasicTest::cleanupTestCase()
|
||||||
{
|
{
|
||||||
post->deleteLater();
|
// post->deleteLater();
|
||||||
user->deleteLater();
|
// user->deleteLater();
|
||||||
|
|
||||||
//release models before exiting
|
//release models before exiting
|
||||||
qDeleteAll(TableModel::allModels());
|
// qDeleteAll(TableModel::allModels());
|
||||||
|
|
||||||
|
// if (QFile::remove("nut_tst_basic"))
|
||||||
|
// qDebug() << "database removed";
|
||||||
|
|
||||||
PRINT_FORM(db);
|
PRINT_FORM(db);
|
||||||
}
|
}
|
||||||
|
|
||||||
QTEST_MAIN(MainTest)
|
QTEST_MAIN(BasicTest)
|
||||||
|
|
@ -7,16 +7,16 @@
|
||||||
#include "weblogdatabase.h"
|
#include "weblogdatabase.h"
|
||||||
class Post;
|
class Post;
|
||||||
class User;
|
class User;
|
||||||
class MainTest : public QObject
|
class BasicTest : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
WeblogDatabase db;
|
WeblogDatabase db;
|
||||||
int postId;
|
int postId;
|
||||||
Post *post;
|
Nut::Row<Post> post;
|
||||||
User *user;
|
Nut::Row<User> user;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit MainTest(QObject *parent = nullptr);
|
explicit BasicTest(QObject *parent = nullptr);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
QT += testlib sql
|
||||||
|
|
||||||
|
TARGET = tst_basic
|
||||||
|
TEMPLATE = app
|
||||||
|
|
||||||
|
CONFIG += warn_on c++11
|
||||||
|
|
||||||
|
include(../common/nut-lib.pri)
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
../common/comment.cpp \
|
||||||
|
../common/post.cpp \
|
||||||
|
../common/user.cpp \
|
||||||
|
../common/weblogdatabase.cpp \
|
||||||
|
../common/score.cpp \
|
||||||
|
tst_basic.cpp
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
../common/consts.h \
|
||||||
|
../common/comment.h \
|
||||||
|
../common/post.h \
|
||||||
|
../common/user.h \
|
||||||
|
../common/weblogdatabase.h \
|
||||||
|
../common/score.h \
|
||||||
|
tst_basic.h
|
||||||
|
|
||||||
|
include($$PWD/../../ci-test-init.pri)
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#include "weblogdatabase.h"
|
#include "weblogdatabase.h"
|
||||||
class Post;
|
class Post;
|
||||||
class MainTest : public QObject
|
class BenchmarkTest : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
WeblogDatabase db;
|
WeblogDatabase db;
|
||||||
|
|
@ -14,7 +14,7 @@ class MainTest : public QObject
|
||||||
Post *post;
|
Post *post;
|
||||||
Query<Post> *q;
|
Query<Post> *q;
|
||||||
public:
|
public:
|
||||||
explicit MainTest(QObject *parent = nullptr);
|
explicit BenchmarkTest(QObject *parent = nullptr);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
|
|
@ -10,23 +10,27 @@
|
||||||
#include "tablemodel.h"
|
#include "tablemodel.h"
|
||||||
#include "databasemodel.h"
|
#include "databasemodel.h"
|
||||||
|
|
||||||
|
#include "user.h"
|
||||||
#include "post.h"
|
#include "post.h"
|
||||||
#include "comment.h"
|
#include "comment.h"
|
||||||
|
#include "score.h"
|
||||||
|
|
||||||
MainTest::MainTest(QObject *parent) : QObject(parent)
|
BenchmarkTest::BenchmarkTest(QObject *parent) : QObject(parent)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainTest::initTestCase()
|
void BenchmarkTest::initTestCase()
|
||||||
{
|
{
|
||||||
qDebug() << "User type id:" << qRegisterMetaType<Post*>();
|
REGISTER(User);
|
||||||
qDebug() << "Comment type id:" << qRegisterMetaType<Comment*>();
|
REGISTER(Post);
|
||||||
qDebug() << "DB type id:" << qRegisterMetaType<WeblogDatabase*>();
|
REGISTER(Score);
|
||||||
|
REGISTER(Comment);
|
||||||
|
REGISTER(WeblogDatabase);
|
||||||
|
|
||||||
db.setDriver(DRIVER);
|
db.setDriver(DRIVER);
|
||||||
db.setHostName(HOST);
|
db.setHostName(HOST);
|
||||||
db.setDatabaseName(DATABASE);
|
db.setDatabaseName("tst_benchmark_db");
|
||||||
db.setUserName(USERNAME);
|
db.setUserName(USERNAME);
|
||||||
db.setPassword(PASSWORD);
|
db.setPassword(PASSWORD);
|
||||||
|
|
||||||
|
|
@ -35,21 +39,21 @@ void MainTest::initTestCase()
|
||||||
QTEST_ASSERT(ok);
|
QTEST_ASSERT(ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainTest::insert1kPost()
|
void BenchmarkTest::insert1kPost()
|
||||||
{
|
{
|
||||||
QTime t;
|
QTime t;
|
||||||
t.start();
|
t.start();
|
||||||
|
|
||||||
for (int i = 0; i < 1000; ++i) {
|
for (int i = 0; i < 100; ++i) {
|
||||||
Post *newPost = new Post;
|
auto newPost = Nut::create<Post>();
|
||||||
newPost->setTitle("post title");
|
newPost->setTitle("post title");
|
||||||
newPost->setSaveDate(QDateTime::currentDateTime());
|
newPost->setSaveDate(QDateTime::currentDateTime());
|
||||||
|
|
||||||
db.posts()->append(newPost);
|
db.posts()->append(newPost);
|
||||||
}
|
}
|
||||||
db.saveChanges();
|
db.saveChanges();
|
||||||
|
|
||||||
qDebug("1k post inserted in %d ms", t.elapsed());
|
qDebug("1k post inserted in %d ms", t.elapsed());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QTEST_MAIN(MainTest)
|
QTEST_MAIN(BenchmarkTest)
|
||||||
|
|
@ -1,20 +1,19 @@
|
||||||
QT += qml quick testlib sql
|
QT += testlib sql
|
||||||
QT -= gui
|
|
||||||
|
|
||||||
TARGET = tst_nut
|
TARGET = tst_benchmark
|
||||||
TEMPLATE = app
|
TEMPLATE = app
|
||||||
|
|
||||||
CONFIG += warn_on qmltestcase c++11
|
CONFIG += warn_on c++11
|
||||||
INCLUDEPATH += $$PWD/../../src $$PWD/../common
|
|
||||||
include(../../nut.pri)
|
include(../common/nut-lib.pri)
|
||||||
IMPORTPATH += $$OUT_PWD/../src/imports
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
maintest.cpp \
|
|
||||||
../common/comment.cpp \
|
../common/comment.cpp \
|
||||||
../common/post.cpp \
|
../common/post.cpp \
|
||||||
../common/user.cpp \
|
../common/user.cpp \
|
||||||
../common/weblogdatabase.cpp \
|
../common/weblogdatabase.cpp \
|
||||||
../common/score.cpp
|
../common/score.cpp \
|
||||||
|
tst_benchmark.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
maintest.h \
|
maintest.h \
|
||||||
|
|
@ -24,3 +23,5 @@ HEADERS += \
|
||||||
../common/user.h \
|
../common/user.h \
|
||||||
../common/weblogdatabase.h \
|
../common/weblogdatabase.h \
|
||||||
../common/score.h
|
../common/score.h
|
||||||
|
|
||||||
|
include($$PWD/../../ci-test-init.pri)
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
#include "consts.h"
|
#include "consts.h"
|
||||||
|
|
||||||
#include "maintest.h"
|
#include "tst_commands.h"
|
||||||
#include "query.h"
|
#include "query.h"
|
||||||
#include "tableset.h"
|
#include "tableset.h"
|
||||||
#include "tablemodel.h"
|
#include "tablemodel.h"
|
||||||
|
|
@ -12,17 +12,19 @@
|
||||||
|
|
||||||
#include "post.h"
|
#include "post.h"
|
||||||
#include "comment.h"
|
#include "comment.h"
|
||||||
|
#include "user.h"
|
||||||
|
#include "score.h"
|
||||||
|
|
||||||
MainTest::MainTest(QObject *parent) : QObject(parent)
|
CommandsTest::CommandsTest(QObject *parent) : QObject(parent)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainTest::initTestCase()
|
void CommandsTest::initTestCase()
|
||||||
{
|
{
|
||||||
qDebug() << "User type id:" << qRegisterMetaType<Post*>();
|
REGISTER(Post);
|
||||||
qDebug() << "Comment type id:" << qRegisterMetaType<Comment*>();
|
REGISTER(Comment);
|
||||||
qDebug() << "DB type id:" << qRegisterMetaType<WeblogDatabase*>();
|
REGISTER(WeblogDatabase);
|
||||||
|
|
||||||
db.setDriver(DRIVER);
|
db.setDriver(DRIVER);
|
||||||
db.setHostName(HOST);
|
db.setHostName(HOST);
|
||||||
|
|
@ -35,7 +37,7 @@ void MainTest::initTestCase()
|
||||||
QTEST_ASSERT(ok);
|
QTEST_ASSERT(ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainTest::cmd1()
|
void CommandsTest::cmd1()
|
||||||
{
|
{
|
||||||
Query<Post> *q = db.posts()->query()
|
Query<Post> *q = db.posts()->query()
|
||||||
->setWhere(Post::titleField() == "test" && Post::idField() < 4 + 5);
|
->setWhere(Post::titleField() == "test" && Post::idField() < 4 + 5);
|
||||||
|
|
@ -45,7 +47,7 @@ void MainTest::cmd1()
|
||||||
qDebug() << q->sqlCommand();
|
qDebug() << q->sqlCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainTest::cmd2()
|
void CommandsTest::cmd2()
|
||||||
{
|
{
|
||||||
Query<Post> *q = db.posts()->query()
|
Query<Post> *q = db.posts()->query()
|
||||||
->setWhere(!Post::idField().in({1, 2, 3, 4}));
|
->setWhere(!Post::idField().in({1, 2, 3, 4}));
|
||||||
|
|
@ -56,7 +58,7 @@ void MainTest::cmd2()
|
||||||
qDebug() << q->sqlCommand();
|
qDebug() << q->sqlCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainTest::join()
|
void CommandsTest::join()
|
||||||
{
|
{
|
||||||
auto q = db.posts()->query()
|
auto q = db.posts()->query()
|
||||||
->join<User>()
|
->join<User>()
|
||||||
|
|
@ -64,4 +66,4 @@ void MainTest::join()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QTEST_MAIN(MainTest)
|
QTEST_MAIN(CommandsTest)
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#include "weblogdatabase.h"
|
#include "weblogdatabase.h"
|
||||||
class Post;
|
class Post;
|
||||||
class MainTest : public QObject
|
class CommandsTest : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
WeblogDatabase db;
|
WeblogDatabase db;
|
||||||
|
|
@ -14,7 +14,7 @@ class MainTest : public QObject
|
||||||
Post *post;
|
Post *post;
|
||||||
Query<Post> *q;
|
Query<Post> *q;
|
||||||
public:
|
public:
|
||||||
explicit MainTest(QObject *parent = nullptr);
|
explicit CommandsTest(QObject *parent = nullptr);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue