parent
8fa6a3b6d7
commit
ad6eab9de1
|
|
@ -0,0 +1 @@
|
|||
set(QT_REPO_MODULE_VERSION "0.7.0")
|
||||
|
|
@ -1,90 +1,158 @@
|
|||
name: CI build
|
||||
name: CI Build
|
||||
|
||||
on: [push]
|
||||
on:
|
||||
push:
|
||||
branches-ignore:
|
||||
- "releases/**"
|
||||
paths-ignore:
|
||||
- "**.md"
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- "**.md"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version:
|
||||
- 5.15.0
|
||||
|
||||
platform:
|
||||
- gcc_64
|
||||
- android
|
||||
- msvc2019
|
||||
- msvc2019_64
|
||||
- winrt_x64_msvc2019
|
||||
- winrt_x86_msvc2019
|
||||
- winrt_armv7_msvc2019
|
||||
- mingw81_64
|
||||
- mingw81_32
|
||||
- clang_64
|
||||
- ios
|
||||
|
||||
qt_version: [5.12.11, 5.15.2, 6.2.0]
|
||||
platform: [ubuntu-20.04, windows-latest, macos-latest]
|
||||
include:
|
||||
- platform: gcc_64
|
||||
os: ubuntu-latest
|
||||
- platform: android
|
||||
os: ubuntu-latest
|
||||
- platform: msvc2019_64
|
||||
os: windows-latest
|
||||
- platform: msvc2019
|
||||
os: windows-latest
|
||||
- platform: winrt_x64_msvc2019
|
||||
os: windows-latest
|
||||
- platform: winrt_x86_msvc2019
|
||||
os: windows-latest
|
||||
- platform: winrt_armv7_msvc2019
|
||||
os: windows-latest
|
||||
- platform: mingw81_64
|
||||
os: windows-latest
|
||||
- platform: mingw81_32
|
||||
os: windows-latest
|
||||
- platform: clang_64
|
||||
os: macos-latest
|
||||
- qt_version: 6.2.0
|
||||
additional_arguments: -D QT_DEFAULT_MAJOR_VERSION=6
|
||||
build_cmake: true
|
||||
- platform: ubuntu-20.04
|
||||
make: make
|
||||
#CXXFLAGS: -Wall -Wextra
|
||||
MAKEFLAGS: -j2
|
||||
- platform: macos-latest
|
||||
make: make
|
||||
#CXXFLAGS: -Wall -Wextra
|
||||
MAKEFLAGS: -j3
|
||||
- platform: windows-latest
|
||||
make: nmake
|
||||
QMAKE_MSC_VER: 16.11.31911.196
|
||||
cmake_params: -D CMAKE_CXX_FLAGS_DEBUG="/g"
|
||||
- platform: ubuntu-20.04
|
||||
tests: [sqlite, posgtresql]
|
||||
- platform: ubuntu-20.04
|
||||
qt_version: system
|
||||
tests: [sqlite, posgtresql, mysql]
|
||||
make: make
|
||||
name: ubuntu-20.04, system
|
||||
- platform: windows-latest
|
||||
qt_version: 5.15.2
|
||||
tests: [mssql]
|
||||
|
||||
runs-on: ${{ matrix.platform }}
|
||||
name: ${{ matrix.platform }} - Qt ${{ matrix.qt_version }}
|
||||
|
||||
env:
|
||||
CXXFLAGS: ${{ matrix.CXXFLAGS }}
|
||||
MAKEFLAGS: ${{ matrix.MAKEFLAGS }}
|
||||
QMAKE_MSC_VER: ${{ matrix.QMAKE_MSC_VER }}
|
||||
CMAKE_PREFIX_PATH: $Qt6_DIR/lib/cmake
|
||||
CMAKE_CXX_FLAGS_DEBUG: ${{ matrix.CMAKE_CXX_FLAGS_DEBUG }}
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Clone repo
|
||||
uses: actions/checkout@v2.3.4
|
||||
with:
|
||||
submodules: recursive
|
||||
- uses: actions/setup-python@v1
|
||||
- uses: Skycoder42/action-setup-qt@master
|
||||
id: qt
|
||||
|
||||
- name: Install Qt
|
||||
if: matrix.qt_version != 'system'
|
||||
uses: jurplel/install-qt-action@v2.14.0
|
||||
with:
|
||||
version: ${{matrix.version}}
|
||||
platform: ${{matrix.platform}}
|
||||
packages: qt.tools.ifw.32
|
||||
- name: qmake
|
||||
version: ${{ matrix.qt_version }}
|
||||
|
||||
- name: Install Qt from package manager
|
||||
if: matrix.qt_version == 'system'
|
||||
run: |
|
||||
qmake CONFIG+=install_ok QT_PLATFORM=${{matrix.platform}} "QT_TOOL_PATH=${{steps.qt.outputs.qtdir}}/Tools" nut.pro
|
||||
${{steps.qt.outputs.make}} qmake_all
|
||||
- name: make module
|
||||
run: |
|
||||
${{steps.qt.outputs.make}}
|
||||
${{steps.qt.outputs.make}} INSTALL_ROOT="${{steps.qt.outputs.installdir}}" install
|
||||
- name: make tests
|
||||
if: steps.qt.outputs.tests == 'true'
|
||||
run: |
|
||||
${{steps.qt.outputs.make}} all
|
||||
${{steps.qt.outputs.make}} ${{steps.qt.outputs.testflags}} run-tests
|
||||
- name: upload module to releases
|
||||
uses: Skycoder42/action-upload-release@master
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
sudo apt install qt5-default qt5-qmake qt5-qmake-bin libqt5core5a libqt5gui5 libqt5sql5 libqt5sql5-psql libqt5sql5-mysql libqt5sql5-sqlite
|
||||
|
||||
- name: Setup MSVC environment for QMake
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
repo_token: ${{secrets.GITHUB_TOKEN}}
|
||||
directory: ${{steps.qt.outputs.outdir}}
|
||||
platform: ${{matrix.platform}}
|
||||
asset_name: nut-${{matrix.platform}}-${{matrix.version}}
|
||||
tag: ${{github.ref}}
|
||||
overwrite: true
|
||||
uwp: false
|
||||
|
||||
- name: Build with QMake
|
||||
run: |
|
||||
mkdir build-qmake
|
||||
cd build-qmake
|
||||
qmake ../nut.pro
|
||||
${{ matrix.make }} qmake_all
|
||||
${{ matrix.make }}
|
||||
|
||||
- name: Build with CMake
|
||||
if: startsWith(matrix.qt_version, '6.')
|
||||
run: |
|
||||
mkdir build-cmake
|
||||
cd build-cmake
|
||||
cmake .. ${{ matrix.additional_arguments }} ${{ matrix.cmake_params }}
|
||||
cmake --build .
|
||||
|
||||
- name: Seutp postgres
|
||||
if: contains(matrix.tests, 'posgtresql')
|
||||
uses: ikalnytskyi/action-setup-postgres@v1
|
||||
|
||||
- name: Setup sql server
|
||||
if: contains(matrix.tests, 'mssql')
|
||||
uses: potatoqualitee/mssqlsuite@v1
|
||||
with:
|
||||
install: sqlengine
|
||||
sa-password: NUT_sa_PASS_1_???
|
||||
show-log: true
|
||||
|
||||
- name: Check sql server
|
||||
if: contains(matrix.tests, 'mssql')
|
||||
run: sqlcmd -S localhost -U sa -P NUT_sa_PASS_1_??? -d tempdb -Q "SELECT @@version;"
|
||||
|
||||
- name: Run tests with sqlite
|
||||
if: contains(matrix.tests, 'sqlite')
|
||||
continue-on-error: true
|
||||
run: |
|
||||
rm tests/auto/common/test_params.h
|
||||
cp tests/auto/common/test_params_sqlite.h tests/auto/common/test_params.h
|
||||
cd build-qmake
|
||||
${{ matrix.make }} all
|
||||
${{ matrix.make }} run-tests
|
||||
|
||||
- name: Run tests with posgtresql
|
||||
if: contains(matrix.tests, 'posgtresql')
|
||||
#continue-on-error: true
|
||||
run: |
|
||||
rm tests/auto/common/test_params.h
|
||||
cp tests/auto/common/test_params_postgresql.h tests/auto/common/test_params.h
|
||||
cd build-qmake
|
||||
${{ matrix.make }} all
|
||||
${{ matrix.make }} run-tests
|
||||
|
||||
- name: Run tests with mysql
|
||||
if: contains(matrix.tests, 'mysql')
|
||||
#continue-on-error: true
|
||||
run: |
|
||||
sudo systemctl start mysql.service
|
||||
rm tests/auto/common/test_params.h
|
||||
cp tests/auto/common/test_params_mysql.h tests/auto/common/test_params.h
|
||||
cd build-qmake
|
||||
${{ matrix.make }} all
|
||||
${{ matrix.make }} run-tests
|
||||
|
||||
- name: Run tests with sql server
|
||||
if: contains(matrix.tests, 'mssql')
|
||||
continue-on-error: true
|
||||
run: |
|
||||
rm tests/auto/common/test_params.h
|
||||
cp tests/auto/common/test_params_mssql.h tests/auto/common/test_params.h
|
||||
cd build-qmake
|
||||
${{ matrix.make }} all
|
||||
${{ matrix.make }} run-tests
|
||||
|
||||
deploy:
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
|
|
@ -94,7 +162,7 @@ jobs:
|
|||
- uses: Skycoder42/action-deploy-qt@master
|
||||
with:
|
||||
token: ${{secrets.GITHUB_TOKEN}}
|
||||
version: 5.15.0
|
||||
version: 5.15.2
|
||||
host: ${{secrets.SSHFS_HOST}}
|
||||
key: ${{secrets.SSHFS_KEY}}
|
||||
port: ${{secrets.SSHFS_PORT}}
|
||||
|
|
|
|||
|
|
@ -54,3 +54,4 @@ test/tst_quuid/tst_uuid*
|
|||
test/tst_upgrades/tst_upgrades*
|
||||
|
||||
.idea
|
||||
CMakeLists.txt.user
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
[submodule "src/nut/3rdparty/serializer"]
|
||||
path = src/nut/3rdparty/serializer
|
||||
url = https://github.com/HamedMasafi/Serializer.git
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# Generated from nut.pro.
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
|
||||
include(.cmake.conf)
|
||||
project(Nut
|
||||
VERSION "0.7.0"
|
||||
DESCRIPTION "Nut"
|
||||
HOMEPAGE_URL "https://github.com/HamedMasafi/Nut"
|
||||
LANGUAGES CXX C
|
||||
)
|
||||
|
||||
set(PROJECT_VERSION_MAJOR, 0)
|
||||
set(PROJECT_VERSION_MINOR, 7)
|
||||
set(PROJECT_VERSION_PATCH, 0)
|
||||
|
||||
find_package(Qt6 CONFIG REQUIRED COMPONENTS BuildInternals Core Gui Sql)
|
||||
|
||||
qt_build_repo()
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
Database class must inherits from Nut::Database class.
|
||||
Database class must inherit from Nut::Database class.
|
||||
Database class can have NUT_DB_VERSION for declaring version number, version will be stored in database if upgrade needed.
|
||||
```cpp
|
||||
NUT_DB_VERSION(major, minor)
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ auto posts = db.posts().query()
|
|||
->orderBy(Post::idField())
|
||||
->toList();
|
||||
```
|
||||
Also you can sort descending by adding **!** to field name
|
||||
Also, you can sort descending by adding **!** to field name
|
||||
```cpp
|
||||
auto posts = db.posts().query()
|
||||
->where(Post::idField() == 1)
|
||||
|
|
|
|||
|
|
@ -1,22 +0,0 @@
|
|||
QMAKE_CXX.QT_COMPILER_STDCXX = 201402L
|
||||
QMAKE_CXX.QMAKE_GCC_MAJOR_VERSION = 10
|
||||
QMAKE_CXX.QMAKE_GCC_MINOR_VERSION = 2
|
||||
QMAKE_CXX.QMAKE_GCC_PATCH_VERSION = 1
|
||||
QMAKE_CXX.COMPILER_MACROS = \
|
||||
QT_COMPILER_STDCXX \
|
||||
QMAKE_GCC_MAJOR_VERSION \
|
||||
QMAKE_GCC_MINOR_VERSION \
|
||||
QMAKE_GCC_PATCH_VERSION
|
||||
QMAKE_CXX.INCDIRS = \
|
||||
/usr/include/c++/10 \
|
||||
/usr/include/c++/10/x86_64-redhat-linux \
|
||||
/usr/include/c++/10/backward \
|
||||
/usr/lib/gcc/x86_64-redhat-linux/10/include \
|
||||
/usr/local/include \
|
||||
/usr/include
|
||||
QMAKE_CXX.LIBDIRS = \
|
||||
/usr/lib/gcc/x86_64-redhat-linux/10 \
|
||||
/usr/lib64 \
|
||||
/lib64 \
|
||||
/usr/lib \
|
||||
/lib
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# Generated from src.pro.
|
||||
|
||||
add_subdirectory(nut)
|
||||
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 535778e15d30ef51b53e80d47630bef4ca20f4c7
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
# Generated from nut.pro.
|
||||
|
||||
#####################################################################
|
||||
## Nut Module:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_add_module(Nut
|
||||
SOURCES
|
||||
config/nut_config.h
|
||||
config/nut_consts.h
|
||||
config/nut_global.h
|
||||
config/nut_macros.h
|
||||
config/nut_namespace.h
|
||||
core/abstracttableset.cpp core/abstracttableset.h
|
||||
core/abstracttablesetdata.h
|
||||
core/bulkinserter.cpp core/bulkinserter.h core/bulkinserter_p.h
|
||||
core/changelogtable.cpp core/changelogtable.h
|
||||
core/database.cpp core/database.h core/database_p.h
|
||||
core/foreigncontainer.cpp core/foreigncontainer.h
|
||||
core/propertysignalmapper.cpp core/propertysignalmapper.h
|
||||
core/query.cpp core/query.h
|
||||
core/table.cpp core/table.h core/table_p.h
|
||||
core/tableset.cpp core/tableset.h
|
||||
core/sqlserializer.cpp core/sqlserializer.h
|
||||
generators/abstractsqlgenerator.cpp generators/abstractsqlgenerator.h
|
||||
generators/mysqlgenerator.cpp generators/mysqlgenerator.h
|
||||
generators/postgresqlgenerator.cpp generators/postgresqlgenerator.h
|
||||
generators/sqlitegenerator.cpp generators/sqlitegenerator.h
|
||||
generators/sqlservergenerator.cpp generators/sqlservergenerator.h
|
||||
models/databasemodel.cpp models/databasemodel.h
|
||||
models/sqlmodel.cpp models/sqlmodel.h models/sqlmodel_p.h
|
||||
models/tablemodel.cpp models/tablemodel.h
|
||||
phrase.cpp phrase.h
|
||||
phrases/abstractfieldphrase.cpp phrases/abstractfieldphrase.h
|
||||
phrases/assignmentphrase.cpp phrases/assignmentphrase.h
|
||||
phrases/assignmentphraselist.cpp phrases/assignmentphraselist.h
|
||||
phrases/conditionalphrase.cpp phrases/conditionalphrase.h
|
||||
phrases/fieldphrase.cpp phrases/fieldphrase.h
|
||||
phrases/fieldphrase_bool.cpp phrases/fieldphrase_bool.h
|
||||
phrases/fieldphrase_date.cpp phrases/fieldphrase_date.h
|
||||
phrases/fieldphrase_qstring.cpp phrases/fieldphrase_qstring.h
|
||||
phrases/phrasedata.cpp phrases/phrasedata.h
|
||||
phrases/phrasedatalist.cpp phrases/phrasedatalist.h
|
||||
phrases/phraselist.cpp phrases/phraselist.h
|
||||
types/dbgeography.cpp types/dbgeography.h
|
||||
DEFINES
|
||||
NUT_BUILD_LIB
|
||||
NUT_SHARED
|
||||
NUT_SHARED_POINTER
|
||||
QT_DEPRECATED_WARNINGS
|
||||
INCLUDE_DIRECTORIES
|
||||
config
|
||||
core
|
||||
generators
|
||||
models
|
||||
phrases
|
||||
types
|
||||
PUBLIC_LIBRARIES
|
||||
Qt::Core
|
||||
Qt::Gui
|
||||
Qt::Sql
|
||||
)
|
||||
|
||||
#### Keys ignored in scope 1:.:.:nut.pro:<TRUE>:
|
||||
# MODULE = "nut"
|
||||
|
|
@ -1,6 +1,10 @@
|
|||
#ifndef NUT_CONFIG_H
|
||||
#define NUT_CONFIG_H
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
#if defined(NUT_SHARED) || !defined(NUT_STATIC)
|
||||
# ifdef NUT_STATIC
|
||||
# error "Both NUT_SHARED and NUT_STATIC defined, please make up your mind"
|
||||
|
|
@ -17,4 +21,6 @@
|
|||
# define NUT_EXPORT
|
||||
#endif
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // NUT_CONFIG_H
|
||||
|
|
|
|||
|
|
@ -21,6 +21,10 @@
|
|||
#ifndef NUT_CONSTS_H
|
||||
#define NUT_CONSTS_H
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
#define __NAME "name"
|
||||
#define __TYPE "type"
|
||||
#define __FIELDS "fields"
|
||||
|
|
@ -46,6 +50,7 @@
|
|||
#define __nut_REMOVE "remove"
|
||||
#define __nut_CHANGE "change"
|
||||
|
||||
#define NUT_NAMESPACE Nut
|
||||
#ifdef NUT_NAMESPACE
|
||||
# define NUT_BEGIN_NAMESPACE namespace NUT_NAMESPACE{
|
||||
# define NUT_END_NAMESPACE }
|
||||
|
|
@ -56,4 +61,6 @@
|
|||
# define NUT_WRAP_NAMESPACE(x) x
|
||||
#endif
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // NUT_CONSTS_H
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
#ifndef NUT_GLOBAL_H
|
||||
#define NUT_GLOBAL_H
|
||||
|
||||
#define NUT_NAMESPACE Nut
|
||||
#include <QtGlobal>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
#include <QtNut/nut_config.h>
|
||||
#include <QtNut/nut_consts.h>
|
||||
|
|
@ -9,4 +11,6 @@
|
|||
#include <QtNut/nut_macros.h>
|
||||
#include <QtNut/nut_namespace.h>
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // NUT_GLOBAL_H
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
#ifndef NUT_MACROS_H
|
||||
#define NUT_MACROS_H
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
#define NUT_INFO(type, name, value) \
|
||||
Q_CLASSINFO(__nut_NAME_PERFIX type #name #value, \
|
||||
|
|
@ -20,22 +23,23 @@
|
|||
#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: \
|
||||
NUT_WRAP_NAMESPACE(TableSet<type>) * m_##name; \
|
||||
\
|
||||
public: \
|
||||
static const type *_##name; \
|
||||
NUT_WRAP_NAMESPACE(TableSet<type>) *name() const \
|
||||
{ return m_##name; } \
|
||||
private:
|
||||
NUT_WRAP_NAMESPACE(TableSet<type>) * name() const { return m_##name; } \
|
||||
\
|
||||
private:
|
||||
|
||||
//Table
|
||||
#define NUT_FIELD(type, name) \
|
||||
private: \
|
||||
private: \
|
||||
NUT_INFO(__nut_FIELD, name, 0) \
|
||||
public: \
|
||||
static NUT_WRAP_NAMESPACE(FieldPhrase<type>)& name ## Field(){ \
|
||||
static NUT_WRAP_NAMESPACE(FieldPhrase<type>) f = \
|
||||
NUT_WRAP_NAMESPACE(FieldPhrase<type>) \
|
||||
(staticMetaObject.className(), #name); \
|
||||
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; \
|
||||
}
|
||||
|
||||
|
|
@ -43,101 +47,101 @@
|
|||
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); \
|
||||
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){ \
|
||||
type read() const { return m_##name; } \
|
||||
void write(type name) \
|
||||
{ \
|
||||
m_##name = name; \
|
||||
propertyChanged(QString::fromUtf8(#name)); \
|
||||
}
|
||||
|
||||
#define NUT_FOREIGN_KEY(type, keytype, name, read, write) \
|
||||
Q_PROPERTY(Nut::Row<type> name READ read WRITE write) \
|
||||
Q_PROPERTY(NUT_WRAP_NAMESPACE(Row<type>) name READ read WRITE write) \
|
||||
NUT_DECLARE_FIELD(keytype, name##Id, read##Id, write##Id) \
|
||||
NUT_INFO(__nut_FOREIGN_KEY, name, type) \
|
||||
Nut::Row<type> m_##name; \
|
||||
NUT_WRAP_NAMESPACE(Row<type>) m_##name; \
|
||||
public Q_SLOTS: \
|
||||
Nut::Row<type> read() const { return m_##name ; } \
|
||||
Q_INVOKABLE void write(Nut::Row<type> name){ \
|
||||
m_##name = name; \
|
||||
}
|
||||
NUT_WRAP_NAMESPACE(Row<type>) read() const { return m_##name; } \
|
||||
Q_INVOKABLE void write(NUT_WRAP_NAMESPACE(Row<type>) name) { m_##name = name; }
|
||||
|
||||
#define NUT_FOREIGN_KEY_DECLARE(type, keytype, name, read, write) \
|
||||
NUT_INFO(__nut_FIELD, name##Id, 0) \
|
||||
NUT_INFO(__nut_FOREIGN_KEY, name, type) \
|
||||
Nut::Row<type> m_##name; \
|
||||
NUT_WRAP_NAMESPACE(Row<type>) m_##name; \
|
||||
keytype m_##name##Id; \
|
||||
Q_PROPERTY(Nut::Row<type> name READ read WRITE write) \
|
||||
Q_PROPERTY(NUT_WRAP_NAMESPACE(Row<type>) name READ read WRITE write) \
|
||||
Q_PROPERTY(keytype name##Id READ read##Id WRITE write##Id) \
|
||||
public: \
|
||||
Nut::Row<type> read() const; \
|
||||
NUT_WRAP_NAMESPACE(Row<type>) read() const; \
|
||||
keytype read##Id() const; \
|
||||
static NUT_WRAP_NAMESPACE(FieldPhrase<keytype>)& name##Id ## Field(){ \
|
||||
static NUT_WRAP_NAMESPACE(FieldPhrase<keytype>) f = \
|
||||
NUT_WRAP_NAMESPACE(FieldPhrase<keytype>) \
|
||||
(staticMetaObject.className(), #name "Id"); \
|
||||
static NUT_WRAP_NAMESPACE(FieldPhrase<keytype>) & name##Id##Field() \
|
||||
{ \
|
||||
static NUT_WRAP_NAMESPACE(FieldPhrase<keytype>) f = NUT_WRAP_NAMESPACE( \
|
||||
FieldPhrase<keytype>)(staticMetaObject.className(), #name "Id"); \
|
||||
return f; \
|
||||
} \
|
||||
public : \
|
||||
Q_INVOKABLE void write(Nut::Row<type> name); \
|
||||
Q_INVOKABLE void write(Nut::Row<Nut::Table> name); \
|
||||
\
|
||||
public: \
|
||||
Q_INVOKABLE void write(NUT_WRAP_NAMESPACE(Row<type>) name); \
|
||||
Q_INVOKABLE void write(NUT_WRAP_NAMESPACE(Row<NUT_WRAP_NAMESPACE(Table)>) name); \
|
||||
void write##Id(keytype name##Id);
|
||||
|
||||
#define NUT_FOREIGN_KEY_IMPLEMENT(class, type, keytype, name, read, write) \
|
||||
Nut::Row<type> class::read() const { return m_##name ; } \
|
||||
void class::write(Nut::Row<type> name){ \
|
||||
NUT_WRAP_NAMESPACE(Row<type>) class ::read() const { return m_##name; } \
|
||||
void class ::write(NUT_WRAP_NAMESPACE(Row<type>) name) \
|
||||
{ \
|
||||
propertyChanged(QStringLiteral(QT_STRINGIFY2(name##Id))); \
|
||||
m_##name = name; \
|
||||
m_##name##Id = name->primaryValue().value<keytype>(); \
|
||||
} \
|
||||
void class::write(Nut::Row<Nut::Table> name){ \
|
||||
void class ::write(NUT_WRAP_NAMESPACE(Row<NUT_WRAP_NAMESPACE(Table)>) name) \
|
||||
{ \
|
||||
write(qSharedPointerDynamicCast<type>(name)); \
|
||||
} keytype class::read##Id() const{ \
|
||||
} \
|
||||
keytype class ::read##Id() const \
|
||||
{ \
|
||||
if (m_##name) \
|
||||
return m_##name->primaryValue().value<keytype>(); \
|
||||
return m_##name##Id; \
|
||||
} \
|
||||
void class::write##Id(keytype name##Id){ \
|
||||
void class ::write##Id(keytype name##Id) \
|
||||
{ \
|
||||
m_##name##Id = name##Id; \
|
||||
m_##name = nullptr; \
|
||||
propertyChanged(QStringLiteral(QT_STRINGIFY2(name##Id))); \
|
||||
}
|
||||
|
||||
|
||||
#define NUT_DECLARE_CHILD_TABLE(type, n) \
|
||||
private: \
|
||||
private: \
|
||||
NUT_WRAP_NAMESPACE(TableSet)<type> *m_##n; \
|
||||
public: \
|
||||
\
|
||||
public: \
|
||||
static type *n##Table(); \
|
||||
NUT_WRAP_NAMESPACE(TableSet)<type> *n();
|
||||
|
||||
#define NUT_IMPLEMENT_CHILD_TABLE(class, type, n) \
|
||||
type *class::n##Table(){ \
|
||||
type *class ::n##Table() \
|
||||
{ \
|
||||
static auto f = new type(); \
|
||||
return f; \
|
||||
} \
|
||||
NUT_WRAP_NAMESPACE(TableSet)<type> *class::n(){ \
|
||||
return m_##n; \
|
||||
}
|
||||
NUT_WRAP_NAMESPACE(TableSet)<type> *class ::n() { return m_##n; }
|
||||
|
||||
//#define NUT_FIELD(name) NUT_INFO(__nut_FIELD, name, 0)
|
||||
#define NUT_PRIMARY_KEY(x) NUT_INFO(__nut_PRIMARY_KEY, x, 0) \
|
||||
public: \
|
||||
QVariant primaryValue() const override { \
|
||||
return property(#x); \
|
||||
} \
|
||||
void setPrimaryValue(const QVariant &value) override { \
|
||||
setProperty(#x, value); \
|
||||
} \
|
||||
private:
|
||||
|
||||
#define NUT_PRIMARY_KEY(x) \
|
||||
NUT_INFO(__nut_PRIMARY_KEY, x, 0) \
|
||||
public: \
|
||||
QVariant primaryValue() const override { return property(#x); } \
|
||||
void setPrimaryValue(const QVariant &value) override { setProperty(#x, value); } \
|
||||
\
|
||||
private:
|
||||
|
||||
#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)\
|
||||
|
|
@ -149,4 +153,6 @@ public : \
|
|||
#define NUT_NOT_NULL(x) NUT_INFO(__nut_NOT_NULL, x, 1)
|
||||
#define NUT_INDEX(name, field, order)
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // NUT_MACROS_H
|
||||
|
|
|
|||
|
|
@ -1,10 +1,6 @@
|
|||
#ifndef NUT_NAMESPACE_H
|
||||
#define NUT_NAMESPACE_H
|
||||
|
||||
#ifndef NUT_GLOBAL_H
|
||||
# error "Do not include nut_namespace.h header directly!"
|
||||
#endif
|
||||
|
||||
//avoid ide warnings
|
||||
#include <QtNut/nut_global.h>
|
||||
|
||||
|
|
@ -13,6 +9,8 @@
|
|||
#include <QtCore/QVariant>
|
||||
#include <QtCore/QMetaClassInfo>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
inline bool nutClassInfo(const QMetaClassInfo &classInfo,
|
||||
|
|
@ -84,59 +82,77 @@ inline bool nutClassInfoInt(const QMetaClassInfo &classInfo,
|
|||
}
|
||||
|
||||
#ifdef NUT_RAW_POINTER
|
||||
template <typename T>
|
||||
using RowList = QList<T*>;
|
||||
|
||||
template <typename T>
|
||||
using RowSet = QSet<T*>;
|
||||
|
||||
template <typename T>
|
||||
using Row = T*;
|
||||
template<typename T>
|
||||
using RowList = QList<T *>;
|
||||
|
||||
template<class T>
|
||||
inline Row<T> create() {
|
||||
using WeakRowList = QList<T *>;
|
||||
|
||||
template<typename T>
|
||||
using RowSet = QSet<T *>;
|
||||
|
||||
template<typename T>
|
||||
using Row = T *;
|
||||
|
||||
template<class T>
|
||||
inline Row<T> create()
|
||||
{
|
||||
return new T;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline T *get(const Row<T> row) {
|
||||
inline T *get(const Row<T> row)
|
||||
{
|
||||
return row;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline T *get(const QSharedPointer<T> row) {
|
||||
inline T *get(const QSharedPointer<T> row)
|
||||
{
|
||||
return row.data();
|
||||
}
|
||||
#else
|
||||
template <class T>
|
||||
template<class T>
|
||||
using RowList = QList<QSharedPointer<T>>;
|
||||
|
||||
template <class T>
|
||||
using RowSet = QSet<QSharedPointer<T>>;
|
||||
|
||||
template <typename T>
|
||||
using Row = QSharedPointer<T>;
|
||||
template<class T>
|
||||
using WeakRowList = QList<QWeakPointer<T>>;
|
||||
|
||||
template<class T>
|
||||
inline Row<T> create() {
|
||||
using RowSet = QSet<QSharedPointer<T>>;
|
||||
|
||||
template<typename T>
|
||||
using Row = QSharedPointer<T>;
|
||||
|
||||
template<typename T>
|
||||
using WeakRow = QWeakPointer<T>;
|
||||
|
||||
template<class T>
|
||||
inline Row<T> create()
|
||||
{
|
||||
return QSharedPointer<T>(new T);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline Row<T> create(QObject *parent) {
|
||||
inline Row<T> create(QObject *parent)
|
||||
{
|
||||
return QSharedPointer<T>(new T(parent));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline Row<T> createFrom(T *row) {
|
||||
inline Row<T> createFrom(T *row)
|
||||
{
|
||||
return QSharedPointer<T>(row);
|
||||
}
|
||||
template<class T>
|
||||
inline Row<T> createFrom(const QSharedPointer<T> row) {
|
||||
inline Row<T> createFrom(const QSharedPointer<T> row)
|
||||
{
|
||||
return row;
|
||||
}
|
||||
#endif
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // NUT_NAMESPACE_H
|
||||
|
|
|
|||
|
|
@ -18,12 +18,16 @@
|
|||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include <QWeakPointer>
|
||||
|
||||
#include "table.h"
|
||||
#include "database.h"
|
||||
#include "abstracttableset.h"
|
||||
#include "databasemodel.h"
|
||||
#include "abstracttablesetdata.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
AbstractTableSet::AbstractTableSet(Database *parent) : QObject(parent),
|
||||
|
|
@ -40,7 +44,7 @@ AbstractTableSet::AbstractTableSet(Table *parent) : QObject(parent),
|
|||
|
||||
AbstractTableSet::~AbstractTableSet()
|
||||
{
|
||||
Q_FOREACH (Row<Table> t, data->childs)
|
||||
for (auto &t: data->children)
|
||||
if (t)
|
||||
t->setParentTableSet(nullptr);
|
||||
}
|
||||
|
|
@ -52,14 +56,14 @@ int AbstractTableSet::save(Database *db, bool cleanUp)
|
|||
if (data->table)
|
||||
masterModel = db->model().tableByClassName(QString::fromUtf8(data->table->metaObject()->className()));
|
||||
|
||||
Q_FOREACH (Row<Table> t, data->childs) {
|
||||
for (auto &t : data->children) {
|
||||
if (data->table)
|
||||
t->setParentTable(data->table,
|
||||
masterModel,
|
||||
db->model().tableByClassName(QString::fromUtf8(t->metaObject()->className())));
|
||||
db->model().tableByClassName(
|
||||
QString::fromUtf8(t->metaObject()->className())));
|
||||
|
||||
if (t->status() == Table::Added
|
||||
|| t->status() == Table::Modified
|
||||
if (t->status() == Table::Added || t->status() == Table::Modified
|
||||
|| t->status() == Table::Deleted) {
|
||||
rowsAffected += t->save(db);
|
||||
if (cleanUp)
|
||||
|
|
@ -71,32 +75,67 @@ int AbstractTableSet::save(Database *db, bool cleanUp)
|
|||
}
|
||||
}
|
||||
|
||||
for (auto &row : data->weakChildren) {
|
||||
auto t = row.lock();
|
||||
if (data->table)
|
||||
t->setParentTable(data->table,
|
||||
masterModel,
|
||||
db->model().tableByClassName(
|
||||
QString::fromUtf8(t->metaObject()->className())));
|
||||
|
||||
if (t->status() == Table::Added || t->status() == Table::Modified
|
||||
|| t->status() == Table::Deleted) {
|
||||
rowsAffected += t->save(db);
|
||||
if (cleanUp)
|
||||
data->childs.clear();
|
||||
#ifdef NUT_RAW_POINTER
|
||||
t->deleteLater();
|
||||
#else
|
||||
remove(row);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (cleanUp) {
|
||||
data->children.clear();
|
||||
data->weakChildren.clear();
|
||||
}
|
||||
|
||||
return rowsAffected;
|
||||
}
|
||||
|
||||
void AbstractTableSet::clearChilds()
|
||||
void AbstractTableSet::clearChildren()
|
||||
{
|
||||
#ifdef NUT_RAW_POINTER
|
||||
Q_FOREACH (Table *t, data->childs)
|
||||
for (auto &t: data->children)
|
||||
t->deleteLater();
|
||||
#endif
|
||||
data->childs.clear();
|
||||
data->children.clear();
|
||||
}
|
||||
|
||||
void AbstractTableSet::add(Row<Table> t)
|
||||
{
|
||||
data.detach();
|
||||
data->childs.append(t);
|
||||
data->children.append(t);
|
||||
t->setParentTableSet(this);
|
||||
}
|
||||
|
||||
void AbstractTableSet::add(WeakRow<Table> t)
|
||||
{
|
||||
data.detach();
|
||||
data->weakChildren.append(t);
|
||||
t.toStrongRef()->setParentTableSet(this);
|
||||
}
|
||||
|
||||
void AbstractTableSet::remove(Row<Table> t)
|
||||
{
|
||||
data.detach();
|
||||
data->childs.removeAll(t);
|
||||
data->children.removeAll(t);
|
||||
}
|
||||
|
||||
void AbstractTableSet::remove(WeakRow<Table> t)
|
||||
{
|
||||
data.detach();
|
||||
data->weakChildren.removeAll(t);
|
||||
}
|
||||
|
||||
QString AbstractTableSet::childClassName() const
|
||||
|
|
@ -117,7 +156,9 @@ void AbstractTableSet::setDatabase(Database *database)
|
|||
|
||||
int AbstractTableSet::size() const
|
||||
{
|
||||
return data->childs.size();
|
||||
return data->children.size();
|
||||
}
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -28,11 +28,14 @@
|
|||
|
||||
#include <QtNut/nut_global.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
class Table;
|
||||
class Database;
|
||||
class AbstractTableSetData;
|
||||
class TableModel;
|
||||
class NUT_EXPORT AbstractTableSet : public QObject
|
||||
{
|
||||
|
||||
|
|
@ -42,7 +45,7 @@ public:
|
|||
virtual ~AbstractTableSet();
|
||||
|
||||
virtual int save(Database *db, bool cleanUp = false);
|
||||
void clearChilds();
|
||||
void clearChildren();
|
||||
QString childClassName() const;
|
||||
|
||||
Database *database() const;
|
||||
|
|
@ -58,12 +61,17 @@ public://TODO: change this to private
|
|||
// void remove(Table *t);
|
||||
|
||||
void add(Row<Table> t);
|
||||
void add(WeakRow<Table> t);
|
||||
void remove(Row<Table> t);
|
||||
void remove(WeakRow<Table> t);
|
||||
|
||||
friend class Table;
|
||||
friend class QueryBase;
|
||||
private:
|
||||
void saveChangedOnRow(Nut::Table *t, Nut::TableModel *masterModel);
|
||||
};
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // NUT_ABSTRACTTABLESET_H
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
#include <QtNut/nut_global.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
class Table;
|
||||
|
|
@ -42,13 +44,17 @@ public:
|
|||
|
||||
// QSet<Table*> tables;
|
||||
// QList<Table*> childRows;
|
||||
RowList<Table> childs;
|
||||
RowList<Table> children;
|
||||
WeakRowList<Table> weakChildren;
|
||||
|
||||
Database *database;
|
||||
Table *table;
|
||||
QString childClassName;
|
||||
};
|
||||
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // NUT_ABSTRACTTABLESETDATA_H
|
||||
|
|
|
|||
|
|
@ -1,3 +1,23 @@
|
|||
/**************************************************************************
|
||||
**
|
||||
** 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 "bulkinserter.h"
|
||||
#include "bulkinserter_p.h"
|
||||
|
||||
|
|
@ -8,6 +28,8 @@
|
|||
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
BulkInserterPrivate::BulkInserterPrivate(Database *db)
|
||||
|
|
@ -21,7 +43,7 @@ BulkInserter::BulkInserter(Database *db, QString &className)
|
|||
{
|
||||
Q_D(BulkInserter);
|
||||
|
||||
Q_FOREACH (TableModel *m, db->model())
|
||||
for (auto &m: db->model())
|
||||
if (m->className() == className)
|
||||
d->className = m->name();
|
||||
}
|
||||
|
|
@ -71,3 +93,5 @@ int BulkInserter::apply()
|
|||
}
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -1,3 +1,23 @@
|
|||
/**************************************************************************
|
||||
**
|
||||
** 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 BULKINSERTER_H
|
||||
#define BULKINSERTER_H
|
||||
|
||||
|
|
@ -8,6 +28,8 @@
|
|||
|
||||
#include <QtNut/nut_global.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
class PhraseList;
|
||||
|
|
@ -15,7 +37,7 @@ class Database;
|
|||
class BulkInserterPrivate;
|
||||
class NUT_EXPORT BulkInserter
|
||||
{
|
||||
Q_DECLARE_PRIVATE(BulkInserter);
|
||||
Q_DECLARE_PRIVATE(BulkInserter)
|
||||
|
||||
public:
|
||||
BulkInserter(Database *db, QString &className);
|
||||
|
|
@ -37,4 +59,6 @@ private:
|
|||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // BULKINSERTER_H
|
||||
|
|
|
|||
|
|
@ -1,8 +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/>.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Nut API. This header
|
||||
// file may change from version to version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#ifndef BULKINSERTER_P_H
|
||||
#define BULKINSERTER_P_H
|
||||
|
||||
#include <QtNut/phraselist.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
class Database;
|
||||
|
|
@ -20,4 +52,6 @@ public:
|
|||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // BULKINSERTER_P_H
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
#include "changelogtable.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
ChangeLogTable::ChangeLogTable(QObject *tableSet) : Table(tableSet)
|
||||
|
|
@ -29,3 +31,5 @@ ChangeLogTable::ChangeLogTable(QObject *tableSet) : Table(tableSet)
|
|||
}
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
#include <QtCore/qglobal.h>
|
||||
#include <QtNut/table.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
class NUT_EXPORT ChangeLogTable : public Table
|
||||
|
|
@ -43,6 +45,8 @@ public:
|
|||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
Q_DECLARE_METATYPE(Nut::ChangeLogTable*)
|
||||
QT_END_NAMESPACE
|
||||
|
||||
Q_DECLARE_METATYPE(NUT_WRAP_NAMESPACE(ChangeLogTable*))
|
||||
|
||||
#endif // CHANGELOGTABLE_H
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ HEADERS += \
|
|||
$$PWD/foreigncontainer.h \
|
||||
$$PWD/propertysignalmapper.h \
|
||||
$$PWD/query.h \
|
||||
$$PWD/sqlserializer.h \
|
||||
$$PWD/table.h \
|
||||
$$PWD/table_p.h \
|
||||
$$PWD/tableset.h
|
||||
|
|
@ -23,6 +24,7 @@ SOURCES += \
|
|||
$$PWD/foreigncontainer.cpp \
|
||||
$$PWD/propertysignalmapper.cpp \
|
||||
$$PWD/query.cpp \
|
||||
$$PWD/sqlserializer.cpp \
|
||||
$$PWD/table.cpp \
|
||||
$$PWD/tableset.cpp
|
||||
|
||||
|
|
|
|||
|
|
@ -49,8 +49,11 @@
|
|||
# define __CHANGE_LOG_TABLE_NAME "__change_logs"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
QStringList DatabasePrivate::updatedDatabases;
|
||||
qulonglong DatabasePrivate::lastId = 0;
|
||||
QMap<QString, DatabaseModel> DatabasePrivate::allTableMaps;
|
||||
|
||||
|
|
@ -131,7 +134,12 @@ bool DatabasePrivate::updateDatabase()
|
|||
{
|
||||
Q_Q(Database);
|
||||
|
||||
if (!getCurrectSchema())
|
||||
QString databaseHistoryName = driver + "\t" + databaseName + "\t" + hostName;
|
||||
|
||||
if (updatedDatabases.contains(databaseHistoryName))
|
||||
return true;
|
||||
|
||||
if (!getCurrentSchema())
|
||||
return true;
|
||||
|
||||
DatabaseModel last = isDatabaseNew ? DatabaseModel() : getLastSchema();
|
||||
|
|
@ -140,12 +148,12 @@ bool DatabasePrivate::updateDatabase()
|
|||
if (last == current) {
|
||||
qDebug("Database is up-to-date");
|
||||
//TODO: crash without this and I don't know why!
|
||||
changeLogs->clearChilds();
|
||||
changeLogs->clearChildren();
|
||||
return true;
|
||||
}
|
||||
|
||||
Q_FOREACH (TableModel *tm, current) {
|
||||
Q_FOREACH (FieldModel *fm, tm->fields()) {
|
||||
for (auto &tm: current) {
|
||||
for (auto &fm: tm->fields()) {
|
||||
if (sqlGenerator->fieldType(fm).isEmpty()) {
|
||||
qWarning("The type (%s) is not supported for field %s::%s",
|
||||
QMetaType::typeName(fm->type),
|
||||
|
|
@ -160,10 +168,10 @@ bool DatabasePrivate::updateDatabase()
|
|||
else
|
||||
qDebug("Database is changed");
|
||||
|
||||
QStringList sql = sqlGenerator->diff(last, current);
|
||||
QStringList sql = sqlGenerator->diffDatabase(last, current);
|
||||
|
||||
db.transaction();
|
||||
Q_FOREACH (QString s, sql) {
|
||||
for (auto &s: sql) {
|
||||
db.exec(s);
|
||||
|
||||
if (db.lastError().type() != QSqlError::NoError) {
|
||||
|
|
@ -182,6 +190,7 @@ bool DatabasePrivate::updateDatabase()
|
|||
if (!last.count())
|
||||
q->databaseCreated();
|
||||
|
||||
updatedDatabases.append(databaseHistoryName);
|
||||
} else {
|
||||
qWarning("Unable update database, error = %s",
|
||||
db.lastError().text().toLatin1().data());
|
||||
|
|
@ -190,14 +199,14 @@ bool DatabasePrivate::updateDatabase()
|
|||
return ok;
|
||||
}
|
||||
|
||||
bool DatabasePrivate::getCurrectSchema()
|
||||
bool DatabasePrivate::getCurrentSchema()
|
||||
{
|
||||
Q_Q(Database);
|
||||
|
||||
//is not first instanicate of this class
|
||||
if (allTableMaps.contains(QString::fromUtf8(q->metaObject()->className()))) {
|
||||
currentModel = allTableMaps[QString::fromUtf8(q->metaObject()->className())];
|
||||
return false;
|
||||
// return false;
|
||||
}
|
||||
|
||||
QMap<QString, QString> tables;
|
||||
|
|
@ -252,15 +261,28 @@ bool DatabasePrivate::getCurrectSchema()
|
|||
QMetaProperty tableProperty = q->metaObject()->property(i);
|
||||
int typeId = QMetaType::type(tableProperty.typeName());
|
||||
|
||||
if (tables.values().contains(QString::fromUtf8(tableProperty.name()))
|
||||
&& (unsigned)typeId >= QVariant::UserType) {
|
||||
TableModel *sch = new TableModel(typeId, QString::fromUtf8(tableProperty.name()));
|
||||
if ((unsigned) typeId >= QVariant::UserType) {
|
||||
bool contains{false};
|
||||
auto tableName = QString::fromUtf8(tableProperty.name());
|
||||
for (auto i = tables.begin(); i != tables.end(); ++i)
|
||||
if (i.value() == tableName)
|
||||
contains = true;
|
||||
|
||||
if (contains) {
|
||||
TableModel *sch = new TableModel(typeId, tableName);
|
||||
currentModel.append(sch);
|
||||
}
|
||||
}
|
||||
|
||||
Q_FOREACH (TableModel *table, currentModel) {
|
||||
Q_FOREACH (FieldModel *f, table->fields()) {
|
||||
/*if (tables.values().contains(QString::fromUtf8(tableProperty.name()))
|
||||
&& (unsigned)typeId >= QVariant::UserType) {
|
||||
TableModel *sch = new TableModel(typeId, QString::fromUtf8(tableProperty.name()));
|
||||
currentModel.append(sch);
|
||||
}*/
|
||||
}
|
||||
|
||||
for (auto &table: currentModel) {
|
||||
for (auto &f: table->fields()) {
|
||||
if (f->isPrimaryKey && ! sqlGenerator->supportPrimaryKey(f->type))
|
||||
qFatal("The field of type %s does not support as primary key",
|
||||
qPrintable(f->typeName));
|
||||
|
|
@ -270,7 +292,7 @@ bool DatabasePrivate::getCurrectSchema()
|
|||
qPrintable(f->typeName));
|
||||
}
|
||||
|
||||
Q_FOREACH (RelationModel *fk, table->foreignKeys())
|
||||
for (auto &fk: table->foreignKeys())
|
||||
fk->masterTable = currentModel.tableByClassName(fk->masterClassName);
|
||||
}
|
||||
|
||||
|
|
@ -295,28 +317,8 @@ DatabaseModel DatabasePrivate::getLastSchema()
|
|||
|
||||
DatabaseModel ret = json;
|
||||
return ret;
|
||||
/*
|
||||
Q_FOREACH (QString key, json.keys()) {
|
||||
TableModel *sch = new TableModel(json.value(key).toObject(), key);
|
||||
ret.append(sch);
|
||||
}*/
|
||||
}
|
||||
return DatabaseModel();
|
||||
|
||||
// QSqlQuery query = q->exec("select * from __change_logs order by id
|
||||
// desc limit 1");
|
||||
// DatabaseModel ret;
|
||||
// if(query.next()){
|
||||
// QJsonObject json =
|
||||
// QJsonDocument::fromJson(query.value("data").toByteArray()).object();
|
||||
|
||||
// Q_FOREACH (QString key, json.keys()) {
|
||||
// TableModel *sch = new TableModel(json.value(key).toObject(),
|
||||
// key);
|
||||
// ret.append(sch);
|
||||
// }
|
||||
// }
|
||||
// return ret;
|
||||
}
|
||||
|
||||
bool DatabasePrivate::putModelToDatabase()
|
||||
|
|
@ -333,26 +335,16 @@ bool DatabasePrivate::putModelToDatabase()
|
|||
changeLog->deleteLater();
|
||||
|
||||
return true;
|
||||
|
||||
// QSqlQuery query(db);
|
||||
// query.prepare("insert into __change_logs (data) values (:data)");
|
||||
// query.bindValue(":data",
|
||||
// QString(QJsonDocument(currentModel.toJson()).toJson()));
|
||||
// bool ret = query.exec();
|
||||
// if(query.lastError().type() != QSqlError::NoError)
|
||||
// qWarning(QString("storeSchemaInDB" +
|
||||
// query.lastError().text()).toLatin1().data());
|
||||
// return ret;
|
||||
}
|
||||
|
||||
void DatabasePrivate::createChangeLogs()
|
||||
{
|
||||
// currentModel.model("change_log")
|
||||
QStringList diff = sqlGenerator->diff(nullptr,
|
||||
QStringList diff = sqlGenerator->diffTable(nullptr,
|
||||
currentModel.tableByName(
|
||||
QStringLiteral("__change_log")));
|
||||
|
||||
Q_FOREACH (QString s, diff)
|
||||
for (auto &s: diff)
|
||||
db.exec(s);
|
||||
}
|
||||
|
||||
|
|
@ -564,7 +556,7 @@ bool Database::open(bool updateDatabase)
|
|||
else if (d->driver == QStringLiteral("QODBC") || d->driver == QStringLiteral("QODBC3")) {
|
||||
QString driverName = QString();
|
||||
QStringList parts = d->databaseName.toLower().split(';');
|
||||
Q_FOREACH (QString p, parts)
|
||||
for (auto &p: parts)
|
||||
if (p.trimmed().startsWith(QStringLiteral("driver=")))
|
||||
driverName = p.split('=').at(1).toLower().trimmed();
|
||||
|
||||
|
|
@ -615,7 +607,7 @@ int Database::saveChanges(bool cleanUp)
|
|||
}
|
||||
|
||||
int rowsAffected = 0;
|
||||
Q_FOREACH (AbstractTableSet *ts, d->tableSets)
|
||||
for (const auto &ts: qAsConst(d->tableSets))
|
||||
rowsAffected += ts->save(this, cleanUp);
|
||||
|
||||
return rowsAffected;
|
||||
|
|
@ -624,8 +616,10 @@ int Database::saveChanges(bool cleanUp)
|
|||
void Database::cleanUp()
|
||||
{
|
||||
Q_D(Database);
|
||||
Q_FOREACH (AbstractTableSet *ts, d->tableSets)
|
||||
ts->clearChilds();
|
||||
for (const auto &ts: qAsConst(d->tableSets))
|
||||
ts->clearChildren();
|
||||
}
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@
|
|||
#include <QtNut/nut_global.h>
|
||||
#include <QtNut/tableset.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
class DatabaseModel;
|
||||
|
|
@ -57,7 +59,7 @@ public:
|
|||
|
||||
QSqlQuery exec(const QString& sql);
|
||||
|
||||
int saveChanges(bool cleanUp = false);
|
||||
int saveChanges(bool cleanUp = true);
|
||||
void cleanUp();
|
||||
|
||||
QString databaseName() const;
|
||||
|
|
@ -75,7 +77,6 @@ public:
|
|||
QSqlDatabase database();
|
||||
|
||||
protected:
|
||||
//remove minor version
|
||||
virtual void databaseCreated();
|
||||
virtual void databaseUpdated(int oldVersion, int newVersion);
|
||||
|
||||
|
|
@ -96,4 +97,6 @@ private:
|
|||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // NUTDATABASE_H
|
||||
|
|
|
|||
|
|
@ -18,6 +18,16 @@
|
|||
**
|
||||
**************************************************************************/
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Nut API. This header
|
||||
// file may change from version to version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#ifndef DATABASE_P_H
|
||||
#define DATABASE_P_H
|
||||
|
||||
|
|
@ -27,6 +37,8 @@
|
|||
#include <QtNut/database.h>
|
||||
#include <QtNut/databasemodel.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
class ChangeLogTable;
|
||||
|
|
@ -44,7 +56,7 @@ public:
|
|||
void createChangeLogs();
|
||||
bool putModelToDatabase();
|
||||
DatabaseModel getLastSchema();
|
||||
bool getCurrectSchema();
|
||||
bool getCurrentSchema();
|
||||
|
||||
QSqlDatabase db;
|
||||
|
||||
|
|
@ -63,6 +75,7 @@ public:
|
|||
|
||||
static QMap<QString, DatabaseModel> allTableMaps;
|
||||
static qulonglong lastId;
|
||||
static QStringList updatedDatabases;
|
||||
|
||||
QSet<AbstractTableSet *> tableSets;
|
||||
|
||||
|
|
@ -73,4 +86,6 @@ public:
|
|||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // DATABASE_P_H
|
||||
|
|
|
|||
|
|
@ -1,6 +1,33 @@
|
|||
/**************************************************************************
|
||||
**
|
||||
** 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 FOREIGNCONTAINER_H
|
||||
#define FOREIGNCONTAINER_H
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QtNut/NutGlobal>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
template<class _OBJECT, typename _KEY>
|
||||
class ForeignContainer
|
||||
{
|
||||
|
|
@ -55,4 +82,8 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // FOREIGNCONTAINER_H
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@
|
|||
|
||||
#include "propertysignalmapper.h"
|
||||
#include "table.h"
|
||||
#include "nut_global.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
|
|
@ -71,3 +74,5 @@ QString PropertySignalMapper::changedProperty(QObject *obj, int senderSignalInde
|
|||
}
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@
|
|||
#include <QMetaMethod>
|
||||
#include <QMetaProperty>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
class Table;
|
||||
|
|
@ -46,4 +48,6 @@ public:
|
|||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // PROPERTYSIGNALMAPPER_H
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
#include "query.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
|
|
@ -80,3 +82,5 @@ NUT_BEGIN_NAMESPACE
|
|||
*/
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -44,9 +44,18 @@
|
|||
#include <QtNut/tablemodel.h>
|
||||
#include <QtNut/sqlmodel.h>
|
||||
|
||||
#ifdef NUT_PRINT_DEBUG_INFO
|
||||
# define printSql(sql) qDebug().noquote() << "[Nut][" << __FUNCTION__ << "] sql=" << sql;
|
||||
#else
|
||||
# define printSql(sql)
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
struct NUT_EXPORT QueryData {
|
||||
bool hasCustomCommand{false};
|
||||
QString sql;
|
||||
QString className;
|
||||
QString tableName;
|
||||
|
|
@ -146,15 +155,17 @@ public:
|
|||
|
||||
//debug purpose
|
||||
QString sqlCommand() const;
|
||||
|
||||
Query<T> &setSqlCommand(const QString &command);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template<typename O>
|
||||
Q_OUTOFLINE_TEMPLATE QList<O> Query<T>::select(const std::function<O (const QSqlQuery &)> allocator)
|
||||
{
|
||||
//Q_D(AbstractQuery);
|
||||
QList<O> ret;
|
||||
|
||||
if (!d->hasCustomCommand) {
|
||||
d->joins.prepend(d->tableName);
|
||||
d->sql = d->database->sqlGenerator()->selectCommand(d->tableName,
|
||||
AbstractSqlGenerator::SingleField,
|
||||
|
|
@ -164,6 +175,8 @@ Q_OUTOFLINE_TEMPLATE QList<O> Query<T>::select(const std::function<O (const QSql
|
|||
d->skip,
|
||||
d->take);
|
||||
|
||||
printSql(d->sql);
|
||||
}
|
||||
QSqlQuery q = d->database->exec(d->sql);
|
||||
|
||||
while (q.next()) {
|
||||
|
|
@ -184,8 +197,6 @@ template <class T>
|
|||
Q_OUTOFLINE_TEMPLATE Query<T>::Query(Database *database, AbstractTableSet *tableSet)
|
||||
: d(new QueryData(database))
|
||||
{
|
||||
//Q_D(AbstractQuery);
|
||||
|
||||
d->database = database;
|
||||
d->tableSet = tableSet;
|
||||
d->className = QString::fromUtf8(T::staticMetaObject.className());
|
||||
|
|
@ -209,7 +220,6 @@ Q_OUTOFLINE_TEMPLATE Query<T>::Query(Query<T> &&other) {
|
|||
template <class T>
|
||||
Q_OUTOFLINE_TEMPLATE Query<T>::~Query()
|
||||
{
|
||||
//Q_D(AbstractQuery);
|
||||
delete d;
|
||||
}
|
||||
|
||||
|
|
@ -228,14 +238,19 @@ Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::operator=(const Query<T> &q)
|
|||
template <class T>
|
||||
Q_OUTOFLINE_TEMPLATE RowList<T> Query<T>::toList(int count)
|
||||
{
|
||||
//Q_D(AbstractQuery);
|
||||
RowList<T> returnList;
|
||||
d->select = QStringLiteral("*");
|
||||
|
||||
d->sql = d->database->sqlGenerator()->selectCommand(
|
||||
d->tableName, d->fieldPhrase, d->wherePhrase, d->orderPhrase,
|
||||
d->relations, d->skip, count);
|
||||
if (!d->hasCustomCommand)
|
||||
d->sql = d->database->sqlGenerator()->selectCommand(d->tableName,
|
||||
d->fieldPhrase,
|
||||
d->wherePhrase,
|
||||
d->orderPhrase,
|
||||
d->relations,
|
||||
d->skip,
|
||||
count);
|
||||
|
||||
printSql(d->sql);
|
||||
QSqlQuery q = d->database->exec(d->sql);
|
||||
if (q.lastError().isValid()) {
|
||||
qDebug() << q.lastError().text();
|
||||
|
|
@ -244,7 +259,7 @@ Q_OUTOFLINE_TEMPLATE RowList<T> Query<T>::toList(int count)
|
|||
|
||||
QSet<TableModel*> relatedTables;
|
||||
relatedTables << d->database->model().tableByName(d->tableName);
|
||||
Q_FOREACH (RelationModel *rel, d->relations)
|
||||
for (auto &rel: d->relations)
|
||||
relatedTables << rel->slaveTable << rel->masterTable;
|
||||
|
||||
struct LevelData{
|
||||
|
|
@ -271,7 +286,7 @@ Q_OUTOFLINE_TEMPLATE RowList<T> Query<T>::toList(int count)
|
|||
data.lastKeyValue = QVariant();
|
||||
|
||||
QHash<QString, QString> masters;
|
||||
Q_FOREACH (RelationModel *rel, d->relations)
|
||||
for (auto &rel: d->relations)
|
||||
if (rel->slaveTable->name() == table->name())
|
||||
masters.insert(rel->masterTable->name(), rel->localProperty);
|
||||
|
||||
|
|
@ -337,7 +352,7 @@ Q_OUTOFLINE_TEMPLATE RowList<T> Query<T>::toList(int count)
|
|||
}
|
||||
|
||||
// check if master if current table has processed
|
||||
Q_FOREACH (int m, data.masters)
|
||||
for (auto &m: data.masters)
|
||||
if (!checked[m]) {
|
||||
// qDebug() << "row is checked";
|
||||
continue;
|
||||
|
|
@ -350,7 +365,7 @@ Q_OUTOFLINE_TEMPLATE RowList<T> Query<T>::toList(int count)
|
|||
//create table row
|
||||
Row<Table> row;
|
||||
if (data.table->className() == d->className) {
|
||||
Row<T> tmpRow = Nut::create<T>();
|
||||
Row<T> tmpRow = create<T>();
|
||||
row = tmpRow.template objectCast<Table>();
|
||||
|
||||
row->init();
|
||||
|
|
@ -363,8 +378,13 @@ Q_OUTOFLINE_TEMPLATE RowList<T> Query<T>::toList(int count)
|
|||
|
||||
} else {
|
||||
Table *table;
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
auto childMetaObject = QMetaType(data.table->typeId()).metaObject();
|
||||
#else
|
||||
const QMetaObject *childMetaObject
|
||||
= QMetaType::metaObjectForType(data.table->typeId());
|
||||
#endif
|
||||
table = qobject_cast<Table *>(childMetaObject->newInstance());
|
||||
// table = dynamic_cast<Table *>(QMetaType::create(data.table->typeId()));
|
||||
if (!table)
|
||||
|
|
@ -374,7 +394,7 @@ Q_OUTOFLINE_TEMPLATE RowList<T> Query<T>::toList(int count)
|
|||
}
|
||||
|
||||
QList<FieldModel*> childFields = data.table->fields();
|
||||
Q_FOREACH (FieldModel *field, childFields)
|
||||
for (auto &field: childFields)
|
||||
row->setProperty(field->name.toLatin1().data(),
|
||||
d->database->sqlGenerator()->unescapeValue(
|
||||
field->type,
|
||||
|
|
@ -399,6 +419,8 @@ Q_OUTOFLINE_TEMPLATE RowList<T> Query<T>::toList(int count)
|
|||
Q_ARG(Nut::Row<Nut::Table>,
|
||||
levels[master].lastRow));
|
||||
|
||||
if (Q_UNLIKELY(!ok))
|
||||
qWarning("Unable to invoke method %s on object", qPrintable(setterName));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -419,17 +441,20 @@ template <typename T>
|
|||
template <typename F>
|
||||
Q_OUTOFLINE_TEMPLATE QList<F> Query<T>::select(const FieldPhrase<F> f)
|
||||
{
|
||||
//Q_D(AbstractQuery);
|
||||
QList<F> ret;
|
||||
|
||||
if (!d->hasCustomCommand) {
|
||||
d->joins.prepend(d->tableName);
|
||||
d->sql = d->database->sqlGenerator()->selectCommand(
|
||||
d->tableName,
|
||||
AbstractSqlGenerator::SingleField, f.data->toString(),
|
||||
d->sql = d->database->sqlGenerator()->selectCommand(d->tableName,
|
||||
AbstractSqlGenerator::SingleField,
|
||||
f.data->toString(),
|
||||
d->wherePhrase,
|
||||
d->relations,
|
||||
d->skip, d->take);
|
||||
d->skip,
|
||||
d->take);
|
||||
|
||||
printSql(d->sql);
|
||||
}
|
||||
QSqlQuery q = d->database->exec(d->sql);
|
||||
|
||||
while (q.next()) {
|
||||
|
|
@ -455,16 +480,16 @@ Q_OUTOFLINE_TEMPLATE Row<T> Query<T>::first()
|
|||
template <class T>
|
||||
Q_OUTOFLINE_TEMPLATE int Query<T>::count()
|
||||
{
|
||||
//Q_D(AbstractQuery);
|
||||
|
||||
if (!d->hasCustomCommand) {
|
||||
d->joins.prepend(d->tableName);
|
||||
d->select = QStringLiteral("COUNT(*)");
|
||||
d->sql = d->database->sqlGenerator()->selectCommand(
|
||||
d->tableName,
|
||||
d->sql = d->database->sqlGenerator()->selectCommand(d->tableName,
|
||||
AbstractSqlGenerator::Count,
|
||||
QStringLiteral("*"),
|
||||
d->wherePhrase,
|
||||
d->relations);
|
||||
printSql(d->sql);
|
||||
}
|
||||
QSqlQuery q = d->database->exec(d->sql);
|
||||
|
||||
if (q.next())
|
||||
|
|
@ -475,14 +500,15 @@ Q_OUTOFLINE_TEMPLATE int Query<T>::count()
|
|||
template <class T>
|
||||
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::max(const FieldPhrase<int> &f)
|
||||
{
|
||||
//Q_D(AbstractQuery);
|
||||
|
||||
if (!d->hasCustomCommand) {
|
||||
d->joins.prepend(d->tableName);
|
||||
d->sql = d->database->sqlGenerator()->selectCommand(
|
||||
d->tableName,
|
||||
AbstractSqlGenerator::Max, f.data->toString(),
|
||||
d->sql = d->database->sqlGenerator()->selectCommand(d->tableName,
|
||||
AbstractSqlGenerator::Max,
|
||||
f.data->toString(),
|
||||
d->wherePhrase,
|
||||
d->relations);
|
||||
printSql(d->sql);
|
||||
}
|
||||
QSqlQuery q = d->database->exec(d->sql);
|
||||
|
||||
if (q.next())
|
||||
|
|
@ -493,14 +519,15 @@ Q_OUTOFLINE_TEMPLATE QVariant Query<T>::max(const FieldPhrase<int> &f)
|
|||
template <class T>
|
||||
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::min(const FieldPhrase<int> &f)
|
||||
{
|
||||
//Q_D(AbstractQuery);
|
||||
|
||||
if (!d->hasCustomCommand) {
|
||||
d->joins.prepend(d->tableName);
|
||||
d->sql = d->database->sqlGenerator()->selectCommand(
|
||||
d->tableName,
|
||||
AbstractSqlGenerator::Min, f.data->toString(),
|
||||
d->sql = d->database->sqlGenerator()->selectCommand(d->tableName,
|
||||
AbstractSqlGenerator::Min,
|
||||
f.data->toString(),
|
||||
d->wherePhrase,
|
||||
d->relations);
|
||||
printSql(d->sql);
|
||||
}
|
||||
QSqlQuery q = d->database->exec(d->sql);
|
||||
|
||||
if (q.next())
|
||||
|
|
@ -511,14 +538,15 @@ Q_OUTOFLINE_TEMPLATE QVariant Query<T>::min(const FieldPhrase<int> &f)
|
|||
template <class T>
|
||||
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::sum(const FieldPhrase<int> &f)
|
||||
{
|
||||
//Q_D(AbstractQuery);
|
||||
|
||||
if (!d->hasCustomCommand) {
|
||||
d->joins.prepend(d->tableName);
|
||||
d->sql = d->database->sqlGenerator()->selectCommand(
|
||||
d->tableName,
|
||||
AbstractSqlGenerator::Sum, f.data->toString(),
|
||||
d->sql = d->database->sqlGenerator()->selectCommand(d->tableName,
|
||||
AbstractSqlGenerator::Sum,
|
||||
f.data->toString(),
|
||||
d->wherePhrase,
|
||||
d->relations);
|
||||
printSql(d->sql);
|
||||
}
|
||||
QSqlQuery q = d->database->exec(d->sql);
|
||||
|
||||
if (q.next())
|
||||
|
|
@ -529,14 +557,15 @@ Q_OUTOFLINE_TEMPLATE QVariant Query<T>::sum(const FieldPhrase<int> &f)
|
|||
template <class T>
|
||||
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::average(const FieldPhrase<int> &f)
|
||||
{
|
||||
//Q_D(AbstractQuery);
|
||||
|
||||
if (!d->hasCustomCommand) {
|
||||
d->joins.prepend(d->tableName);
|
||||
d->sql = d->database->sqlGenerator()->selectCommand(
|
||||
d->tableName,
|
||||
AbstractSqlGenerator::Average, f.data->toString(),
|
||||
d->sql = d->database->sqlGenerator()->selectCommand(d->tableName,
|
||||
AbstractSqlGenerator::Average,
|
||||
f.data->toString(),
|
||||
d->wherePhrase,
|
||||
d->relations);
|
||||
printSql(d->sql);
|
||||
}
|
||||
QSqlQuery q = d->database->exec(d->sql);
|
||||
|
||||
if (q.next())
|
||||
|
|
@ -547,9 +576,10 @@ Q_OUTOFLINE_TEMPLATE QVariant Query<T>::average(const FieldPhrase<int> &f)
|
|||
template<class T>
|
||||
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::insert(const AssignmentPhraseList &p)
|
||||
{
|
||||
//Q_D(AbstractQuery);
|
||||
d->sql = d->database->sqlGenerator()
|
||||
->insertCommand(d->tableName, p);
|
||||
if (!d->hasCustomCommand) {
|
||||
d->sql = d->database->sqlGenerator()->insertCommand(d->tableName, p);
|
||||
printSql(d->sql);
|
||||
}
|
||||
QSqlQuery q = d->database->exec(d->sql);
|
||||
|
||||
return q.lastInsertId();
|
||||
|
|
@ -558,8 +588,6 @@ Q_OUTOFLINE_TEMPLATE QVariant Query<T>::insert(const AssignmentPhraseList &p)
|
|||
template <class T>
|
||||
Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::join(const QString &className)
|
||||
{
|
||||
//Q_D(AbstractQuery);
|
||||
|
||||
RelationModel *rel = d->database->model()
|
||||
.relationByClassNames(d->className, className);
|
||||
if (!rel)
|
||||
|
|
@ -587,7 +615,6 @@ Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::join(Table *c)
|
|||
template <class T>
|
||||
Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::where(const ConditionalPhrase &ph)
|
||||
{
|
||||
//Q_D(AbstractQuery);
|
||||
if (d->wherePhrase.data)
|
||||
d->wherePhrase = d->wherePhrase && ph;
|
||||
else
|
||||
|
|
@ -598,7 +625,6 @@ Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::where(const ConditionalPhrase &ph)
|
|||
template <class T>
|
||||
Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::setWhere(const ConditionalPhrase &ph)
|
||||
{
|
||||
//Q_D(AbstractQuery);
|
||||
d->wherePhrase = ph;
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -606,7 +632,6 @@ Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::setWhere(const ConditionalPhrase &ph)
|
|||
template<class T>
|
||||
Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::skip(int n)
|
||||
{
|
||||
//Q_D(AbstractQuery);
|
||||
d->skip = n;
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -614,7 +639,6 @@ Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::skip(int n)
|
|||
template<class T>
|
||||
Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::take(int n)
|
||||
{
|
||||
//Q_D(AbstractQuery);
|
||||
d->take = n;
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -622,24 +646,13 @@ Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::take(int n)
|
|||
template<class T>
|
||||
Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::fields(const PhraseList &ph)
|
||||
{
|
||||
//Q_D(AbstractQuery);
|
||||
d->fieldPhrase = ph;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//template <class T>
|
||||
//Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::orderBy(QString fieldName,
|
||||
// QString type)
|
||||
//{
|
||||
// //Q_D(AbstractQuery);
|
||||
// d->orderPhrases.append(fieldName, type);
|
||||
// return *this;
|
||||
//}
|
||||
|
||||
template <class T>
|
||||
Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::orderBy(const PhraseList &ph)
|
||||
{
|
||||
//Q_D(AbstractQuery);
|
||||
d->orderPhrase = ph;
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -647,13 +660,10 @@ Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::orderBy(const PhraseList &ph)
|
|||
template <class T>
|
||||
Q_OUTOFLINE_TEMPLATE int Query<T>::update(const AssignmentPhraseList &ph)
|
||||
{
|
||||
//Q_D(AbstractQuery);
|
||||
|
||||
d->sql = d->database->sqlGenerator()->updateCommand(
|
||||
d->tableName,
|
||||
ph,
|
||||
d->wherePhrase);
|
||||
|
||||
if (!d->hasCustomCommand) {
|
||||
d->sql = d->database->sqlGenerator()->updateCommand(d->tableName, ph, d->wherePhrase);
|
||||
printSql(d->sql);
|
||||
}
|
||||
QSqlQuery q = d->database->exec(d->sql);
|
||||
|
||||
return q.numRowsAffected();
|
||||
|
|
@ -662,10 +672,10 @@ Q_OUTOFLINE_TEMPLATE int Query<T>::update(const AssignmentPhraseList &ph)
|
|||
template <class T>
|
||||
Q_OUTOFLINE_TEMPLATE int Query<T>::remove()
|
||||
{
|
||||
//Q_D(AbstractQuery);
|
||||
|
||||
d->sql = d->database->sqlGenerator()->deleteCommand(
|
||||
d->tableName, d->wherePhrase);
|
||||
if (!d->hasCustomCommand) {
|
||||
d->sql = d->database->sqlGenerator()->deleteCommand(d->tableName, d->wherePhrase);
|
||||
printSql(d->sql);
|
||||
}
|
||||
QSqlQuery q = d->database->exec(d->sql);
|
||||
|
||||
return q.numRowsAffected();
|
||||
|
|
@ -682,36 +692,33 @@ Q_OUTOFLINE_TEMPLATE QSqlQueryModel *Query<T>::toModel()
|
|||
template <class T>
|
||||
Q_OUTOFLINE_TEMPLATE void Query<T>::toModel(QSqlQueryModel *model)
|
||||
{
|
||||
//Q_D(AbstractQuery);
|
||||
|
||||
d->sql = d->database->sqlGenerator()->selectCommand(
|
||||
d->tableName,
|
||||
if (!d->hasCustomCommand) {
|
||||
d->sql = d->database->sqlGenerator()->selectCommand(d->tableName,
|
||||
d->fieldPhrase,
|
||||
d->wherePhrase, d->orderPhrase, d->relations,
|
||||
d->skip, d->take);
|
||||
|
||||
d->wherePhrase,
|
||||
d->orderPhrase,
|
||||
d->relations,
|
||||
d->skip,
|
||||
d->take);
|
||||
printSql(d->sql);
|
||||
}
|
||||
DatabaseModel dbModel = d->database->model();
|
||||
model->setQuery(d->sql, d->database->database());
|
||||
|
||||
int fieldIndex = 0;
|
||||
|
||||
if (d->fieldPhrase.data.count()) {
|
||||
Q_FOREACH (const PhraseData *pd, d->fieldPhrase.data) {
|
||||
QString displayName = dbModel
|
||||
.tableByClassName(QString::fromUtf8(pd->className))
|
||||
for (const auto &pd : qAsConst(d->fieldPhrase.data)) {
|
||||
QString displayName = dbModel.tableByClassName(QString::fromUtf8(pd->className))
|
||||
->field(QString::fromUtf8(pd->fieldName))
|
||||
->displayName;
|
||||
|
||||
model->setHeaderData(fieldIndex++,
|
||||
Qt::Horizontal,
|
||||
displayName);
|
||||
model->setHeaderData(fieldIndex++, Qt::Horizontal, displayName);
|
||||
}
|
||||
} else {
|
||||
TableModel *tbl = d->database->model().tableByName(d->tableName);
|
||||
Q_FOREACH (FieldModel *f, tbl->fields()) {
|
||||
model->setHeaderData(fieldIndex++,
|
||||
Qt::Horizontal,
|
||||
f->displayName);
|
||||
for (auto &f : tbl->fields()) {
|
||||
model->setHeaderData(fieldIndex++, Qt::Horizontal, f->displayName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -719,38 +726,15 @@ Q_OUTOFLINE_TEMPLATE void Query<T>::toModel(QSqlQueryModel *model)
|
|||
template<class T>
|
||||
Q_OUTOFLINE_TEMPLATE void Query<T>::toModel(SqlModel *model)
|
||||
{
|
||||
//Q_D(AbstractQuery);
|
||||
|
||||
d->sql = d->database->sqlGenerator()->selectCommand(
|
||||
d->tableName,
|
||||
d->fieldPhrase,
|
||||
d->wherePhrase, d->orderPhrase, d->relations,
|
||||
d->skip, d->take);
|
||||
|
||||
printSql(d->sql);
|
||||
|
||||
model->setTable(toList());
|
||||
/*
|
||||
DatabaseModel dbModel = d->database->model();
|
||||
model->setQuery(d->sql, d->database->database());
|
||||
|
||||
int fieldIndex = 0;
|
||||
|
||||
if (d->fieldPhrase.data.count()) {
|
||||
Q_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);
|
||||
Q_FOREACH (FieldModel *f, tbl->fields()) {
|
||||
model->setHeaderData(fieldIndex++,
|
||||
Qt::Horizontal,
|
||||
f->displayName);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
template <class T>
|
||||
|
|
@ -760,15 +744,15 @@ Q_OUTOFLINE_TEMPLATE QString Query<T>::sqlCommand() const
|
|||
return d->sql;
|
||||
}
|
||||
|
||||
//TODO: complete this class later
|
||||
//class RawQuery : public Query<void>
|
||||
//{
|
||||
//public:
|
||||
// void setRawCommand(const QString &sql) {
|
||||
|
||||
// }
|
||||
//};
|
||||
template<class T>
|
||||
Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::setSqlCommand(const QString &command)
|
||||
{
|
||||
d->hasCustomCommand = true;
|
||||
d->sql = command;
|
||||
}
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // NUT_QUERY_H
|
||||
|
|
|
|||
|
|
@ -0,0 +1,694 @@
|
|||
/**************************************************************************
|
||||
**
|
||||
** 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 "sqlserializer.h"
|
||||
|
||||
#include <QtCore/QUuid>
|
||||
#include <QtCore/QPoint>
|
||||
#include <QtCore/QPointF>
|
||||
#include <QtCore/QSizeF>
|
||||
#include <QtCore/QSize>
|
||||
#include <QtCore/QRect>
|
||||
#include <QtCore/QRectF>
|
||||
#include <QtCore/QDate>
|
||||
#include <QtCore/QTime>
|
||||
#include <QtCore/QDateTime>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QUrl>
|
||||
#include <QtCore/QLineF>
|
||||
#include <QtCore/QJsonDocument>
|
||||
#include <QtCore/QJsonArray>
|
||||
#include <QtCore/QJsonObject>
|
||||
#include <QtCore/QBitArray>
|
||||
#include <QtCore/QBuffer>
|
||||
#include "nut_p.h"
|
||||
#include "nut_global.h"
|
||||
|
||||
#ifdef QT_GUI_LIB
|
||||
#include <QtGui/QFont>
|
||||
#include <QtGui/QPolygon>
|
||||
#include <QtGui/QPolygonF>
|
||||
#include <QtGui/QColor>
|
||||
#include <QtGui/QImage>
|
||||
#include <QtGui/QVector2D>
|
||||
#include <QtGui/QVector3D>
|
||||
#include <QtGui/QVector4D>
|
||||
#endif
|
||||
|
||||
#define DATE_FORMAT QStringLiteral("yyyy-MM-dd")
|
||||
#define TIME_FORMAT QStringLiteral("HH:mm:ss.zzz")
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
SqlSerializer::SqlSerializer()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
SqlSerializer::~SqlSerializer()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QVariant SqlSerializer::fromString(const QString &value, const QMetaType::Type &type) const
|
||||
{
|
||||
switch (type) {
|
||||
case QMetaType::Bool: return !value.compare(QStringLiteral("true"), Qt::CaseInsensitive) || value == QStringLiteral("1");
|
||||
case QMetaType::Char:
|
||||
case QMetaType::SChar:
|
||||
case QMetaType::Int: return value.toInt();
|
||||
case QMetaType::UChar:
|
||||
case QMetaType::UInt: return value.toUInt();
|
||||
case QMetaType::Short: return value.toShort();
|
||||
case QMetaType::UShort: return value.toUShort();
|
||||
case QMetaType::Long: return QVariant::fromValue(value.toLong());
|
||||
case QMetaType::ULong: return QVariant::fromValue(value.toULong());
|
||||
case QMetaType::LongLong: return value.toLongLong();
|
||||
case QMetaType::ULongLong: return QVariant::fromValue(value.toULongLong());
|
||||
case QMetaType::Float: return value.toFloat();
|
||||
case QMetaType::Double: return value.toDouble();
|
||||
case QMetaType::QString: return unescapeString(value);
|
||||
case QMetaType::QDate: return QDate::fromString(value, DATE_FORMAT);
|
||||
case QMetaType::QTime: return QTime::fromString(value, TIME_FORMAT);
|
||||
case QMetaType::QDateTime: return QDateTime::fromString(value, DATE_FORMAT + QStringLiteral(" ") + TIME_FORMAT);
|
||||
case QMetaType::QUrl: return QUrl(value);
|
||||
case QMetaType::QChar: return value.at(0);
|
||||
case QMetaType::QStringList: {
|
||||
QStringList ret;
|
||||
QString copy(value);
|
||||
QString out;
|
||||
|
||||
while (readString(copy, out) )
|
||||
ret.append(out);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
case QMetaType::QPoint: {
|
||||
QList<int> parts = toListInt(value);
|
||||
if (parts.size() != 2)
|
||||
return QPoint();
|
||||
|
||||
return QPoint(parts.at(0), parts.at(1));
|
||||
}
|
||||
case QMetaType::QSize: {
|
||||
QList<int> parts = toListInt(value);
|
||||
if (parts.size() != 2)
|
||||
return QSize();
|
||||
|
||||
return QSize(parts.at(0), parts.at(1));
|
||||
}
|
||||
case QMetaType::QRect: {
|
||||
QList<int> parts = toListInt(value);
|
||||
if (parts.size() != 4)
|
||||
return QRect();
|
||||
|
||||
return QRect(parts.at(0), parts.at(1), parts.at(2), parts.at(3));
|
||||
}
|
||||
case QMetaType::QLine: {
|
||||
QList<int> parts = toListInt(value);
|
||||
if (parts.size() != 4)
|
||||
return QLine();
|
||||
|
||||
return QLine(parts.at(0), parts.at(1), parts.at(2), parts.at(3));
|
||||
}
|
||||
case QMetaType::QPointF: {
|
||||
QList<qreal> parts = toListReal(value);
|
||||
if (parts.size() != 2)
|
||||
return QPointF();
|
||||
|
||||
return QPointF(parts.at(0), parts.at(1));
|
||||
}
|
||||
case QMetaType::QSizeF: {
|
||||
QList<qreal> parts = toListReal(value);
|
||||
if (parts.size() != 2)
|
||||
return QSizeF();
|
||||
|
||||
return QSizeF(parts.at(0), parts.at(1));
|
||||
}
|
||||
case QMetaType::QRectF: {
|
||||
QList<qreal> parts = toListReal(value);
|
||||
if (parts.size() != 4)
|
||||
return QRectF();
|
||||
|
||||
return QRectF(parts.at(0), parts.at(1), parts.at(2), parts.at(3));
|
||||
}
|
||||
case QMetaType::QLineF: {
|
||||
QList<qreal> parts = toListReal(value);
|
||||
if (parts.size() != 4)
|
||||
return QLineF();
|
||||
|
||||
return QLineF(parts.at(0), parts.at(1), parts.at(2), parts.at(3));
|
||||
}
|
||||
|
||||
case QMetaType::QUuid:
|
||||
return QUuid(value);
|
||||
|
||||
case QMetaType::QByteArray:
|
||||
return value.toUtf8();
|
||||
|
||||
case QMetaType::QJsonDocument:
|
||||
return QJsonDocument::fromJson(value.toUtf8());
|
||||
|
||||
case QMetaType::QJsonObject:
|
||||
return QJsonDocument::fromJson(value.toUtf8()).object();
|
||||
|
||||
case QMetaType::QJsonArray:
|
||||
return QJsonDocument::fromJson(value.toUtf8()).array();
|
||||
|
||||
case QMetaType::QJsonValue: {
|
||||
if (value == QStringLiteral("true"))
|
||||
return QJsonValue(true);
|
||||
else if (value == QStringLiteral("false"))
|
||||
return QJsonValue(false);
|
||||
bool ok;
|
||||
int n = value.toInt(&ok);
|
||||
if (ok)
|
||||
return QJsonValue(n);
|
||||
|
||||
double d = value.toDouble(&ok);
|
||||
if (ok)
|
||||
return QJsonValue(d);
|
||||
|
||||
return QJsonValue(value);
|
||||
}
|
||||
|
||||
case QMetaType::QBitArray: {
|
||||
QBitArray bita(value.size());
|
||||
for (int i = 0; i < value.size(); ++i) {
|
||||
if (value.at(i) == QStringLiteral("0"))
|
||||
bita.setBit(i, false);
|
||||
else
|
||||
bita.setBit(i, true);
|
||||
}
|
||||
return bita;
|
||||
}
|
||||
|
||||
case QMetaType::QVariantMap: {
|
||||
QVariantMap ret;
|
||||
QStringList parts = value.split(QStringLiteral("\n"));
|
||||
for (auto &p: parts) {
|
||||
if (p.isEmpty())
|
||||
continue;
|
||||
QString name;
|
||||
QString value;
|
||||
if (readString(p, name) && readString(p, value))
|
||||
ret.insert(name, value);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
case QMetaType::QVariantList: {
|
||||
QVariantMap ret;
|
||||
QStringList parts = value.split(QStringLiteral("\n"));
|
||||
for (auto &p: parts) {
|
||||
if (p.isEmpty())
|
||||
continue;
|
||||
QString name;
|
||||
QString value;
|
||||
if (readString(p, name) && readString(p, value))
|
||||
ret.insert(name, value);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef QT_GUI_LIB
|
||||
case QMetaType::QVector2D: {
|
||||
QList<float> parts = toListFloat(value);
|
||||
if (parts.size() != 2)
|
||||
return QVector2D();
|
||||
|
||||
return QVector2D(parts.at(0), parts.at(1));
|
||||
}
|
||||
case QMetaType::QVector3D: {
|
||||
QList<float> parts = toListFloat(value);
|
||||
if (parts.size() != 3)
|
||||
return QVector3D();
|
||||
|
||||
return QVector3D(parts.at(0), parts.at(1), parts.at(2));
|
||||
}
|
||||
case QMetaType::QVector4D: {
|
||||
QList<float> parts = toListFloat(value);
|
||||
if (parts.size() != 4)
|
||||
return QVector4D();
|
||||
|
||||
return QVector4D(parts.at(0), parts.at(1), parts.at(2), parts.at(3));
|
||||
}
|
||||
|
||||
case QMetaType::QImage: {
|
||||
QImage image;
|
||||
image.loadFromData(QByteArray::fromBase64(value.toLocal8Bit()));
|
||||
return image;
|
||||
}
|
||||
|
||||
case QMetaType::QColor:
|
||||
return QColor(value);
|
||||
|
||||
case QMetaType::QPolygon: {
|
||||
QStringList parts = value.split(QStringLiteral(" "));
|
||||
QPolygon pol;
|
||||
for (int i = 0; i < parts.count(); i++)
|
||||
pol.append(fromString(parts.at(i), QMetaType::QPoint).toPoint());
|
||||
return pol;
|
||||
}
|
||||
case QMetaType::QPolygonF: {
|
||||
QStringList parts = value.split(QStringLiteral(" "));
|
||||
QPolygonF pol;
|
||||
for (int i = 0; i < parts.count(); i++)
|
||||
pol.append(fromString(parts.at(i), QMetaType::QPointF).toPointF());
|
||||
return pol;
|
||||
}
|
||||
case QMetaType::QFont: {
|
||||
QFont f;
|
||||
f.fromString(value);
|
||||
return f;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
QString SqlSerializer::toString(const QVariant &value) const
|
||||
{
|
||||
auto type = METATYPE_ID(value);
|
||||
switch (type) {
|
||||
case QMetaType::Bool:
|
||||
case QMetaType::Char:
|
||||
case QMetaType::Short:
|
||||
case QMetaType::UShort:
|
||||
case QMetaType::Int:
|
||||
case QMetaType::UInt:
|
||||
case QMetaType::Long:
|
||||
case QMetaType::ULong:
|
||||
case QMetaType::LongLong:
|
||||
case QMetaType::ULongLong:
|
||||
case QMetaType::Double:
|
||||
case QMetaType::Float:
|
||||
case QMetaType::QChar:
|
||||
case QMetaType::QUrl:
|
||||
return value.toString();
|
||||
|
||||
case QMetaType::UChar:
|
||||
case QMetaType::SChar:
|
||||
return QString::number(value.toInt());
|
||||
|
||||
case QMetaType::QString:
|
||||
return value.toString();
|
||||
|
||||
case QMetaType::QStringList: {
|
||||
QString ret;
|
||||
QStringList sl = value.toStringList();
|
||||
for (auto &s: sl) {
|
||||
if (!ret.isEmpty())
|
||||
ret.append(QStringLiteral(" "));
|
||||
|
||||
ret.append(QStringLiteral("\"") + escapeString(s) + QStringLiteral("\""));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
case QMetaType::QUuid:
|
||||
return value.toUuid().toString();
|
||||
|
||||
case QMetaType::QByteArray:
|
||||
return QString::fromUtf8(value.toByteArray());
|
||||
|
||||
case QMetaType::QDate: return value.toDate().toString(DATE_FORMAT);
|
||||
case QMetaType::QTime: return value.toTime().toString(TIME_FORMAT);
|
||||
case QMetaType::QDateTime: return value.toDateTime().toString(DATE_FORMAT + QStringLiteral(" ") + TIME_FORMAT);
|
||||
|
||||
case QMetaType::QPoint: {
|
||||
QPoint pt = value.toPoint();
|
||||
return fromVariantList({pt.x(), pt.y()});
|
||||
}
|
||||
case QMetaType::QPointF: {
|
||||
QPointF pt = value.toPointF();
|
||||
return fromVariantList({pt.x(), pt.y()});
|
||||
}
|
||||
case QMetaType::QSize: {
|
||||
QSize pt = value.toSize();
|
||||
return fromVariantList({pt.width(), pt.height()});
|
||||
}
|
||||
case QMetaType::QSizeF: {
|
||||
QSizeF pt = value.toSizeF();
|
||||
return fromVariantList({pt.width(), pt.height()});
|
||||
}
|
||||
case QMetaType::QRect: {
|
||||
QRect rc = value.toRect();
|
||||
return fromVariantList({rc.x(), rc.y(), rc.width(), rc.height()});
|
||||
}
|
||||
case QMetaType::QRectF: {
|
||||
QRectF rc = value.toRectF();
|
||||
return fromVariantList({rc.x(), rc.y(), rc.width(), rc.height()});
|
||||
}
|
||||
case QMetaType::QLine: {
|
||||
QLine rc = value.toLine();
|
||||
return fromVariantList({rc.x1(), rc.y1(), rc.x2(), rc.y2()});
|
||||
}
|
||||
case QMetaType::QLineF: {
|
||||
QLineF rc = value.toLineF();
|
||||
return fromVariantList({rc.x1(), rc.y1(), rc.x2(), rc.y2()});
|
||||
}
|
||||
case QMetaType::QJsonDocument:
|
||||
return QString::fromUtf8(value.toJsonDocument().toJson(QJsonDocument::Compact));
|
||||
|
||||
case QMetaType::QJsonObject: {
|
||||
QJsonDocument doc;
|
||||
doc.setObject(value.toJsonObject());
|
||||
return QString::fromUtf8(doc.toJson(QJsonDocument::Compact));
|
||||
}
|
||||
|
||||
case QMetaType::QJsonArray: {
|
||||
QJsonDocument doc;
|
||||
doc.setArray(value.toJsonArray());
|
||||
return QString::fromUtf8(doc.toJson(QJsonDocument::Compact));
|
||||
}
|
||||
|
||||
case QMetaType::QJsonValue:
|
||||
return value.toJsonValue().toVariant().toString();
|
||||
|
||||
case QMetaType::QBitArray: {
|
||||
QString ret;
|
||||
QBitArray bita = value.toBitArray();
|
||||
for (int i = 0; i < bita.size(); ++i)
|
||||
ret.append(bita.at(i) ? QStringLiteral("1") : QStringLiteral("0"));
|
||||
return ret;
|
||||
}
|
||||
case QMetaType::QVariantMap: {
|
||||
QString ret;
|
||||
QVariantMap map = value.toMap();
|
||||
for (auto i = map.begin(); i != map.end(); ++i) {
|
||||
if (!ret.isEmpty())
|
||||
ret.append(QStringLiteral("\n"));
|
||||
QVariant v = map.value(i.key());
|
||||
QString str = toString(v);
|
||||
ret.append(QStringLiteral("\"%1\" \"%2\"")
|
||||
.arg(escapeString(i.key()), escapeString(str)));
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef QT_GUI_LIB
|
||||
case QMetaType::QVector2D: {
|
||||
QVector2D vec = value.value<QVector2D>();
|
||||
return fromList(QList<float>() << vec.x() << vec.y());
|
||||
}
|
||||
case QMetaType::QVector3D: {
|
||||
QVector3D vec = value.value<QVector3D>();
|
||||
return fromList(QList<float>() << vec.x() << vec.y() << vec.z());
|
||||
}
|
||||
case QMetaType::QVector4D: {
|
||||
QVector4D vec = value.value<QVector4D>();
|
||||
return fromList(QList<float>() << vec.x() << vec.y() << vec.z() << vec.w());
|
||||
}
|
||||
|
||||
case QMetaType::QImage: {
|
||||
QImage image = value.value<QImage>();
|
||||
QByteArray byteArray;
|
||||
QBuffer buffer(&byteArray);
|
||||
image.save(&buffer, "PNG");
|
||||
QString base64 = QString::fromLatin1(byteArray.toBase64().data());
|
||||
return base64;
|
||||
}
|
||||
|
||||
case QMetaType::QColor:
|
||||
return value.value<QColor>().name();
|
||||
|
||||
case QMetaType::QPolygon: {
|
||||
QStringList list;
|
||||
QPolygon pol = value.value<QPolygon>();
|
||||
QPoint pt;
|
||||
for (int i = 0; i < pol.size(); ++i) {
|
||||
pt = pol.at(i);
|
||||
list.append(toString(pt));
|
||||
}
|
||||
|
||||
return list.join(QStringLiteral(" "));
|
||||
}
|
||||
case QMetaType::QPolygonF: {
|
||||
QStringList list;
|
||||
QPolygonF pol = value.value<QPolygonF>();
|
||||
QPointF pt;
|
||||
for (int i = 0; i < pol.size(); ++i) {
|
||||
pt = pol.at(i);
|
||||
list.append(toString(pt));
|
||||
}
|
||||
|
||||
return list.join(QStringLiteral(" "));
|
||||
}
|
||||
case QMetaType::QFont:
|
||||
return value.value<QFont>().toString();
|
||||
#endif
|
||||
|
||||
case QMetaType::QVariantList: {
|
||||
auto l = value.toList();
|
||||
QString ret;
|
||||
|
||||
for (auto &v: l) {
|
||||
if (!ret.isEmpty())
|
||||
ret.append(QStringLiteral(", "));
|
||||
ret.append(toString(v));
|
||||
}
|
||||
|
||||
return QStringLiteral("(") + ret + QStringLiteral(")");
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
qWarning("The type (%s) does not supported",
|
||||
METATYPE_TO_NAME(type));
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
||||
QList<int> SqlSerializer::toListInt(const QString &s) const
|
||||
{
|
||||
return toListInt(s, QStringLiteral(","));
|
||||
}
|
||||
|
||||
QList<int> SqlSerializer::toListInt(const QString &s, const QString &sep) const
|
||||
{
|
||||
auto parts = s.split(sep);
|
||||
QList<int> ret;
|
||||
for (auto &p: parts) {
|
||||
bool ok;
|
||||
ret.append(p.toInt(&ok));
|
||||
if (!ok)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QList<qreal> SqlSerializer::toListReal(const QString &s) const
|
||||
{
|
||||
return toListReal(s, QStringLiteral(","));
|
||||
}
|
||||
|
||||
QString SqlSerializer::fromList(const QList<int> &list) const
|
||||
{
|
||||
QString ret;
|
||||
for (auto &n: list) {
|
||||
if (!ret.isEmpty())
|
||||
ret.append(QStringLiteral(","));
|
||||
ret.append(QString::number(n));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
QList<qreal> SqlSerializer::toListReal(const QString &s, const QString &sep) const
|
||||
{
|
||||
auto parts = s.split(sep);
|
||||
QList<qreal> ret;
|
||||
for (auto &p: parts) {
|
||||
bool ok;
|
||||
ret.append(p.toDouble(&ok));
|
||||
if (!ok)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QList<float> SqlSerializer::toListFloat(const QString &s) const
|
||||
{
|
||||
auto parts = s.split(QStringLiteral(","));
|
||||
QList<float> ret;
|
||||
for (auto &p: parts) {
|
||||
bool ok;
|
||||
ret.append(p.toFloat(&ok));
|
||||
if (!ok)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString SqlSerializer::fromList(const QList<qreal> &list) const
|
||||
{
|
||||
QString ret;
|
||||
for (auto &n: list) {
|
||||
if (!ret.isEmpty())
|
||||
ret.append(QStringLiteral(","));
|
||||
ret.append(QString::number(n, 'f', -1));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString SqlSerializer::fromList(const QList<float> &list) const
|
||||
{
|
||||
QString ret;
|
||||
for (auto &n: list) {
|
||||
if (!ret.isEmpty())
|
||||
ret.append(QStringLiteral(","));
|
||||
ret.append(QString::number(static_cast<double>(n)));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString SqlSerializer::fromVariantList(const QVariantList &list) const
|
||||
{
|
||||
QString ret;
|
||||
for (auto &n: list) {
|
||||
if (!ret.isEmpty())
|
||||
ret.append(QStringLiteral(","));
|
||||
ret.append(n.toString());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define CASE_W(o, r) \
|
||||
case o: \
|
||||
ret.append(QStringLiteral(r)); \
|
||||
break;
|
||||
QString SqlSerializer::escapeString(const QString &str) const
|
||||
{
|
||||
// QString ret;
|
||||
// for (int i = 0; i < str.length(); ++i) {
|
||||
// switch (str.at(i).cell()) {
|
||||
// CASE_W('\\', "\\\\")
|
||||
// CASE_W('\r', "\\r")
|
||||
// CASE_W('\n', "\\n")
|
||||
// CASE_W('\a', "\\a")
|
||||
// CASE_W('\b', "\\b")
|
||||
// CASE_W('\f', "\\f")
|
||||
// // CASE_W('\'', "\\'")
|
||||
// CASE_W('\t', "\\t")
|
||||
// CASE_W('\v', "\\v")
|
||||
// CASE_W('\"', "\\\"")
|
||||
|
||||
// default:
|
||||
// ret.append(str.at(i));
|
||||
// }
|
||||
// }
|
||||
// return ret;
|
||||
QString ret(str);
|
||||
return ret.replace(QStringLiteral("'"), QStringLiteral("''"));
|
||||
}
|
||||
|
||||
QString SqlSerializer::unescapeString(const QString &str) const
|
||||
{
|
||||
// QString ret;
|
||||
// for (int i = 0; i < str.length(); ++i) {
|
||||
// if (str.at(i) == '\\' && str.length() > i) {
|
||||
// switch (str.at(++i).cell()) {
|
||||
// case '\\':
|
||||
// ret.append(QStringLiteral("\\"));
|
||||
// break;
|
||||
// case 'r':
|
||||
// ret.append(QStringLiteral("\r"));
|
||||
// break;
|
||||
// case 'n':
|
||||
// ret.append(QStringLiteral("\n"));
|
||||
// break;
|
||||
// case 'a':
|
||||
// ret.append(QStringLiteral("\a"));
|
||||
// break;
|
||||
// case 'b':
|
||||
// ret.append(QStringLiteral("b"));
|
||||
// break;
|
||||
// case 'f':
|
||||
// ret.append(QStringLiteral("\f"));
|
||||
// break;
|
||||
// // case '\'':
|
||||
// // ret.append(QStringLiteral("\\'"));
|
||||
// // break;
|
||||
// case 't':
|
||||
// ret.append(QStringLiteral("\t"));
|
||||
// break;
|
||||
// case 'v':
|
||||
// ret.append(QStringLiteral("\v"));
|
||||
// break;
|
||||
// case '"':
|
||||
// ret.append(QStringLiteral("\\\""));
|
||||
// break;
|
||||
|
||||
// default:
|
||||
// ret.append(str.at(i));
|
||||
// }
|
||||
// } else {
|
||||
// ret.append(str.at(i));
|
||||
// }
|
||||
// }
|
||||
|
||||
// return ret;
|
||||
QString ret(str);
|
||||
return ret.replace(QStringLiteral("''"), QStringLiteral("'"));
|
||||
}
|
||||
|
||||
bool SqlSerializer::readString(QString &text, QString &out) const
|
||||
{
|
||||
int start = -1;
|
||||
int end = -1;
|
||||
|
||||
for (int i = 0; i < text.length(); ++i) {
|
||||
if (text.at(i) == QLatin1Char('"') && (i == 0 || text.at(i - 1) != QStringLiteral("\\"))) {
|
||||
if (start == -1)
|
||||
start = i;
|
||||
else
|
||||
end = i;
|
||||
}
|
||||
if (end != -1){
|
||||
out = text.mid(start + 1, end - start - 1);
|
||||
text = text.mid(end + 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QVariant SqlSerializer::deserialize(const QString &value, const QMetaType::Type &type) const
|
||||
{
|
||||
return fromString(unescapeString(value), type);
|
||||
}
|
||||
|
||||
QString SqlSerializer::serialize(const QVariant &value) const
|
||||
{
|
||||
return escapeString(toString(value));
|
||||
}
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/**************************************************************************
|
||||
**
|
||||
** 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 SQLSERIALIZER_H
|
||||
#define SQLSERIALIZER_H
|
||||
|
||||
#include <QVariant>
|
||||
#include <QtNut/NutGlobal>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
class SqlSerializer
|
||||
{
|
||||
public:
|
||||
SqlSerializer();
|
||||
virtual ~SqlSerializer();
|
||||
|
||||
bool readString(QString &text, QString &out) const;
|
||||
|
||||
QVariant fromString(const QString &value, const QMetaType::Type &type) const;
|
||||
QString toString(const QVariant &value) const;
|
||||
QList<int> toListInt(const QString &s) const;
|
||||
QList<int> toListInt(const QString &s, const QString &sep) const;
|
||||
QList<qreal> toListReal(const QString &s) const;
|
||||
QList<qreal> toListReal(const QString &s, const QString &sep) const;
|
||||
QList<float> toListFloat(const QString &s) const;
|
||||
|
||||
QString fromList(const QList<int> &list) const;
|
||||
QString fromList(const QList<qreal> &list) const;
|
||||
QString fromList(const QList<float> &list) const;
|
||||
QString fromVariantList(const QVariantList &list) const;
|
||||
|
||||
QVariant deserialize(const QString &value, const QMetaType::Type &type) const;
|
||||
QString serialize(const QVariant &value) const;
|
||||
private:
|
||||
QString escapeString(const QString &str) const;
|
||||
QString unescapeString(const QString &str) const;
|
||||
};
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // SQLSERIALIZER_H
|
||||
|
|
@ -30,6 +30,8 @@
|
|||
#include "abstracttableset.h"
|
||||
#include "propertysignalmapper.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
/*
|
||||
|
|
@ -89,17 +91,6 @@ void Table::add(AbstractTableSet *t)
|
|||
|
||||
void Table::propertyChanged(const QString &propName)
|
||||
{
|
||||
//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()));
|
||||
|
||||
// Q_FOREACH (FieldModel *f, d->model->fields())
|
||||
// if(f->isPrimaryKey && propName == f->name && f->isAutoIncrement)
|
||||
// return;
|
||||
|
||||
d.detach();
|
||||
d->changedProperties.insert(propName);
|
||||
if (d->status == FetchedFromDB)
|
||||
|
|
@ -121,7 +112,7 @@ void Table::clear()
|
|||
d->changedProperties.clear();
|
||||
}
|
||||
|
||||
QSet<QString> Table::changedProperties() const
|
||||
const QSet<QString> &Table::changedProperties() const
|
||||
{
|
||||
//Q_D(const Table);
|
||||
return d->changedProperties;
|
||||
|
|
@ -138,7 +129,7 @@ bool Table::setParentTable(Table *master, TableModel *masterModel, TableModel *m
|
|||
// if (!d->model)
|
||||
// d->model = TableModel::findByClassName(metaObject()->className());
|
||||
|
||||
Q_FOREACH (RelationModel *r, model->foreignKeys())
|
||||
for (auto &r: model->foreignKeys())
|
||||
if(r->masterClassName == masterClassName)
|
||||
{
|
||||
setProperty(QString(r->localColumn).toLatin1().data(),
|
||||
|
|
@ -179,7 +170,7 @@ void Table::setParentTableSet(AbstractTableSet *parent)
|
|||
AbstractTableSet *Table::childTableSet(const QString &name) const
|
||||
{
|
||||
//Q_D(const Table);
|
||||
Q_FOREACH (AbstractTableSet *t, d->childTableSets)
|
||||
for (auto &t: qAsConst(d->childTableSets))
|
||||
if (t->childClassName() == name)
|
||||
return t;
|
||||
return Q_NULLPTR;
|
||||
|
|
@ -230,3 +221,5 @@ void TablePrivate::refreshModel()
|
|||
}
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@
|
|||
#include <QtNut/tablemodel.h>
|
||||
#include <QtNut/phrase.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
class Database;
|
||||
|
|
@ -66,7 +68,7 @@ public:
|
|||
|
||||
AbstractTableSet *childTableSet(const QString &name) const;
|
||||
|
||||
QSet<QString> changedProperties() const;
|
||||
const QSet<QString> &changedProperties() const;
|
||||
|
||||
bool setParentTable(Table *master, TableModel *masterModel, TableModel *model);
|
||||
Q_SIGNALS:
|
||||
|
|
@ -103,4 +105,9 @@ private:
|
|||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
Q_DECLARE_METATYPE(NUT_WRAP_NAMESPACE(Table)*)
|
||||
Q_DECLARE_METATYPE(NUT_WRAP_NAMESPACE(Row<NUT_WRAP_NAMESPACE(Table)>))
|
||||
|
||||
#endif // TABLE_H
|
||||
|
|
|
|||
|
|
@ -1,3 +1,33 @@
|
|||
/**************************************************************************
|
||||
**
|
||||
** 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/>.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Nut API. This header
|
||||
// file may change from version to version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#ifndef TABLEPRIVATE_H
|
||||
#define TABLEPRIVATE_H
|
||||
|
||||
|
|
@ -7,6 +37,8 @@
|
|||
#include <QtNut/nut_global.h>
|
||||
#include <QtNut/table.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
class TableModel;
|
||||
|
|
@ -31,4 +63,6 @@ public:
|
|||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // TABLEPRIVATE_H
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@
|
|||
#include <QtNut/databasemodel.h>
|
||||
#include <QtNut/abstracttablesetdata.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
template<class T>
|
||||
|
|
@ -98,16 +100,16 @@ Q_OUTOFLINE_TEMPLATE BulkInserter TableSet<T>::bulkInserter()
|
|||
template<class T>
|
||||
Q_OUTOFLINE_TEMPLATE int TableSet<T>::length() const
|
||||
{
|
||||
return data->childs.count();
|
||||
return data->children.count();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Q_OUTOFLINE_TEMPLATE Row<T> TableSet<T>::at(int i) const
|
||||
{
|
||||
#ifdef NUT_RAW_POINTER
|
||||
return reinterpret_cast<T*>(data->childs.at(i));
|
||||
return reinterpret_cast<T*>(data->children.at(i));
|
||||
#else
|
||||
return data->childs.at(i).template objectCast<T>();
|
||||
return data->children.at(i).template objectCast<T>();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -136,7 +138,7 @@ template<class T>
|
|||
Q_OUTOFLINE_TEMPLATE void TableSet<T>::append(Row<T> t)
|
||||
{
|
||||
data.detach();
|
||||
data->childs.append(t);
|
||||
data->children.append(t);
|
||||
// data->tables.insert(t.data());
|
||||
// data->childRows.append(t.data());
|
||||
|
||||
|
|
@ -151,7 +153,7 @@ Q_OUTOFLINE_TEMPLATE void TableSet<T>::append(Row<T> t)
|
|||
template<class T>
|
||||
Q_OUTOFLINE_TEMPLATE void TableSet<T>::append(RowList<T> t)
|
||||
{
|
||||
Q_FOREACH (Row<T> i, t)
|
||||
for (auto &i: t)
|
||||
append(i);
|
||||
}
|
||||
|
||||
|
|
@ -159,19 +161,21 @@ template<class T>
|
|||
Q_OUTOFLINE_TEMPLATE void TableSet<T>::remove(Row<T> t)
|
||||
{
|
||||
data.detach();
|
||||
// data->childs.removeOne(t.data());
|
||||
// data->children.removeOne(t.data());
|
||||
// data->tables.remove(t.data());
|
||||
data->childs.removeOne(t);
|
||||
data->children.removeOne(t);
|
||||
t->setStatus(Table::Deleted);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Q_OUTOFLINE_TEMPLATE void TableSet<T>::remove(RowList<T> t)
|
||||
{
|
||||
Q_FOREACH (Row<T> i, t)
|
||||
for (auto &i: t)
|
||||
remove(i);
|
||||
}
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // TABLESET_H
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@
|
|||
#include "databasemodel.h"
|
||||
#include "tablemodel.h"
|
||||
#include "sqlserializer.h"
|
||||
#include "nut_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
|
|
@ -114,7 +117,7 @@ QString AbstractSqlGenerator::recordsPhrase(TableModel *table)
|
|||
return QString();
|
||||
|
||||
QString ret = QString();
|
||||
Q_FOREACH (FieldModel *f, table->fields()) {
|
||||
for (auto &f: table->fields()) {
|
||||
if (!ret.isEmpty())
|
||||
ret.append(QLatin1String(", "));
|
||||
ret.append(QStringLiteral("%1.%2 AS \"%1.%2\"").arg(table->name(), f->name));
|
||||
|
|
@ -125,9 +128,9 @@ QString AbstractSqlGenerator::recordsPhrase(TableModel *table)
|
|||
QString AbstractSqlGenerator::insertBulk(const QString &tableName, const PhraseList &ph, const QList<QVariantList> &vars)
|
||||
{
|
||||
QString sql;
|
||||
Q_FOREACH (QVariantList list, vars) {
|
||||
for (auto &list: vars) {
|
||||
QStringList values;
|
||||
Q_FOREACH (QVariant v, list)
|
||||
for (auto &v: list)
|
||||
values.append(escapeValue(v));
|
||||
|
||||
if (!sql.isEmpty())
|
||||
|
|
@ -147,7 +150,7 @@ QString AbstractSqlGenerator::fieldDeclare(FieldModel *field)
|
|||
if (type.isEmpty())
|
||||
return type;
|
||||
|
||||
QString ret = escaleFieldName(field->name) + QStringLiteral(" ") + type;
|
||||
QString ret = escapeFieldName(field->name) + QStringLiteral(" ") + type;
|
||||
if (field->notNull)
|
||||
ret.append(QStringLiteral(" NOT NULL"));
|
||||
|
||||
|
|
@ -157,7 +160,7 @@ QString AbstractSqlGenerator::fieldDeclare(FieldModel *field)
|
|||
return ret;
|
||||
}
|
||||
|
||||
QString AbstractSqlGenerator::escaleFieldName(const QString &fieldName) const
|
||||
QString AbstractSqlGenerator::escapeFieldName(const QString &fieldName) const
|
||||
{
|
||||
return fieldName;
|
||||
}
|
||||
|
|
@ -174,7 +177,7 @@ QString AbstractSqlGenerator::relationDeclare(const RelationModel *relation)
|
|||
.arg(relation->localColumn, relation->slaveTable->name());
|
||||
}
|
||||
|
||||
QStringList AbstractSqlGenerator::diff(const DatabaseModel &lastModel,
|
||||
QStringList AbstractSqlGenerator::diffDatabase(const DatabaseModel &lastModel,
|
||||
const DatabaseModel &newModel)
|
||||
{
|
||||
QStringList ret;
|
||||
|
|
@ -185,7 +188,7 @@ QStringList AbstractSqlGenerator::diff(const DatabaseModel &lastModel,
|
|||
for (i = unionModel.begin(); i != unionModel.end(); ++i) {
|
||||
TableModel *oldTable = lastModel.tableByName((*i)->name());
|
||||
TableModel *newTable = newModel.tableByName((*i)->name());
|
||||
QStringList sql = diff(oldTable, newTable);
|
||||
QStringList sql = diffTable(oldTable, newTable);
|
||||
if (!sql.isEmpty())
|
||||
ret << sql;
|
||||
|
||||
|
|
@ -197,13 +200,16 @@ QStringList AbstractSqlGenerator::diff(const DatabaseModel &lastModel,
|
|||
return ret;
|
||||
}
|
||||
|
||||
QString AbstractSqlGenerator::diff(FieldModel *oldField, FieldModel *newField)
|
||||
QString AbstractSqlGenerator::diffField(FieldModel *oldField, FieldModel *newField)
|
||||
{
|
||||
QString sql = QString();
|
||||
if (!oldField && !newField)
|
||||
return QString();
|
||||
|
||||
if (oldField && newField)
|
||||
if (*oldField == *newField)
|
||||
return sql;
|
||||
return QString();
|
||||
|
||||
QString sql = QString();
|
||||
if (!newField) {
|
||||
sql = QStringLiteral("DROP COLUMN ") + oldField->name;
|
||||
} else {
|
||||
|
|
@ -216,7 +222,7 @@ QString AbstractSqlGenerator::diff(FieldModel *oldField, FieldModel *newField)
|
|||
return sql;
|
||||
}
|
||||
|
||||
QStringList AbstractSqlGenerator::diff(TableModel *oldTable, TableModel *newTable)
|
||||
QStringList AbstractSqlGenerator::diffTable(TableModel *oldTable, TableModel *newTable)
|
||||
{
|
||||
if (!newTable && !oldTable)
|
||||
return QStringList();
|
||||
|
|
@ -232,28 +238,28 @@ QStringList AbstractSqlGenerator::diff(TableModel *oldTable, TableModel *newTabl
|
|||
QList<QString> relations;
|
||||
|
||||
if (oldTable) {
|
||||
Q_FOREACH (FieldModel *f, oldTable->fields())
|
||||
for (auto &f: oldTable->fields())
|
||||
if (!fieldNames.contains(f->name))
|
||||
fieldNames.append(f->name);
|
||||
Q_FOREACH (RelationModel *r, oldTable->foreignKeys())
|
||||
for (auto &r: oldTable->foreignKeys())
|
||||
if (!relations.contains(r->localColumn))
|
||||
relations.append(r->localColumn);
|
||||
}
|
||||
|
||||
Q_FOREACH (FieldModel *f, newTable->fields())
|
||||
for (auto &f: newTable->fields())
|
||||
if (!fieldNames.contains(f->name))
|
||||
fieldNames.append(f->name);
|
||||
Q_FOREACH (RelationModel *r, newTable->foreignKeys())
|
||||
for (auto &r: newTable->foreignKeys())
|
||||
if (!relations.contains(r->localColumn))
|
||||
relations.append(r->localColumn);
|
||||
|
||||
QStringList columnSql;
|
||||
Q_FOREACH (QString fieldName, fieldNames) {
|
||||
for (auto &fieldName: fieldNames) {
|
||||
FieldModel *newField = newTable->field(fieldName);
|
||||
if (oldTable) {
|
||||
FieldModel *oldField = oldTable->field(fieldName);
|
||||
|
||||
QString buffer = diff(oldField, newField);
|
||||
QString buffer = diffField(oldField, newField);
|
||||
if (!buffer.isEmpty())
|
||||
columnSql << buffer;
|
||||
} else {
|
||||
|
|
@ -303,23 +309,23 @@ QStringList AbstractSqlGenerator::diffRelation(TableModel *oldTable, TableModel
|
|||
QList<QString> relations;
|
||||
|
||||
if (oldTable) {
|
||||
Q_FOREACH (RelationModel *r, oldTable->foreignKeys())
|
||||
for (auto &r: oldTable->foreignKeys())
|
||||
if (!relations.contains(r->localColumn))
|
||||
relations.append(r->localColumn);
|
||||
}
|
||||
|
||||
Q_FOREACH (RelationModel *r, newTable->foreignKeys())
|
||||
for (auto &r: newTable->foreignKeys())
|
||||
if (!relations.contains(r->localColumn))
|
||||
relations.append(r->localColumn);
|
||||
|
||||
QStringList columnSql;
|
||||
Q_FOREACH (QString fieldName, relations) {
|
||||
for (auto &fieldName: relations) {
|
||||
RelationModel *newRelation = newTable->foreignKeyByField(fieldName);
|
||||
RelationModel *oldRelation = nullptr;
|
||||
if (oldTable)
|
||||
oldRelation = oldTable->foreignKeyByField(fieldName);
|
||||
|
||||
QStringList buffer = diff(oldRelation, newRelation);
|
||||
QStringList buffer = diffRelation2(oldRelation, newRelation);
|
||||
if (!buffer.isEmpty())
|
||||
columnSql << buffer.at(0);
|
||||
}
|
||||
|
|
@ -332,7 +338,7 @@ QStringList AbstractSqlGenerator::diffRelation(TableModel *oldTable, TableModel
|
|||
return ret;
|
||||
}
|
||||
|
||||
QStringList AbstractSqlGenerator::diff(RelationModel *oldRel, RelationModel *newRel)
|
||||
QStringList AbstractSqlGenerator::diffRelation2(RelationModel *oldRel, RelationModel *newRel)
|
||||
{
|
||||
QStringList ret;
|
||||
/*
|
||||
|
|
@ -478,7 +484,7 @@ QString AbstractSqlGenerator::insertRecord(Table *t, QString tableName)
|
|||
|
||||
if (changedPropertiesText != QLatin1String(""))
|
||||
changedPropertiesText.append(QStringLiteral(", "));
|
||||
changedPropertiesText.append(escaleFieldName(f));
|
||||
changedPropertiesText.append(escapeFieldName(f));
|
||||
}
|
||||
sql = QStringLiteral("INSERT INTO %1 (%2) VALUES (%3)")
|
||||
.arg(tableName, changedPropertiesText, values.join(QStringLiteral(", ")));
|
||||
|
|
@ -495,9 +501,9 @@ QString AbstractSqlGenerator::updateRecord(Table *t, QString tableName)
|
|||
QString key = model->primaryKey();
|
||||
QStringList values;
|
||||
|
||||
for (auto &f : t->changedProperties())
|
||||
for (const auto &f : t->changedProperties())
|
||||
if (f != key)
|
||||
values.append(f + QStringLiteral("=")
|
||||
values.append(escapeFieldName(f) + QStringLiteral("=")
|
||||
+ escapeValue(t->property(f.toLatin1().data())));
|
||||
|
||||
sql = QStringLiteral("UPDATE %1 SET %2 WHERE %3=%4")
|
||||
|
|
@ -600,11 +606,11 @@ QString AbstractSqlGenerator::selectCommand(const QString &tableName,
|
|||
if (fields.data.count() == 0) {
|
||||
QSet<TableModel*> tables;
|
||||
tables.insert(_database->model().tableByName(tableName));
|
||||
Q_FOREACH (RelationModel *rel, joins)
|
||||
for (auto &rel: joins)
|
||||
tables << rel->masterTable << rel->slaveTable;
|
||||
|
||||
selectText = QString();
|
||||
Q_FOREACH (TableModel *t, tables) {
|
||||
for (auto &t: qAsConst(tables)) {
|
||||
if (!selectText.isEmpty())
|
||||
selectText.append(QStringLiteral(", "));
|
||||
selectText.append(recordsPhrase(t));
|
||||
|
|
@ -689,8 +695,8 @@ QString AbstractSqlGenerator::updateCommand(const QString &tableName,
|
|||
const ConditionalPhrase &where)
|
||||
{
|
||||
QString assigmentTexts = QString();
|
||||
Q_FOREACH (PhraseData *d, assigments.data) {
|
||||
if (assigmentTexts != QStringLiteral(""))
|
||||
for (auto &d: assigments.data) {
|
||||
if (assigmentTexts != QLatin1String())
|
||||
assigmentTexts.append(QStringLiteral(", "));
|
||||
|
||||
assigmentTexts.append(createConditionalPhrase(d));
|
||||
|
|
@ -717,92 +723,23 @@ QString AbstractSqlGenerator::insertCommand(const QString &tableName, const Assi
|
|||
|
||||
QString fieldNames;
|
||||
QString values;
|
||||
Q_FOREACH (PhraseData *d, assigments.data) {
|
||||
for (auto &d: assigments.data) {
|
||||
if (!fieldNames.isEmpty())
|
||||
fieldNames.append(QStringLiteral(", "));
|
||||
|
||||
if (!values.isEmpty())
|
||||
values.append(QStringLiteral(", "));
|
||||
|
||||
fieldNames.append(escaleFieldName(QString::fromUtf8(d->left->fieldName)));
|
||||
fieldNames.append(escapeFieldName(QString::fromUtf8(d->left->fieldName)));
|
||||
values.append(escapeValue(d->operand));
|
||||
}
|
||||
return QStringLiteral("INSERT INTO %1 (%2) VALUES (%3);")
|
||||
.arg(tableName, fieldNames, values);
|
||||
}
|
||||
|
||||
//QString SqlGeneratorBase::selectCommand(SqlGeneratorBase::AgregateType t,
|
||||
// QString agregateArg,
|
||||
// QString tableName,
|
||||
// QList<WherePhrase> &wheres,
|
||||
// QList<WherePhrase> &orders,
|
||||
// QList<RelationModel*> joins,
|
||||
// int skip, int take)
|
||||
//{
|
||||
// Q_UNUSED(take)
|
||||
// Q_UNUSED(skip)
|
||||
|
||||
// QStringList joinedOrders;
|
||||
// QString select = agregateText(t, agregateArg);
|
||||
|
||||
// //TODO: temporatory disabled
|
||||
// if (t == SelectAll) {
|
||||
// QSet<TableModel*> tables;
|
||||
// tables.insert(_database->model().tableByName(tableName));
|
||||
// Q_FOREACH (RelationModel *rel, joins)
|
||||
// tables << rel->masterTable << rel->slaveTable;
|
||||
|
||||
// select = "";
|
||||
// Q_FOREACH (TableModel *t, tables) {
|
||||
// if (!select.isEmpty())
|
||||
// select.append(", ");
|
||||
// select.append(recordsPhrase(t));
|
||||
// }
|
||||
// }
|
||||
// QString from = join(tableName, joins, &joinedOrders);
|
||||
// QString where = createWhere(wheres);
|
||||
// QString orderText = joinedOrders.join(", ");
|
||||
|
||||
// Q_FOREACH (WherePhrase p, orders) {
|
||||
// if (orderText != "")
|
||||
// orderText.append(", ");
|
||||
// orderText.append(phraseOrder(p.data()));
|
||||
// }
|
||||
|
||||
// QString sql = "SELECT " + select + " FROM " + from;
|
||||
|
||||
// if (where != "")
|
||||
// sql.append(" WHERE " + where);
|
||||
|
||||
// if (orderText != "")
|
||||
// sql.append(" ORDER BY " + orderText);
|
||||
|
||||
// for (int i = 0; i < _database->model().count(); i++)
|
||||
// sql = sql.replace(_database->model().at(i)->className() + ".",
|
||||
// _database->model().at(i)->name() + ".");
|
||||
|
||||
// replaceTableNames(sql);
|
||||
|
||||
// return sql + " ";
|
||||
//}
|
||||
|
||||
//QString SqlGeneratorBase::createWhere(QList<WherePhrase> &wheres)
|
||||
//{
|
||||
// QString whereText = "";
|
||||
|
||||
// Q_FOREACH (WherePhrase w, wheres) {
|
||||
// if (whereText != "")
|
||||
// whereText.append(" AND ");
|
||||
|
||||
// whereText.append(phrase(w.data()));
|
||||
// }
|
||||
|
||||
// return whereText;
|
||||
//}
|
||||
|
||||
void AbstractSqlGenerator::replaceTableNames(QString &command)
|
||||
{
|
||||
Q_FOREACH (TableModel *m, _database->model())
|
||||
for (auto &m: _database->model())
|
||||
command = command
|
||||
.replace(QStringLiteral("[") + m->className()
|
||||
+ QStringLiteral("]"), m->name());
|
||||
|
|
@ -810,10 +747,10 @@ void AbstractSqlGenerator::replaceTableNames(QString &command)
|
|||
|
||||
void AbstractSqlGenerator::removeTableNames(QString &command)
|
||||
{
|
||||
Q_FOREACH (TableModel *m, _database->model())
|
||||
for (auto &m: _database->model())
|
||||
command = command.replace(QStringLiteral("[")
|
||||
+ m->className()
|
||||
+ QStringLiteral("]."), QStringLiteral(""));
|
||||
+ QStringLiteral("]."), QLatin1String());
|
||||
}
|
||||
|
||||
QString AbstractSqlGenerator::dateTimePartName(const PhraseData::Condition &op) const
|
||||
|
|
@ -891,13 +828,13 @@ QString AbstractSqlGenerator::dateTimePartName(const PhraseData::Condition &op)
|
|||
|
||||
QString AbstractSqlGenerator::escapeValue(const QVariant &v) const
|
||||
{
|
||||
if (v.type() == QVariant::String && v.toString().isEmpty())
|
||||
if (VARIANT_TYPE_COMPARE(v, String) && v.toString().isEmpty())
|
||||
return QStringLiteral("''");
|
||||
|
||||
if (v.type() == QVariant::List) {
|
||||
if (VARIANT_TYPE_COMPARE_X(v, QVariant::List, QMetaType::QVariantList)) {
|
||||
auto list = v.toList();
|
||||
QStringList ret;
|
||||
Q_FOREACH (QVariant vi, list) {
|
||||
for (auto &vi: list) {
|
||||
ret.append(QStringLiteral("'")
|
||||
+ _serializer->serialize(vi)
|
||||
+ QStringLiteral("'"));
|
||||
|
|
@ -1121,7 +1058,7 @@ QString AbstractSqlGenerator::createConditionalPhrase(const PhraseData *d) const
|
|||
QString AbstractSqlGenerator::createOrderPhrase(const PhraseList &ph)
|
||||
{
|
||||
QString ret = QString();
|
||||
Q_FOREACH (const PhraseData *d, ph.data) {
|
||||
for (const auto &d: ph.data) {
|
||||
if (!ret.isEmpty())
|
||||
ret.append(QStringLiteral(", "));
|
||||
ret.append(d->toString());
|
||||
|
|
@ -1135,10 +1072,10 @@ QString AbstractSqlGenerator::createOrderPhrase(const PhraseList &ph)
|
|||
QString AbstractSqlGenerator::createFieldPhrase(const PhraseList &ph)
|
||||
{
|
||||
QString ret = QString();
|
||||
Q_FOREACH (const PhraseData *d, ph.data) {
|
||||
for (const auto &d: ph.data) {
|
||||
if (!ret.isEmpty())
|
||||
ret.append(QStringLiteral(", "));
|
||||
ret.append(d->toString());
|
||||
ret.append("`" + d->toString() + "`");
|
||||
if (d->isNot)
|
||||
qDebug() << "Operator ! is ignored in fields phrase";
|
||||
}
|
||||
|
|
@ -1147,7 +1084,7 @@ QString AbstractSqlGenerator::createFieldPhrase(const PhraseList &ph)
|
|||
|
||||
void AbstractSqlGenerator::createInsertPhrase(const AssignmentPhraseList &ph, QString &fields, QString &values)
|
||||
{
|
||||
Q_FOREACH (PhraseData *d, ph.data) {
|
||||
for (auto &d: ph.data) {
|
||||
if (!fields.isEmpty())
|
||||
fields.append(QStringLiteral(", "));
|
||||
|
||||
|
|
@ -1175,3 +1112,5 @@ void AbstractSqlGenerator::createInsertPhrase(const AssignmentPhraseList &ph, QS
|
|||
}
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -27,7 +27,8 @@
|
|||
|
||||
#include <QtNut/phrase.h>
|
||||
|
||||
class SqlSerializer;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
|
|
@ -37,6 +38,7 @@ class DatabaseModel;
|
|||
class TableModel;
|
||||
class Database;
|
||||
struct RelationModel;
|
||||
class SqlSerializer;
|
||||
class NUT_EXPORT AbstractSqlGenerator : public QObject
|
||||
{
|
||||
// Q_OBJECT
|
||||
|
|
@ -80,7 +82,7 @@ public:
|
|||
//fields
|
||||
virtual QString fieldType(FieldModel *field) = 0;
|
||||
virtual QString fieldDeclare(FieldModel *field);
|
||||
virtual QString escaleFieldName(const QString &fieldName) const;
|
||||
virtual QString escapeFieldName(const QString &fieldName) const;
|
||||
virtual QStringList constraints(TableModel *table);
|
||||
virtual QString escapeValue(const QVariant &v) const;
|
||||
virtual QVariant unescapeValue(const QMetaType::Type &type, const QVariant &dbValue);
|
||||
|
|
@ -91,11 +93,11 @@ public:
|
|||
|
||||
virtual QString relationDeclare(const RelationModel *relation);
|
||||
|
||||
virtual QStringList diff(const DatabaseModel &lastModel, const DatabaseModel &newModel);
|
||||
virtual QString diff(FieldModel *oldField, FieldModel *newField);
|
||||
virtual QStringList diff(TableModel *oldTable, TableModel *newTable);
|
||||
virtual QStringList diffDatabase(const DatabaseModel &lastModel, const DatabaseModel &newModel);
|
||||
virtual QString diffField(FieldModel *oldField, FieldModel *newField);
|
||||
virtual QStringList diffTable(TableModel *oldTable, TableModel *newTable);
|
||||
virtual QStringList diffRelation(TableModel *oldTable, TableModel *newTable);
|
||||
virtual QStringList diff(RelationModel *oldRel, RelationModel *newRel);
|
||||
virtual QStringList diffRelation2(RelationModel *oldRel, RelationModel *newRel);
|
||||
|
||||
virtual QString join(const QString &mainTable,
|
||||
const QList<RelationModel*> &list,
|
||||
|
|
@ -169,4 +171,6 @@ protected:
|
|||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // NUT_ABSTRACTSQLGENERATOR_H
|
||||
|
|
|
|||
|
|
@ -26,12 +26,17 @@
|
|||
#include <QtCore/QTime>
|
||||
#include <QtCore/QDate>
|
||||
#include <QtCore/QDateTime>
|
||||
#include <QtCore/QUuid>
|
||||
|
||||
#ifdef QT_GUI_LIB
|
||||
# include <QtGui/QPolygon>
|
||||
# include <QtGui/QPolygonF>
|
||||
#endif
|
||||
|
||||
#include "sqlserializer.h"
|
||||
#include "nut_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
|
|
@ -83,15 +88,15 @@ QString MySqlGenerator::fieldType(FieldModel *field)
|
|||
dbType = QStringLiteral("TEXT");
|
||||
break;
|
||||
|
||||
case QMetaType::QUuid:
|
||||
dbType = QStringLiteral("VARCHAR(38)");
|
||||
break;
|
||||
|
||||
case QMetaType::QPolygon:
|
||||
case QMetaType::QPolygonF:
|
||||
// dbType = "POLYGON";
|
||||
// break;
|
||||
|
||||
case QMetaType::QUuid:
|
||||
// dbType = "VARCHAR(64)";
|
||||
// break;
|
||||
|
||||
case QMetaType::QPoint:
|
||||
case QMetaType::QPointF:
|
||||
|
|
@ -114,7 +119,7 @@ QString MySqlGenerator::fieldType(FieldModel *field)
|
|||
default:
|
||||
qWarning("Type %s::%s(%d) is not supported",
|
||||
qPrintable(field->name),
|
||||
QMetaType::typeName(field->type),
|
||||
METATYPE_TO_NAME(field->type),
|
||||
field->type);
|
||||
dbType = QString();
|
||||
}
|
||||
|
|
@ -127,18 +132,21 @@ QString MySqlGenerator::fieldType(FieldModel *field)
|
|||
|
||||
QString MySqlGenerator::escapeValue(const QVariant &v) const
|
||||
{
|
||||
if (v.type() == QVariant::Bool)
|
||||
if (VARIANT_TYPE_COMPARE_X(v, Bool, Bool))
|
||||
return v.toBool() ? QStringLiteral("1") : QStringLiteral("0");
|
||||
|
||||
if (v.type() == QVariant::Time)
|
||||
if (VARIANT_TYPE_COMPARE(v, Time))
|
||||
return v.toTime().toString(QStringLiteral("''HH:mm:ss''"));
|
||||
|
||||
if (v.type() == QVariant::Date)
|
||||
if (VARIANT_TYPE_COMPARE(v, Date))
|
||||
return v.toDate().toString(QStringLiteral("''yyyy-MM-dd''"));
|
||||
|
||||
if (v.type() == QVariant::DateTime)
|
||||
if (VARIANT_TYPE_COMPARE(v, DateTime))
|
||||
return v.toDateTime().toString(QStringLiteral("''yyyy-MM-dd HH:mm:ss''"));
|
||||
|
||||
if (VARIANT_TYPE_COMPARE(v, Uuid))
|
||||
return QStringLiteral("'") + v.toUuid().toString() + QStringLiteral("'");
|
||||
|
||||
//#ifdef QT_GUI_LIB
|
||||
// if (v.type() == QVariant::Polygon) {
|
||||
// QString ret;
|
||||
|
|
@ -194,7 +202,7 @@ QVariant MySqlGenerator::unescapeValue(const QMetaType::Type &type, const QVaria
|
|||
// if (!readInsideParentese(ref, p))
|
||||
// return pol;
|
||||
// QStringList parts = p.split(",");
|
||||
// Q_FOREACH (QString v, parts) {
|
||||
// for (auto &v: parts) {
|
||||
// QList<int> l = _serializer->toListInt(p.trimmed(), " ");
|
||||
// if (l.count() != 2)
|
||||
// return QPolygon();
|
||||
|
|
@ -210,7 +218,7 @@ QVariant MySqlGenerator::unescapeValue(const QMetaType::Type &type, const QVaria
|
|||
// return pol;
|
||||
|
||||
// QStringList parts = p.split(",");
|
||||
// Q_FOREACH (QString v, parts) {
|
||||
// for (auto &v: parts) {
|
||||
// QList<qreal> l = _serializer->toListReal(p.trimmed(), " ");
|
||||
// if (l.count() != 2)
|
||||
// return QPolygonF();
|
||||
|
|
@ -229,6 +237,9 @@ QVariant MySqlGenerator::unescapeValue(const QMetaType::Type &type, const QVaria
|
|||
if (type == QMetaType::QDate)
|
||||
return dbValue.toDate();
|
||||
|
||||
if (type == QMetaType::QUuid)
|
||||
return QUuid::fromString(dbValue.toString());
|
||||
|
||||
return AbstractSqlGenerator::unescapeValue(type, dbValue);
|
||||
}
|
||||
|
||||
|
|
@ -240,12 +251,12 @@ bool MySqlGenerator::readInsideParentese(QString &text, QString &out)
|
|||
for (int i = 0; i < text.length(); ++i) {
|
||||
QChar ch = text.at(i);
|
||||
|
||||
if (ch == '(') {
|
||||
if (ch == QLatin1Char('(')) {
|
||||
if (start == -1)
|
||||
start = i;
|
||||
pc++;
|
||||
}
|
||||
if (ch == ')') {
|
||||
if (ch == QLatin1Char(')')) {
|
||||
pc--;
|
||||
|
||||
if (!pc && end == -1)
|
||||
|
|
@ -315,11 +326,20 @@ QString MySqlGenerator::createConditionalPhrase(const PhraseData *d) const
|
|||
case PhraseData::AddMinutes:
|
||||
case PhraseData::AddMinutesDateTime:
|
||||
case PhraseData::AddSeconds:
|
||||
case PhraseData::AddSecondsDateTime:
|
||||
case PhraseData::AddSecondsDateTime: {
|
||||
auto interval = d->operand.toInt();
|
||||
|
||||
if (interval < 0)
|
||||
return QStringLiteral("DATE_SUB(%1, INTERVAL %2 %3)")
|
||||
.arg(createConditionalPhrase(d->left))
|
||||
.arg(-interval)
|
||||
.arg(AbstractSqlGenerator::dateTimePartName(op));
|
||||
else
|
||||
return QStringLiteral("DATE_ADD(%1, INTERVAL %2 %3)")
|
||||
.arg(createConditionalPhrase(d->left),
|
||||
d->operand.toString(),
|
||||
AbstractSqlGenerator::dateTimePartName(op));
|
||||
.arg(createConditionalPhrase(d->left))
|
||||
.arg(interval)
|
||||
.arg(AbstractSqlGenerator::dateTimePartName(op));
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
|
|
@ -362,8 +382,11 @@ QString MySqlGenerator::primaryKeyConstraint(const TableModel *table) const
|
|||
.arg(table->primaryKey());
|
||||
}
|
||||
|
||||
QString MySqlGenerator::escaleFieldName(const QString &fieldName) const
|
||||
QString MySqlGenerator::escapeFieldName(const QString &fieldName) const
|
||||
{
|
||||
return "`" + fieldName + "`";
|
||||
}
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
#include <QtNut/abstractsqlgenerator.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
class NUT_EXPORT MySqlGenerator : public AbstractSqlGenerator
|
||||
|
|
@ -40,7 +42,7 @@ public:
|
|||
QString createConditionalPhrase(const PhraseData *d) const override;
|
||||
void appendSkipTake(QString &sql, int skip, int take) override;
|
||||
QString primaryKeyConstraint(const TableModel *table) const override;
|
||||
QString escaleFieldName(const QString &fieldName) const override;
|
||||
QString escapeFieldName(const QString &fieldName) const override;
|
||||
|
||||
private:
|
||||
bool readInsideParentese(QString &text, QString &out);
|
||||
|
|
@ -48,4 +50,6 @@ private:
|
|||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // MYSQLGENERATOR_H
|
||||
|
|
|
|||
|
|
@ -32,6 +32,9 @@
|
|||
#include "table.h"
|
||||
#include "tablemodel.h"
|
||||
#include "sqlserializer.h"
|
||||
#include "nut_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
|
|
@ -43,12 +46,12 @@ bool PostgreSqlGenerator::readInsideParentese(QString &text, QString &out)
|
|||
for (int i = 0; i < text.length(); ++i) {
|
||||
QChar ch = text.at(i);
|
||||
|
||||
if (ch == '(') {
|
||||
if (ch == QLatin1Char('(')) {
|
||||
if (start == -1)
|
||||
start = i;
|
||||
pc++;
|
||||
}
|
||||
if (ch == ')') {
|
||||
if (ch == QLatin1Char(')')) {
|
||||
pc--;
|
||||
|
||||
if (!pc && end == -1)
|
||||
|
|
@ -63,14 +66,14 @@ bool PostgreSqlGenerator::readInsideParentese(QString &text, QString &out)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool PostgreSqlGenerator::isPostGisType(const QVariant::Type &t) const
|
||||
bool PostgreSqlGenerator::isPostGisType(const QMetaType::Type &t) const
|
||||
{
|
||||
return t == QVariant::Point
|
||||
|| t == QVariant::PointF
|
||||
|| t == QVariant::Rect
|
||||
|| t == QVariant::RectF
|
||||
|| t == QVariant::Polygon
|
||||
|| t == QVariant::PolygonF;
|
||||
return t == QMetaType::QPoint
|
||||
|| t == QMetaType::QPointF
|
||||
|| t == QMetaType::QRect
|
||||
|| t == QMetaType::QRectF
|
||||
|| t == QMetaType::QPolygon
|
||||
|| t == QMetaType::QPolygonF;
|
||||
}
|
||||
|
||||
PostgreSqlGenerator::PostgreSqlGenerator(Database *parent) : AbstractSqlGenerator (parent)
|
||||
|
|
@ -189,13 +192,16 @@ QString PostgreSqlGenerator::fieldType(FieldModel *field)
|
|||
return dbType;
|
||||
}
|
||||
|
||||
QString PostgreSqlGenerator::diff(FieldModel *oldField, FieldModel *newField)
|
||||
QString PostgreSqlGenerator::diffField(FieldModel *oldField, FieldModel *newField)
|
||||
{
|
||||
QString sql = QString();
|
||||
if(!oldField && !newField)
|
||||
return QString();
|
||||
|
||||
if(oldField && newField)
|
||||
if(*oldField == *newField)
|
||||
return QString();
|
||||
|
||||
QString sql = QString();
|
||||
if(!newField){
|
||||
sql = QStringLiteral("DROP COLUMN ") + oldField->name;
|
||||
}else{
|
||||
|
|
@ -212,25 +218,25 @@ QString PostgreSqlGenerator::diff(FieldModel *oldField, FieldModel *newField)
|
|||
|
||||
QString PostgreSqlGenerator::escapeValue(const QVariant &v) const
|
||||
{
|
||||
if (v.type() == QVariant::Time)
|
||||
if (VARIANT_TYPE_COMPARE(v, Time))
|
||||
return v.toTime().toString(QStringLiteral("''HH:mm:ss''"));
|
||||
|
||||
if (v.type() == QVariant::Date)
|
||||
if (VARIANT_TYPE_COMPARE(v, Date))
|
||||
return v.toDate().toString(QStringLiteral("''yyyy-MM-dd''"));
|
||||
|
||||
if (v.type() == QVariant::DateTime)
|
||||
if (VARIANT_TYPE_COMPARE(v, DateTime))
|
||||
return v.toDateTime().toString(QStringLiteral("''yyyy-MM-dd HH:mm:ss''"));
|
||||
|
||||
if (v.type() == QVariant::StringList)
|
||||
if (VARIANT_TYPE_COMPARE(v, StringList))
|
||||
return QStringLiteral("'{")
|
||||
+ v.toStringList().join(QStringLiteral(","))
|
||||
+ QStringLiteral("}'");
|
||||
|
||||
if (v.type() == QVariant::Point) {
|
||||
if (VARIANT_TYPE_COMPARE(v, Point)) {
|
||||
QPoint pt = v.toPoint();
|
||||
return QStringLiteral("point(%1, %2)").arg(pt.x()).arg(pt.y());
|
||||
}
|
||||
if (v.type() == QVariant::PointF) {
|
||||
if (VARIANT_TYPE_COMPARE(v, PointF)) {
|
||||
QPointF pt = v.toPointF();
|
||||
return QStringLiteral("point(%1, %2)").arg(pt.x()).arg(pt.y());
|
||||
}
|
||||
|
|
@ -241,7 +247,7 @@ QString PostgreSqlGenerator::escapeValue(const QVariant &v) const
|
|||
}
|
||||
|
||||
#ifdef QT_GUI_LIB
|
||||
if (v.type() == QVariant::Polygon) {
|
||||
if (VARIANT_TYPE_COMPARE(v, Polygon)) {
|
||||
QString ret;
|
||||
QPoint pt;
|
||||
QPolygon pol = v.value<QPolygon>();
|
||||
|
|
@ -254,7 +260,7 @@ QString PostgreSqlGenerator::escapeValue(const QVariant &v) const
|
|||
}
|
||||
return QStringLiteral("'((") + ret + QStringLiteral("))'");
|
||||
}
|
||||
if (v.type() == QVariant::PolygonF) {
|
||||
if (VARIANT_TYPE_COMPARE(v, PolygonF)) {
|
||||
QString ret;
|
||||
QPointF pt;
|
||||
QPolygonF pol = v.value<QPolygonF>();
|
||||
|
|
@ -287,20 +293,20 @@ QVariant PostgreSqlGenerator::unescapeValue(const QMetaType::Type &type, const Q
|
|||
return AbstractSqlGenerator::unescapeValue(QMetaType::QPoint,
|
||||
dbValue.toString()
|
||||
.replace(QStringLiteral("("),
|
||||
QStringLiteral(""))
|
||||
QLatin1String())
|
||||
.replace(QStringLiteral(")"),
|
||||
QStringLiteral("")));
|
||||
QLatin1String()));
|
||||
if (type == QMetaType::QPointF)
|
||||
return AbstractSqlGenerator::unescapeValue(QMetaType::QPointF,
|
||||
dbValue.toString()
|
||||
.replace(QStringLiteral("("),
|
||||
QStringLiteral(""))
|
||||
QLatin1String())
|
||||
.replace(QStringLiteral(")"),
|
||||
QStringLiteral("")));
|
||||
QLatin1String()));
|
||||
if (type == QMetaType::QStringList)
|
||||
return dbValue.toString()
|
||||
.replace(QStringLiteral("{"), QStringLiteral(""))
|
||||
.replace(QStringLiteral("}"), QStringLiteral(""))
|
||||
.replace(QStringLiteral("{"), QLatin1String())
|
||||
.replace(QStringLiteral("}"), QLatin1String())
|
||||
.split(QStringLiteral(","));
|
||||
|
||||
#ifdef QT_GUI_LIB
|
||||
|
|
@ -340,6 +346,17 @@ QVariant PostgreSqlGenerator::unescapeValue(const QMetaType::Type &type, const Q
|
|||
return AbstractSqlGenerator::unescapeValue(type, dbValue);
|
||||
}
|
||||
|
||||
void PostgreSqlGenerator::appendSkipTake(QString &sql, int skip, int take)
|
||||
{
|
||||
if (take > 0 && skip > 0) {
|
||||
sql.append(QStringLiteral(" LIMIT %1 OFFSET %2")
|
||||
.arg(take)
|
||||
.arg(skip));
|
||||
} else if (take > 0) {
|
||||
sql.append(QStringLiteral(" LIMIT %1").arg(take));
|
||||
}
|
||||
}
|
||||
|
||||
QString PostgreSqlGenerator::createConditionalPhrase(const PhraseData *d) const
|
||||
{
|
||||
if (!d)
|
||||
|
|
@ -353,7 +370,7 @@ QString PostgreSqlGenerator::createConditionalPhrase(const PhraseData *d) const
|
|||
}
|
||||
|
||||
if (d->type == PhraseData::WithVariant) {
|
||||
if (isPostGisType(d->operand.type()) && d->operatorCond == PhraseData::Equal) {
|
||||
if (isPostGisType(METATYPE_ID(d->operand)) && d->operatorCond == PhraseData::Equal) {
|
||||
return QStringLiteral("%1 ~= %2")
|
||||
.arg(AbstractSqlGenerator::createConditionalPhrase(d->left),
|
||||
escapeValue(d->operand));
|
||||
|
|
@ -402,3 +419,5 @@ QString PostgreSqlGenerator::createConditionalPhrase(const PhraseData *d) const
|
|||
}
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -25,30 +25,33 @@
|
|||
|
||||
#include <QtNut/abstractsqlgenerator.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
class NUT_EXPORT PostgreSqlGenerator : public AbstractSqlGenerator
|
||||
{
|
||||
private:
|
||||
bool readInsideParentese(QString &text, QString &out);
|
||||
bool isPostGisType(const QVariant::Type &t) const;
|
||||
bool isPostGisType(const QMetaType::Type &t) const;
|
||||
|
||||
public:
|
||||
explicit PostgreSqlGenerator(Database *parent = nullptr);
|
||||
|
||||
QString fieldType(FieldModel *field) override;
|
||||
|
||||
QString diff(FieldModel *oldField, FieldModel *newField) override;
|
||||
QString diffField(FieldModel *oldField, FieldModel *newField) override;
|
||||
|
||||
// SqlGeneratorBase interface
|
||||
public:
|
||||
QString escapeValue(const QVariant &v) const override;
|
||||
QVariant unescapeValue(const QMetaType::Type &type, const QVariant &dbValue) override;
|
||||
void appendSkipTake(QString &sql, int skip = -1, int take = -1) override;
|
||||
|
||||
// SqlGeneratorBase interface
|
||||
protected:
|
||||
QString createConditionalPhrase(const PhraseData *d) const override;
|
||||
};
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // POSTGRESQLGENERATOR_H
|
||||
|
|
|
|||
|
|
@ -21,6 +21,9 @@
|
|||
#include "sqlitegenerator.h"
|
||||
#include "table.h"
|
||||
#include "tablemodel.h"
|
||||
#include "nut_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
|
|
@ -116,15 +119,18 @@ bool SqliteGenerator::supportAutoIncrement(const QMetaType::Type &type)
|
|||
}
|
||||
|
||||
|
||||
QStringList SqliteGenerator::diff(TableModel *oldTable, TableModel *newTable)
|
||||
QStringList SqliteGenerator::diffTable(TableModel *oldTable, TableModel *newTable)
|
||||
{
|
||||
QStringList ret;
|
||||
|
||||
if (!oldTable && !newTable)
|
||||
return ret;
|
||||
|
||||
if (oldTable && newTable)
|
||||
if (*oldTable == *newTable)
|
||||
return ret;
|
||||
|
||||
QStringList newTableSql = AbstractSqlGenerator::diff(nullptr, newTable);
|
||||
QStringList newTableSql = AbstractSqlGenerator::diffTable(nullptr, newTable);
|
||||
|
||||
if (!newTable)
|
||||
return QStringList() << QStringLiteral("DROP TABLE ") + oldTable->name();
|
||||
|
|
@ -135,22 +141,22 @@ QStringList SqliteGenerator::diff(TableModel *oldTable, TableModel *newTable)
|
|||
QList<QString> fieldNames;
|
||||
QList<QString> relations;
|
||||
|
||||
Q_FOREACH (FieldModel *f, oldTable->fields())
|
||||
for (auto &f: oldTable->fields())
|
||||
if (!fieldNames.contains(f->name))
|
||||
fieldNames.append(f->name);
|
||||
Q_FOREACH (RelationModel *r, oldTable->foreignKeys())
|
||||
for (auto &r: oldTable->foreignKeys())
|
||||
if (!relations.contains(r->localColumn))
|
||||
relations.append(r->localColumn);
|
||||
|
||||
Q_FOREACH (FieldModel *f, newTable->fields())
|
||||
for (auto &f: newTable->fields())
|
||||
if (!fieldNames.contains(f->name))
|
||||
fieldNames.append(f->name);
|
||||
Q_FOREACH (RelationModel *r, newTable->foreignKeys())
|
||||
for (auto &r: newTable->foreignKeys())
|
||||
if (!relations.contains(r->localColumn))
|
||||
relations.append(r->localColumn);
|
||||
|
||||
QString columns;
|
||||
Q_FOREACH (FieldModel *f, oldTable->fields()) {
|
||||
for (auto &f: oldTable->fields()) {
|
||||
if (!newTable->field(f->name))
|
||||
continue;
|
||||
|
||||
|
|
@ -238,9 +244,8 @@ QString SqliteGenerator::createConditionalPhrase(const PhraseData *d) const
|
|||
int i = d->operand.toInt();
|
||||
return QStringLiteral("DATE(%1,'%2 %3')")
|
||||
.arg(createConditionalPhrase(d->left),
|
||||
(i < 0 ? QStringLiteral("") : QStringLiteral("+")) + QString::number(i),
|
||||
(i < 0 ? QLatin1String() : QStringLiteral("+")) + QString::number(i),
|
||||
dateTimePartName(op));
|
||||
break;
|
||||
}
|
||||
case PhraseData::AddHours:
|
||||
case PhraseData::AddMinutes:
|
||||
|
|
@ -248,9 +253,8 @@ QString SqliteGenerator::createConditionalPhrase(const PhraseData *d) const
|
|||
int i = d->operand.toInt();
|
||||
return QStringLiteral("TIME(%1,'%2 %3')")
|
||||
.arg(createConditionalPhrase(d->left),
|
||||
(i < 0 ? QStringLiteral("") : QStringLiteral("+")) + QString::number(i),
|
||||
(i < 0 ? QLatin1String() : QStringLiteral("+")) + QString::number(i),
|
||||
dateTimePartName(op));
|
||||
break;
|
||||
}
|
||||
case PhraseData::AddYearsDateTime:
|
||||
case PhraseData::AddMonthsDateTime:
|
||||
|
|
@ -261,7 +265,7 @@ QString SqliteGenerator::createConditionalPhrase(const PhraseData *d) const
|
|||
int i = d->operand.toInt();
|
||||
return QStringLiteral("DATETIME(%1,'%2 %3')")
|
||||
.arg(createConditionalPhrase(d->left),
|
||||
(i < 0 ? QStringLiteral("") : QStringLiteral("+")) + QString::number(i),
|
||||
(i < 0 ? QLatin1String() : QStringLiteral("+")) + QString::number(i),
|
||||
dateTimePartName(op));
|
||||
break;
|
||||
}
|
||||
|
|
@ -308,13 +312,13 @@ QString SqliteGenerator::createConditionalPhrase(const PhraseData *d) const
|
|||
|
||||
QString SqliteGenerator::escapeValue(const QVariant &v) const
|
||||
{
|
||||
if (v.type() == QVariant::Time)
|
||||
if (VARIANT_TYPE_COMPARE(v, Time))
|
||||
return v.toTime().toString(QStringLiteral("''HH:mm:ss''"));
|
||||
|
||||
if (v.type() == QVariant::Date)
|
||||
if (VARIANT_TYPE_COMPARE(v, Date))
|
||||
return v.toDate().toString(QStringLiteral("''yyyy-MM-dd''"));
|
||||
|
||||
if (v.type() == QVariant::DateTime)
|
||||
if (VARIANT_TYPE_COMPARE(v, DateTime))
|
||||
return v.toDateTime().toString(QStringLiteral("''yyyy-MM-dd HH:mm:ss''"));
|
||||
|
||||
return AbstractSqlGenerator::escapeValue(v);
|
||||
|
|
@ -335,3 +339,5 @@ QVariant SqliteGenerator::unescapeValue(const QMetaType::Type &type, const QVari
|
|||
}
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
#include <QtNut/abstractsqlgenerator.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
class NUT_EXPORT SqliteGenerator : public AbstractSqlGenerator
|
||||
|
|
@ -40,7 +42,7 @@ public:
|
|||
void appendSkipTake(QString &sql, int skip, int take) override;
|
||||
|
||||
QString primaryKeyConstraint(const TableModel *table) const override;
|
||||
QStringList diff(TableModel *oldTable, TableModel *newTable) override;
|
||||
QStringList diffTable(TableModel *oldTable, TableModel *newTable) override;
|
||||
|
||||
QString createConditionalPhrase(const PhraseData *d) const override;
|
||||
|
||||
|
|
@ -50,4 +52,6 @@ public:
|
|||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // SQLITEGENERATOR_H
|
||||
|
|
|
|||
|
|
@ -21,10 +21,13 @@
|
|||
#include "sqlservergenerator.h"
|
||||
#include "table.h"
|
||||
#include "tablemodel.h"
|
||||
#include "nut_p.h"
|
||||
|
||||
#include <QtCore/QPoint>
|
||||
#include <QtCore/QRegularExpression>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
SqlServerGenerator::SqlServerGenerator(Database *parent)
|
||||
|
|
@ -37,7 +40,7 @@ QString SqlServerGenerator::masterDatabaseName(QString databaseName)
|
|||
return databaseName.replace(
|
||||
QRegularExpression(QStringLiteral("DATABASE\\=(\\w+)"),
|
||||
QRegularExpression::CaseInsensitiveOption),
|
||||
QStringLiteral("DATABASE="));
|
||||
QStringLiteral("DATABASE=master"));
|
||||
}
|
||||
|
||||
QString SqlServerGenerator::fieldType(FieldModel *field)
|
||||
|
|
@ -130,13 +133,16 @@ QString SqlServerGenerator::fieldType(FieldModel *field)
|
|||
}
|
||||
}
|
||||
|
||||
QString SqlServerGenerator::diff(FieldModel *oldField, FieldModel *newField)
|
||||
QString SqlServerGenerator::diffField(FieldModel *oldField, FieldModel *newField)
|
||||
{
|
||||
QString sql = QString();
|
||||
if (!oldField && !newField)
|
||||
return QString();
|
||||
|
||||
if (oldField && newField)
|
||||
if (*oldField == *newField)
|
||||
return sql;
|
||||
return QString();
|
||||
|
||||
QString sql = QString();
|
||||
if (!newField) {
|
||||
sql = QStringLiteral("DROP COLUMN ") + oldField->name;
|
||||
} else {
|
||||
|
|
@ -152,44 +158,44 @@ QString SqlServerGenerator::diff(FieldModel *oldField, FieldModel *newField)
|
|||
|
||||
QString SqlServerGenerator::escapeValue(const QVariant &v) const
|
||||
{
|
||||
switch (v.type()) {
|
||||
case QVariant::String:
|
||||
case QVariant::Char:
|
||||
case QVariant::Polygon:
|
||||
case QVariant::PolygonF:
|
||||
case QVariant::Size:
|
||||
case QVariant::SizeF:
|
||||
case QVariant::Rect:
|
||||
case QVariant::RectF:
|
||||
case QVariant::Line:
|
||||
case QVariant::LineF:
|
||||
case QVariant::Color:
|
||||
case QVariant::StringList:
|
||||
// case QVariant::JsonArray:
|
||||
// case QVariant::JsonValue:
|
||||
// case QVariant::JsonObject:
|
||||
// case QVariant::JsonDocument:
|
||||
case QVariant::Url:
|
||||
switch (METATYPE_ID(v)) {
|
||||
case QMetaType::QString:
|
||||
case QMetaType::QChar:
|
||||
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 QStringLiteral("N") + AbstractSqlGenerator::escapeValue(v);
|
||||
|
||||
// case QVariant::Point: {
|
||||
// case QMetaType::QPoint: {
|
||||
// QPoint pt = v.toPoint();
|
||||
// return QString("geography::POINT(%1, %2, 4326)").arg(pt.x()).arg(
|
||||
// pt.y());
|
||||
// }
|
||||
// case QVariant::PointF: {
|
||||
// case QMetaType::QPointF: {
|
||||
// QPointF pt = v.toPointF();
|
||||
// return QString("geography::POINT(%1, %2, 4326)").arg(pt.x()).arg(
|
||||
// pt.y());
|
||||
// }
|
||||
|
||||
case QVariant::Time:
|
||||
case QMetaType::QTime:
|
||||
return v.toTime().toString(QStringLiteral("''HH:mm:ss''"));
|
||||
|
||||
case QVariant::Date:
|
||||
case QMetaType::QDate:
|
||||
return v.toDate().toString(QStringLiteral("''yyyy-MM-dd''"));
|
||||
|
||||
case QVariant::DateTime:
|
||||
case QMetaType::QDateTime:
|
||||
return v.toDateTime().toString(QStringLiteral("''yyyy-MM-dd HH:mm:ss''"));
|
||||
|
||||
default:
|
||||
|
|
@ -279,3 +285,5 @@ QString SqlServerGenerator::createConditionalPhrase(const PhraseData *d) const
|
|||
}
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
#include <QtNut/abstractsqlgenerator.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
class NUT_EXPORT SqlServerGenerator : public AbstractSqlGenerator
|
||||
|
|
@ -35,7 +37,7 @@ public:
|
|||
QString masterDatabaseName(QString databaseName) override;
|
||||
|
||||
QString fieldType(FieldModel *field) override;
|
||||
QString diff(FieldModel *oldField, FieldModel *newField) override;
|
||||
QString diffField(FieldModel *oldField, FieldModel *newField) override;
|
||||
|
||||
QString escapeValue(const QVariant &v) const override;
|
||||
QVariant unescapeValue(const QMetaType::Type &type, const QVariant &dbValue) override;
|
||||
|
|
@ -48,4 +50,6 @@ protected:
|
|||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // SQLSERVERGENERATOR_H
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
#include <QtCore/QJsonArray>
|
||||
#include <QtCore/QJsonObject>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
QMap<QString, DatabaseModel*> DatabaseModel::_models;
|
||||
|
|
@ -48,7 +50,7 @@ DatabaseModel::DatabaseModel(const QJsonObject &json) :
|
|||
setVersion(json.value(NODE_VERSION).toInt());
|
||||
|
||||
QJsonObject tables = json.value(NODE_TABLES).toObject();
|
||||
Q_FOREACH (QString key, tables.keys()) {
|
||||
for (auto &key: tables.keys()) {
|
||||
if(!tables.value(key).isObject())
|
||||
continue;
|
||||
|
||||
|
|
@ -146,7 +148,7 @@ RelationModel *DatabaseModel::relationByClassNames(const QString &masterClassNam
|
|||
if(!childTable)
|
||||
return nullptr;
|
||||
|
||||
Q_FOREACH (RelationModel *rel, childTable->foreignKeys())
|
||||
for (auto &rel: childTable->foreignKeys())
|
||||
if(rel->masterClassName == masterClassName)
|
||||
return rel;
|
||||
|
||||
|
|
@ -160,7 +162,7 @@ RelationModel *DatabaseModel::relationByTableNames(const QString &masterTableNam
|
|||
if(!childTable)
|
||||
return nullptr;
|
||||
|
||||
Q_FOREACH (RelationModel *rel, childTable->foreignKeys())
|
||||
for (auto &rel: childTable->foreignKeys())
|
||||
if(rel->masterTable->name() == masterTableName)
|
||||
return rel;
|
||||
|
||||
|
|
@ -174,7 +176,7 @@ DatabaseModel DatabaseModel::fromJson(QJsonObject &json)
|
|||
model.setVersion(json.value(NODE_VERSION).toInt());
|
||||
|
||||
QJsonObject tables = json.value(NODE_TABLES).toObject();
|
||||
Q_FOREACH (QString key, tables.keys()) {
|
||||
for (auto &key: tables.keys()) {
|
||||
if(!json.value(key).isObject())
|
||||
continue;
|
||||
|
||||
|
|
@ -209,8 +211,8 @@ bool DatabaseModel::remove(const QString &tableName)
|
|||
void DatabaseModel::fixRelations()
|
||||
{
|
||||
/*TODO: fixme
|
||||
Q_FOREACH (TableModel *table, currentModel)
|
||||
Q_FOREACH (RelationModel *fk, table->foreignKeys())
|
||||
for (auto &table: currentModel)
|
||||
for (auto &fk: table->foreignKeys())
|
||||
fk->masterTable = currentModel.tableByClassName(fk->masterClassName);
|
||||
*/
|
||||
}
|
||||
|
|
@ -238,12 +240,11 @@ void DatabaseModel::deleteAllModels()
|
|||
DatabaseModel operator +(const DatabaseModel &l, const DatabaseModel &r)
|
||||
{
|
||||
DatabaseModel model;
|
||||
DatabaseModel::const_iterator i;
|
||||
|
||||
for (i = r.constBegin(); i != r.constEnd(); ++i)
|
||||
for (auto i = r.constBegin(); i != r.constEnd(); ++i)
|
||||
model.append(*i);
|
||||
|
||||
for (i = l.constBegin(); i != l.constEnd(); ++i)
|
||||
for (auto i = l.constBegin(); i != l.constEnd(); ++i)
|
||||
model.append(*i);
|
||||
|
||||
return model;
|
||||
|
|
@ -252,17 +253,16 @@ DatabaseModel operator +(const DatabaseModel &l, const DatabaseModel &r)
|
|||
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) {
|
||||
for (auto 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) {
|
||||
for (auto i = l.constBegin(); i != l.constEnd(); ++i) {
|
||||
if (tables.contains((*i)->name()))
|
||||
continue;
|
||||
ret.append(*i);
|
||||
|
|
@ -273,3 +273,5 @@ DatabaseModel operator |(const DatabaseModel &l, const DatabaseModel &r)
|
|||
}
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@
|
|||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef DATABASEMODEL_H
|
||||
#define DATABASEMODEL_H
|
||||
#ifndef DATABASE_MODEL_H
|
||||
#define DATABASE_MODEL_H
|
||||
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QMap>
|
||||
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
class QJsonObject;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
class TableModel;
|
||||
|
|
@ -66,7 +68,7 @@ public:
|
|||
|
||||
bool remove(const QString &tableName);
|
||||
|
||||
//TODO: may be private (called from DatabasePrivate::getCurrectSchema only)
|
||||
//TODO: may be private (called from DatabasePrivate::getCurrentSchema only)
|
||||
void fixRelations();
|
||||
|
||||
static DatabaseModel *modelByName(const QString &name);
|
||||
|
|
@ -78,4 +80,6 @@ DatabaseModel operator |(const DatabaseModel &l, const DatabaseModel &r);
|
|||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
#endif // DATABASEMODEL_H
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // DATABASE_MODEL_H
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
#include "sqlmodel.h"
|
||||
#include "query.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
SqlModelPrivate::SqlModelPrivate(SqlModel *parent) : q_ptr(parent)
|
||||
|
|
@ -124,3 +126,5 @@ Row<Table> SqlModel::at(const int &i) const
|
|||
}
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
|
||||
#include <QtNut/nut_global.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
class Database;
|
||||
|
|
@ -44,9 +46,10 @@ public:
|
|||
// explicit SqlModel(Query *q);
|
||||
explicit SqlModel(Database *database, AbstractTableSet *tableSet, QObject *parent = Q_NULLPTR);
|
||||
|
||||
int rowCount(const QModelIndex &parent) const;
|
||||
int columnCount(const QModelIndex &parent) const;
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
int rowCount(const QModelIndex &parent) const override;
|
||||
int columnCount(const QModelIndex &parent) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||
|
||||
template<class T>
|
||||
void setTable(RowList<T> rows);
|
||||
|
|
@ -54,7 +57,6 @@ public:
|
|||
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<Table> at(const int &i) const;
|
||||
|
||||
void setRenderer(const std::function<QVariant (int, QVariant)> &renderer);
|
||||
|
|
@ -67,12 +69,13 @@ template<class T>
|
|||
Q_OUTOFLINE_TEMPLATE void SqlModel::setTable(RowList<T> rows)
|
||||
{
|
||||
RowList<Table> tab;
|
||||
Q_FOREACH (auto t, rows)
|
||||
for (auto t: rows)
|
||||
tab.append(t);
|
||||
setRows(tab);
|
||||
}
|
||||
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // SQLMODEL_H
|
||||
|
|
|
|||
|
|
@ -1,3 +1,33 @@
|
|||
/**************************************************************************
|
||||
**
|
||||
** 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/>.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Nut API. This header
|
||||
// file may change from version to version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#ifndef SQLMODEL_P_H
|
||||
#define SQLMODEL_P_H
|
||||
|
||||
|
|
@ -8,6 +38,8 @@
|
|||
|
||||
#include <QtNut/nut_global.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
class SqlModel;
|
||||
|
|
@ -29,4 +61,6 @@ public:
|
|||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // SQLMODEL_P_H
|
||||
|
|
|
|||
|
|
@ -26,6 +26,9 @@
|
|||
|
||||
#include "tablemodel.h"
|
||||
#include "nut_global.h"
|
||||
#include "nut_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
|
|
@ -74,7 +77,7 @@ FieldModel *TableModel::field(int n) const
|
|||
|
||||
FieldModel *TableModel::field(const QString &name) const
|
||||
{
|
||||
Q_FOREACH (FieldModel *f, _fields)
|
||||
for (auto &f: _fields)
|
||||
if(f->name == name)
|
||||
return f;
|
||||
|
||||
|
|
@ -94,7 +97,7 @@ QList<RelationModel *> TableModel::foreignKeys() const
|
|||
QStringList TableModel::fieldsNames() const
|
||||
{
|
||||
QStringList ret;
|
||||
Q_FOREACH (FieldModel *f, _fields)
|
||||
for (auto &f: _fields)
|
||||
ret.append(f->name);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -106,7 +109,7 @@ bool TableModel::operator ==(const TableModel &t) const{
|
|||
if(fields().count() != t.fields().count())
|
||||
return false;
|
||||
|
||||
Q_FOREACH (FieldModel *f, _fields) {
|
||||
for (auto &f: _fields) {
|
||||
FieldModel *tf = t.field(f->name);
|
||||
if(!tf)
|
||||
return false;
|
||||
|
|
@ -129,7 +132,7 @@ TableModel::TableModel(int typeId, const QString &tableName)
|
|||
// if (findByTypeId(typeId))
|
||||
// return;
|
||||
|
||||
const QMetaObject *tableMetaObject = QMetaType::metaObjectForType(typeId);
|
||||
const QMetaObject *tableMetaObject = QMetaType(typeId).metaObject();
|
||||
|
||||
_typeId = typeId;
|
||||
_name = tableName;
|
||||
|
|
@ -162,12 +165,16 @@ TableModel::TableModel(int typeId, const QString &tableName)
|
|||
QMetaProperty fieldProperty = tableMetaObject->property(j);
|
||||
auto name = QString::fromUtf8(fieldProperty.name());
|
||||
FieldModel *fieldObj = field(name);
|
||||
Q_FOREACH (FieldModel *f, _fields)
|
||||
for (auto &f: _fields)
|
||||
if(f->name == name)
|
||||
f = fieldObj;
|
||||
fieldObj = f;
|
||||
if(!fieldObj)
|
||||
continue;
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
fieldObj->type = static_cast<QMetaType::Type>(fieldProperty.metaType().id());
|
||||
#else
|
||||
fieldObj->type = static_cast<QMetaType::Type>(fieldProperty.type());
|
||||
#endif
|
||||
fieldObj->typeName = QString::fromUtf8(fieldProperty.typeName());
|
||||
}
|
||||
|
||||
|
|
@ -244,13 +251,17 @@ TableModel::TableModel(const QJsonObject &json, const QString &tableName) : _typ
|
|||
|
||||
QJsonObject fields = json.value(QStringLiteral(__FIELDS)).toObject();
|
||||
QJsonObject relations = json.value(QStringLiteral(__FOREIGN_KEYS)).toObject();
|
||||
Q_FOREACH (QString key, fields.keys()) {
|
||||
for (auto &key: fields.keys()) {
|
||||
QJsonObject fieldObject = fields.value(key).toObject();
|
||||
//TODO: use FieldModel(QJsonObject) ctor
|
||||
auto *f = new FieldModel;
|
||||
f->name = fieldObject.value(QStringLiteral(__NAME)).toString();
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
f->type = static_cast<QMetaType::Type>(QMetaType::fromName(fieldObject.value(QStringLiteral(__TYPE)).toString().toLatin1()).id());
|
||||
#else
|
||||
f->type = static_cast<QMetaType::Type>(QMetaType::type(fieldObject.value(QStringLiteral(__TYPE)).toString().toLatin1().data()));
|
||||
f->typeName = QString::fromUtf8(QMetaType::typeName(f->type));
|
||||
#endif
|
||||
f->typeName = QString::fromUtf8(METATYPE_TO_NAME(f->type));
|
||||
|
||||
if(fieldObject.contains(QStringLiteral(__nut_NOT_NULL)))
|
||||
f->notNull = fieldObject.value(QStringLiteral(__nut_NOT_NULL)).toBool();
|
||||
|
|
@ -266,7 +277,7 @@ TableModel::TableModel(const QJsonObject &json, const QString &tableName) : _typ
|
|||
_fields.append(f);
|
||||
}
|
||||
|
||||
Q_FOREACH (QString key, relations.keys()) {
|
||||
for (auto &key: relations.keys()) {
|
||||
QJsonObject relObject = fields.value(key).toObject();
|
||||
_foreignKeys.append(new RelationModel(relObject));
|
||||
}
|
||||
|
|
@ -284,10 +295,10 @@ QJsonObject TableModel::toJson() const
|
|||
QJsonObject fieldsObj;
|
||||
QJsonObject foreignKeysObj;
|
||||
|
||||
Q_FOREACH (FieldModel *f, _fields) {
|
||||
for (auto &f: _fields) {
|
||||
QJsonObject fieldObj;
|
||||
fieldObj.insert(QStringLiteral(__NAME), f->name);
|
||||
fieldObj.insert(QStringLiteral(__TYPE), QString::fromUtf8(QVariant::typeToName(f->type)));
|
||||
fieldObj.insert(QStringLiteral(__TYPE), QString::fromUtf8(METATYPE_TO_NAME(f->type)));
|
||||
|
||||
if(f->length)
|
||||
fieldObj.insert(QStringLiteral(__nut_LEN), f->length);
|
||||
|
|
@ -309,7 +320,7 @@ QJsonObject TableModel::toJson() const
|
|||
|
||||
fieldsObj.insert(f->name, fieldObj);
|
||||
}
|
||||
Q_FOREACH (RelationModel *rel, _foreignKeys)
|
||||
for (auto &rel: _foreignKeys)
|
||||
foreignKeysObj.insert(rel->localColumn, rel->toJson());
|
||||
|
||||
obj.insert(QStringLiteral(__FIELDS), fieldsObj);
|
||||
|
|
@ -320,7 +331,7 @@ QJsonObject TableModel::toJson() const
|
|||
|
||||
RelationModel *TableModel::foreignKey(const QString &otherTable) const
|
||||
{
|
||||
Q_FOREACH (RelationModel *fk, _foreignKeys)
|
||||
for (auto &fk: _foreignKeys)
|
||||
if(fk->masterClassName == otherTable)
|
||||
return fk;
|
||||
|
||||
|
|
@ -329,7 +340,7 @@ RelationModel *TableModel::foreignKey(const QString &otherTable) const
|
|||
|
||||
RelationModel *TableModel::foreignKeyByField(const QString &fieldName) const
|
||||
{
|
||||
Q_FOREACH (RelationModel *fk, _foreignKeys)
|
||||
for (auto &fk: _foreignKeys)
|
||||
if(fk->localColumn == fieldName)
|
||||
return fk;
|
||||
|
||||
|
|
@ -339,9 +350,9 @@ RelationModel *TableModel::foreignKeyByField(const QString &fieldName) const
|
|||
QString TableModel::toString() const
|
||||
{
|
||||
QStringList sl;
|
||||
Q_FOREACH (FieldModel *f, _fields)
|
||||
for (auto &f: _fields)
|
||||
sl.append(f->name + QStringLiteral(" ")
|
||||
+ QString::fromUtf8(QVariant::typeToName(f->type)));
|
||||
+ QString::fromUtf8(METATYPE_TO_NAME(f->type)));
|
||||
|
||||
QString ret = QStringLiteral("%1 (%2)")
|
||||
.arg(_name, sl.join(QStringLiteral(", ")));
|
||||
|
|
@ -350,7 +361,7 @@ QString TableModel::toString() const
|
|||
|
||||
QString TableModel::primaryKey() const
|
||||
{
|
||||
Q_FOREACH (FieldModel *f, _fields)
|
||||
for (auto &f: _fields)
|
||||
if(f->isPrimaryKey)
|
||||
return f->name;
|
||||
return QString();
|
||||
|
|
@ -381,7 +392,7 @@ QJsonObject FieldModel::toJson() const
|
|||
{
|
||||
QJsonObject fieldObj;
|
||||
fieldObj.insert(QStringLiteral(__NAME), name);
|
||||
fieldObj.insert(QStringLiteral(__TYPE), QString::fromUtf8(QVariant::typeToName(type)));
|
||||
fieldObj.insert(QStringLiteral(__TYPE), QString::fromUtf8(METATYPE_TO_NAME(type)));
|
||||
fieldObj.insert(QStringLiteral(__nut_LEN), length);
|
||||
fieldObj.insert(QStringLiteral(__nut_NOT_NULL), notNull);
|
||||
fieldObj.insert(QStringLiteral(__nut_UNIQUE), isUnique);
|
||||
|
|
@ -424,3 +435,5 @@ bool operator !=(const RelationModel &l, const RelationModel &r)
|
|||
}
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
class QJsonObject;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
class TableModel;
|
||||
|
|
@ -135,4 +137,6 @@ private:
|
|||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // TABLEMODEL_H
|
||||
|
|
|
|||
|
|
@ -16,4 +16,3 @@ HEADERS += \
|
|||
SOURCES += \
|
||||
$$PWD/phrase.cpp
|
||||
|
||||
include($$PWD/3rdparty/serializer/src/src.pri)
|
||||
|
|
|
|||
|
|
@ -17,11 +17,11 @@ include(phrases/phrases.pri)
|
|||
include(models/models.pri)
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/phrase.h
|
||||
$$PWD/phrase.h \
|
||||
$$PWD/nut_p.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/phrase.cpp
|
||||
|
||||
load(qt_module)
|
||||
|
||||
include($$PWD/3rdparty/serializer/src/src.pri)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
/**************************************************************************
|
||||
**
|
||||
** 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/>.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Nut API. This header
|
||||
// file may change from version to version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#ifndef NUT_P_H
|
||||
#define NUT_P_H
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
# define VARIANT_TYPE_COMPARE(v, t) v.typeId() == QMetaType::Q##t
|
||||
# define VARIANT_TYPE_COMPARE_X(v, vt, mt) v.typeId() == QMetaType::mt
|
||||
# define METATYPE_TO_NAME(type) QMetaType(type).name()
|
||||
# define METATYPE_ID(v) static_cast<QMetaType::Type>(v.typeId())
|
||||
#else
|
||||
# define VARIANT_TYPE_COMPARE(v, t) v.type() == QVariant::t
|
||||
# define VARIANT_TYPE_COMPARE_X(v, vt, mt) v.type() == QVariant::vt
|
||||
# define METATYPE_TO_NAME(type) QMetaType::typeName(type)
|
||||
# define METATYPE_ID(v) static_cast<QMetaType::Type>(v.type())
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -19,3 +19,6 @@
|
|||
**************************************************************************/
|
||||
|
||||
#include "phrase.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -21,6 +21,9 @@
|
|||
#ifndef PHRASE_H
|
||||
#define PHRASE_H
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
|
||||
#include <QtNut/nut_global.h>
|
||||
#include <QtNut/conditionalphrase.h>
|
||||
#include <QtNut/abstractfieldphrase.h>
|
||||
|
|
@ -35,4 +38,7 @@
|
|||
#include <QtNut/fieldphrase_qstring.h>
|
||||
#include <QtNut/fieldphrase_bool.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // PHRASE_H
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@
|
|||
#include "abstractfieldphrase.h"
|
||||
#include <QDebug>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
AbstractFieldPhrase::AbstractFieldPhrase(PhraseData *d) : data(d)
|
||||
|
|
@ -137,3 +139,5 @@ AbstractFieldPhrase AbstractFieldPhrase::operator !()
|
|||
}
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@
|
|||
#include <QtNut/conditionalphrase.h>
|
||||
#include <QtNut/phraselist.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
class PhraseData;
|
||||
|
|
@ -46,7 +48,7 @@ public:
|
|||
ConditionalPhrase in(QList<T> list)
|
||||
{
|
||||
QVariantList vlist;
|
||||
Q_FOREACH (T t, list)
|
||||
for (auto &t: list)
|
||||
vlist.append(QVariant::fromValue(t));
|
||||
|
||||
return ConditionalPhrase(this, PhraseData::In, vlist);
|
||||
|
|
@ -87,4 +89,6 @@ protected:
|
|||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // ABSTRACTFIELDPHRASE_H
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@
|
|||
#include "assignmentphrase.h"
|
||||
#include "phrasedata.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
AssignmentPhrase::AssignmentPhrase(PhraseData *d) : data(d)
|
||||
|
|
@ -61,3 +63,5 @@ AssignmentPhrase::~AssignmentPhrase()
|
|||
}
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@
|
|||
|
||||
#include <QtNut/nut_global.h>
|
||||
#include <QtNut/assignmentphraselist.h>
|
||||
#include <QtNut/NutGlobal>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
|
|
@ -45,5 +48,6 @@ public:
|
|||
};
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // ASSIGNMENTPHRASE_H
|
||||
|
|
|
|||
|
|
@ -22,8 +22,9 @@
|
|||
#include "phrasedata.h"
|
||||
#include "assignmentphrase.h"
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
AssignmentPhraseList AssignmentPhrase::operator &(const AssignmentPhrase &other)
|
||||
{
|
||||
|
|
@ -68,18 +69,14 @@ AssignmentPhraseList AssignmentPhraseList::operator &(const AssignmentPhrase
|
|||
|
||||
AssignmentPhraseList::~AssignmentPhraseList()
|
||||
{
|
||||
// Q_FOREACH (PhraseData *d, data)
|
||||
// if (!d->ref.deref())
|
||||
// delete d;
|
||||
// qDeleteAll(data);
|
||||
// data.clear();
|
||||
}
|
||||
|
||||
void AssignmentPhraseList::incAllDataParents()
|
||||
{
|
||||
Q_FOREACH (PhraseData *d, data)
|
||||
for (auto &d: data)
|
||||
d->ref.ref();
|
||||
}
|
||||
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
|
||||
#include <QtNut/nut_global.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
class PhraseData;
|
||||
|
|
@ -47,4 +49,6 @@ private:
|
|||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // ASSIGNMENTPHRASELIST_H
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
#include "conditionalphrase.h"
|
||||
#include "phrasedata.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
ConditionalPhrase::ConditionalPhrase() : data(nullptr)
|
||||
|
|
@ -232,3 +234,5 @@ ConditionalPhrase operator >=(ConditionalPhrase &&l, ConditionalPhrase &&r)
|
|||
}
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
|
||||
#include <QtNut/phrasedata.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
class PhraseData;
|
||||
|
|
@ -89,7 +91,8 @@ ConditionalPhrase NUT_EXPORT operator <=(ConditionalPhrase &&l, ConditionalPhras
|
|||
ConditionalPhrase NUT_EXPORT operator >(ConditionalPhrase &&l, ConditionalPhrase &&r);
|
||||
ConditionalPhrase NUT_EXPORT operator >=(ConditionalPhrase &&l, ConditionalPhrase &&r);
|
||||
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // CONDITIONALPHRASE_H
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
#include <QtNut/nut_global.h>
|
||||
#include <QtNut/abstractfieldphrase.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
template<typename T>
|
||||
|
|
@ -60,4 +62,6 @@ Q_OUTOFLINE_TEMPLATE ConditionalPhrase FieldPhrase<T>::operator ==(const QVarian
|
|||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // FIELDPHRASE_H
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "fieldphrase_bool.h"
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
#include <QtNut/fieldphrase.h>
|
||||
#include <QtNut/fieldphrase.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
template<>
|
||||
|
|
@ -35,4 +37,6 @@ public:
|
|||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // NUT_FIELDPHRASE_BOOL_H
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
#include "fieldphrase_date.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
FieldPhrase<QDate>::FieldPhrase(const char *className, const char *s) :
|
||||
|
|
@ -145,3 +147,5 @@ COMMON_OPERATORS_IMPL(QTime)
|
|||
COMMON_OPERATORS_IMPL(QDateTime)
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@
|
|||
|
||||
#include <QtNut/fieldphrase.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
#define COMMON_OPERATORS_DECL(T) \
|
||||
|
|
@ -121,4 +123,6 @@ public:
|
|||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // DATEPHRASE_H
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
#include <QtNut/abstractfieldphrase.h>
|
||||
#include <QtNut/fieldphrase.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
template<>
|
||||
|
|
@ -36,4 +38,6 @@ public:
|
|||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // NUT_FIELDPHRASE_QSTRING_H
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
#include <QtNut/fieldphrase.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
#define SPECIALIZATION_NUMERIC_MEMBER(type, op, cond) \
|
||||
|
|
@ -85,4 +87,6 @@ SPECIALIZATION_NUMERIC_TYPE(float)
|
|||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // NUMERICPHRASE_H
|
||||
|
|
|
|||
|
|
@ -20,18 +20,20 @@
|
|||
|
||||
#include "phrasedata.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
PhraseData::PhraseData()
|
||||
: className(""), fieldName(""), type(Field), operatorCond(NotAssign),
|
||||
left(nullptr), right(nullptr), operand(QVariant::Invalid), isNot(false),
|
||||
left(nullptr), right(nullptr), operand(), isNot(false),
|
||||
ref(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), ref(1)
|
||||
operand(), isNot(false), ref(1)
|
||||
{ }
|
||||
|
||||
PhraseData::PhraseData(PhraseData *l, PhraseData::Condition o)
|
||||
|
|
@ -115,3 +117,5 @@ void PhraseData::cleanUp(PhraseData *d)
|
|||
}
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
|
||||
#include <QtNut/nut_global.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
class NUT_EXPORT PhraseData
|
||||
|
|
@ -122,4 +124,6 @@ private:
|
|||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // PHRASEDATA_H
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
#include "phrasedatalist.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
PhraseDataList::PhraseDataList() : QList<PhraseData*>()
|
||||
|
|
@ -43,7 +45,7 @@ void PhraseDataList::append(PhraseData *d)
|
|||
|
||||
void PhraseDataList::append(QList<PhraseData *> &dl)
|
||||
{
|
||||
Q_FOREACH (PhraseData *d, dl)
|
||||
for (auto &d: dl)
|
||||
d->ref.ref();
|
||||
QList<PhraseData*>::append(dl);
|
||||
}
|
||||
|
|
@ -59,3 +61,5 @@ PhraseDataList::~PhraseDataList()
|
|||
}
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
|
||||
#include <QtNut/phrasedata.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
class NUT_EXPORT PhraseDataList : public QList<PhraseData*>
|
||||
|
|
@ -37,4 +39,6 @@ public:
|
|||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // PHRASEDATALIST_H
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@
|
|||
#include "abstractfieldphrase.h"
|
||||
#include "phraselist.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
PhraseList::PhraseList() : isValid(false)
|
||||
|
|
@ -83,7 +85,7 @@ PhraseList PhraseList::operator |(const AbstractFieldPhrase &other) {
|
|||
|
||||
void PhraseList::incAllDataParents()
|
||||
{
|
||||
// Q_FOREACH (PhraseData *d, data)
|
||||
// for (auto &d: data)
|
||||
// d->parents++;
|
||||
}
|
||||
|
||||
|
|
@ -92,3 +94,5 @@ PhraseList PhraseList::operator |(PhraseList &other) {
|
|||
}
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
#include <QtNut/nut_global.h>
|
||||
#include <QtNut/phrasedatalist.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
class AbstractFieldPhrase;
|
||||
|
|
@ -51,4 +53,6 @@ private:
|
|||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // PHRASELIST_H
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
#include "dbgeography.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
DbGeography::DbGeography() : m_longitude(0), m_latitude(0)
|
||||
|
|
@ -79,3 +81,5 @@ DbGeography::operator QVariant()
|
|||
}
|
||||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
|
||||
#include <QtNut/nut_global.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
NUT_BEGIN_NAMESPACE
|
||||
|
||||
class NUT_EXPORT DbGeography
|
||||
|
|
@ -50,6 +52,8 @@ public:
|
|||
|
||||
NUT_END_NAMESPACE
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
Q_DECLARE_METATYPE(NUT_WRAP_NAMESPACE(DbGeography))
|
||||
|
||||
#endif // DBGEOGRAPHY_H
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
# Generated from tests.pro.
|
||||
|
||||
if(QT_BUILD_STANDALONE_TESTS)
|
||||
# Add qt_find_package calls for extra dependencies that need to be found when building
|
||||
# the standalone tests here.
|
||||
endif()
|
||||
qt_build_tests()
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
# Generated from auto.pro.
|
||||
|
||||
add_subdirectory(tst_basic)
|
||||
add_subdirectory(tst_benckmark)
|
||||
add_subdirectory(tst_datatypes)
|
||||
add_subdirectory(tst_phrases)
|
||||
add_subdirectory(tst_properties)
|
||||
add_subdirectory(tst_qttypes)
|
||||
add_subdirectory(tst_quuid)
|
||||
add_subdirectory(tst_generators)
|
||||
add_subdirectory(tst_upgrades)
|
||||
add_subdirectory(tst_json)
|
||||
add_subdirectory(tst_datetime)
|
||||
|
|
@ -4,13 +4,19 @@
|
|||
#include <QtCore/qglobal.h>
|
||||
#include <QtCore/QDateTime>
|
||||
#include <QtNut/table.h>
|
||||
#include <QSharedPointer>
|
||||
|
||||
#ifdef NUT_NAMESPACE
|
||||
using namespace NUT_NAMESPACE;
|
||||
#endif
|
||||
|
||||
class Post;
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
Q_MOC_INCLUDE("user.h")
|
||||
Q_MOC_INCLUDE("post.h")
|
||||
#endif
|
||||
|
||||
class User;
|
||||
class Post;
|
||||
class Comment : public Table
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
|
|||
|
|
@ -13,18 +13,17 @@
|
|||
.arg(QString::fromUtf8(__func__))
|
||||
|
||||
|
||||
/*#define DRIVER QStringLiteral("QSQLITE")
|
||||
#define HOST QString()
|
||||
#define USERNAME QString()
|
||||
#define PASSWORD QString()
|
||||
*/
|
||||
#define DATABASE QStringLiteral("nut_test_%1_db") \
|
||||
.arg(QString::fromUtf8(metaObject()->className())).toLower()
|
||||
#include "test_params.h"
|
||||
|
||||
/*
|
||||
#define DRIVER QStringLiteral("QMYSQL")
|
||||
#define HOST QStringLiteral("192.168.10.2")
|
||||
#define USERNAME QStringLiteral("root")
|
||||
#define PASSWORD QStringLiteral("lDexDJGvQwx20sfgtsetDSupmn9")
|
||||
*/
|
||||
|
||||
#define DATABASE QStringLiteral("nut_test_%1_db") \
|
||||
.arg(QString::fromUtf8(metaObject()->className())).toLower()
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
# define OS "Linux"
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ QT += nut
|
|||
CONFIG += testcase
|
||||
|
||||
DEFINES += NUT_PATH=\\\"$$PWD/../../\\\"
|
||||
DEFINES += NUT_PRINT_DEBUG_INFO
|
||||
|
||||
runtarget.target = run-tests
|
||||
runtarget.CONFIG = recursive
|
||||
|
|
|
|||
|
|
@ -6,11 +6,17 @@
|
|||
#include <QtNut/table.h>
|
||||
#include <QtNut/database.h>
|
||||
#include <QtNut/databasemodel.h>
|
||||
#include <QSharedPointer>
|
||||
|
||||
#ifdef NUT_NAMESPACE
|
||||
using namespace NUT_NAMESPACE;
|
||||
#endif
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
Q_MOC_INCLUDE("comment.h")
|
||||
Q_MOC_INCLUDE("score.h")
|
||||
#endif
|
||||
|
||||
class Comment;
|
||||
class Score;
|
||||
class Post : public Table
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#include "user.h"
|
||||
#include "post.h"
|
||||
|
||||
Score::Score(QObject *parent) : Nut::Table(parent)
|
||||
Score::Score(QObject *parent) : NUT_WRAP_NAMESPACE(Table)(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,10 +3,17 @@
|
|||
|
||||
#include <QUuid>
|
||||
#include <QtNut/table.h>
|
||||
#include <QSharedPointer>
|
||||
#include <QMetaType>
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
Q_MOC_INCLUDE("user.h")
|
||||
Q_MOC_INCLUDE("post.h")
|
||||
#endif
|
||||
|
||||
class User;
|
||||
class Post;
|
||||
class Score : public Nut::Table
|
||||
class Score : public NUT_WRAP_NAMESPACE(Table)
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
@ -15,6 +22,8 @@ class Score : public Nut::Table
|
|||
|
||||
NUT_DECLARE_FIELD(int, score, score, setScore)
|
||||
|
||||
NUT_DECLARE_FIELD(int, condition, condition, setCondition)
|
||||
|
||||
NUT_FOREIGN_KEY_DECLARE(Post, int, post, post, setPost)
|
||||
NUT_FOREIGN_KEY_DECLARE(User, QUuid, author, author, setAuthor)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
#define DRIVER QStringLiteral("QSQLITE")
|
||||
#define HOST QString()
|
||||
#define USERNAME QString()
|
||||
#define PASSWORD QString()
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
#include <QtGlobal>
|
||||
|
||||
#ifdef DATABASE
|
||||
#undef DATABASE
|
||||
#endif
|
||||
|
||||
#define DATABASE \
|
||||
QStringLiteral("DRIVER={SQL Server Native Client 11.0};Server=localhost;DATABASE=nut_test_%1_db;UID=sa;PWD=NUT_sa_PASS_1_???;") \
|
||||
.arg(QString::fromUtf8(metaObject()->className()).toLower())
|
||||
|
||||
#define DRIVER QStringLiteral("QODBC")
|
||||
#define HOST QLatin1String("")
|
||||
#define USERNAME QLatin1String("")
|
||||
#define PASSWORD QLatin1String("")
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
#define DRIVER QStringLiteral("QMYSQL")
|
||||
#define HOST QStringLiteral("localhost")
|
||||
#define USERNAME QStringLiteral("root")
|
||||
#define PASSWORD QStringLiteral("root")
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
#define DRIVER QStringLiteral("QPSQL")
|
||||
#define HOST QStringLiteral("localhost")
|
||||
#define USERNAME QStringLiteral("postgres")
|
||||
#define PASSWORD QStringLiteral("postgres")
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
#define DRIVER QStringLiteral("QSQLITE")
|
||||
#define HOST QString()
|
||||
#define USERNAME QString()
|
||||
#define PASSWORD QString()
|
||||
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
#include "user.h"
|
||||
|
||||
User::User(QObject *tableSet) : Table(tableSet),
|
||||
m_comments(new TableSet<Comment>(this)),
|
||||
m_scores(new TableSet<Score>(this))
|
||||
User::User(QObject *tableSet) : Nut::Table(tableSet),
|
||||
m_comments(new Nut::TableSet<Comment>(this)),
|
||||
m_scores(new Nut::TableSet<Score>(this))
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,14 +6,20 @@
|
|||
|
||||
#include <QtCore/QUuid>
|
||||
#include <QtCore/QString>
|
||||
#include <QSharedPointer>
|
||||
|
||||
#ifdef NUT_NAMESPACE
|
||||
using namespace NUT_NAMESPACE;
|
||||
#endif
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
Q_MOC_INCLUDE("comment.h")
|
||||
Q_MOC_INCLUDE("score.h")
|
||||
#endif
|
||||
|
||||
class Comment;
|
||||
class Score;
|
||||
class User : public Nut::Table
|
||||
class User : public NUT_WRAP_NAMESPACE(Table)
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,13 @@
|
|||
using namespace NUT_NAMESPACE;
|
||||
#endif
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
Q_MOC_INCLUDE("user.h")
|
||||
Q_MOC_INCLUDE("post.h")
|
||||
Q_MOC_INCLUDE("score.h")
|
||||
Q_MOC_INCLUDE("comment.h")
|
||||
#endif
|
||||
|
||||
class Post;
|
||||
class Comment;
|
||||
class User;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue