mirror of
https://github.com/silverqx/TinyORM.git
synced 2026-02-11 12:59:16 -06:00
Merge branch 'migrations' into develop
This commit is contained in:
@@ -53,8 +53,10 @@ set(minReqMsvcVersion 19.29)
|
||||
set(minRecGCCVersion 10.2)
|
||||
set(minRecClangVersion 12)
|
||||
# Packages
|
||||
set(minQtVersion 5.15.2)
|
||||
set(minRangeV3Version 0.11.0)
|
||||
set(minQtVersion 5.15.2)
|
||||
set(minRangeV3Version 0.11.0)
|
||||
# tabulate doesn't provide Package Version File
|
||||
#set(minTabulateVersion 1.4.0)
|
||||
|
||||
# Make minimum toolchain version a requirement
|
||||
tiny_toolchain_requirement(
|
||||
@@ -157,11 +159,25 @@ option is disabled, then only the query builder without ORM is compiled."
|
||||
DISABLED TINYORM_DISABLE_ORM
|
||||
)
|
||||
|
||||
target_optional_compile_definitions(${TinyOrm_target}
|
||||
PUBLIC
|
||||
FEATURE NAME TOM
|
||||
DEFAULT ON
|
||||
DESCRIPTION "Controls the compilation of all tom related source code (command \
|
||||
line interface)."
|
||||
DISABLED TINYORM_DISABLE_TOM
|
||||
)
|
||||
# Depends on the TOM option so defined here
|
||||
feature_option_dependent(TOM_EXAMPLE
|
||||
"Build the tom command-line application example" OFF
|
||||
"TOM" TOM_EXAMPLE-NOTFOUND
|
||||
)
|
||||
|
||||
# TinyORM library header and source files
|
||||
# ---
|
||||
|
||||
include(TinySources)
|
||||
tiny_sources(${TinyOrm_target}_headers ${TinyOrm_target}_sources)
|
||||
tinyorm_sources(${TinyOrm_target}_headers ${TinyOrm_target}_sources)
|
||||
|
||||
target_sources(${TinyOrm_target} PRIVATE
|
||||
${${TinyOrm_target}_headers}
|
||||
@@ -212,7 +228,6 @@ target_compile_definitions(${TinyOrm_target}
|
||||
$<$<NOT:$<CONFIG:Debug>>:TINYORM_NO_DEBUG>
|
||||
# Do not log queries
|
||||
$<$<NOT:$<CONFIG:Debug>>:TINYORM_NO_DEBUG_SQL>
|
||||
PRIVATE
|
||||
# Debug build
|
||||
$<$<CONFIG:Debug>:TINYORM_DEBUG>
|
||||
# Log queries with a time measurement
|
||||
@@ -237,10 +252,49 @@ else()
|
||||
endif()
|
||||
|
||||
# Enable code needed by tests, eg. connection overriding in the Model
|
||||
if(BUILD_TESTS)
|
||||
if(BUILD_TESTS AND ORM)
|
||||
target_compile_definitions(${TinyOrm_target} PUBLIC TINYORM_TESTS_CODE)
|
||||
endif()
|
||||
|
||||
# TinyTom related header and source files
|
||||
# ---
|
||||
|
||||
if(TOM)
|
||||
tinytom_sources(${TomExample_target}_headers ${TomExample_target}_sources)
|
||||
|
||||
target_sources(${TinyOrm_target} PRIVATE
|
||||
${${TomExample_target}_headers}
|
||||
${${TomExample_target}_sources}
|
||||
)
|
||||
endif()
|
||||
|
||||
# TinyTom related specific configuration
|
||||
# ---
|
||||
|
||||
if(TOM)
|
||||
target_include_directories(${TinyOrm_target} PUBLIC
|
||||
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/tom/include>"
|
||||
)
|
||||
endif()
|
||||
|
||||
# TinyTom related defines
|
||||
# ---
|
||||
|
||||
if(TOM)
|
||||
target_compile_definitions(${TinyOrm_target}
|
||||
PUBLIC
|
||||
# Release build
|
||||
$<$<NOT:$<CONFIG:Debug>>:TINYTOM_NO_DEBUG>
|
||||
# Debug build
|
||||
$<$<CONFIG:Debug>:TINYTOM_DEBUG>
|
||||
)
|
||||
|
||||
# Enable code needed by tests (modify the migrate:status command for tests need)
|
||||
if(BUILD_TESTS)
|
||||
target_compile_definitions(${TinyOrm_target} PUBLIC TINYTOM_TESTS_CODE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Windows resource and manifest files
|
||||
# ---
|
||||
|
||||
@@ -285,6 +339,12 @@ if(MYSQL_PING)
|
||||
target_link_libraries(${TinyOrm_target} PRIVATE MySQL::MySQL)
|
||||
endif()
|
||||
|
||||
if(TOM)
|
||||
# tabulate doesn't provide Package Version File
|
||||
tiny_find_package(tabulate CONFIG REQUIRED)
|
||||
target_link_libraries(${TinyOrm_target} PUBLIC tabulate::tabulate)
|
||||
endif()
|
||||
|
||||
# Build auto tests
|
||||
# ---
|
||||
|
||||
@@ -295,6 +355,13 @@ if(BUILD_TESTS)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
# Build examples
|
||||
# ---
|
||||
|
||||
if(TOM_EXAMPLE)
|
||||
add_subdirectory(examples)
|
||||
endif()
|
||||
|
||||
# Deployment
|
||||
# ---
|
||||
|
||||
@@ -355,10 +422,20 @@ set_package_properties(range-v3
|
||||
if(MYSQL_PING)
|
||||
set_package_properties(MySQL
|
||||
PROPERTIES
|
||||
# URL and DESCRIPTION are already set by Find-module Package (FindMySQL.cmake)
|
||||
TYPE REQUIRED
|
||||
PURPOSE "Provides MySQL ping, enables MySqlConnection::pingDatabase()"
|
||||
)
|
||||
endif()
|
||||
if(TOM)
|
||||
set_package_properties(tabulate
|
||||
PROPERTIES
|
||||
URL "https://github.com/p-ranav/tabulate/"
|
||||
DESCRIPTION "Table Maker for Modern C++"
|
||||
TYPE REQUIRED
|
||||
PURPOSE "Used by the tom in the migrate:status command"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(VERBOSE_CONFIGURE)
|
||||
if(NOT TINY_IS_MULTI_CONFIG AND NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS += src
|
||||
SUBDIRS = src
|
||||
|
||||
tom_example {
|
||||
SUBDIRS += examples
|
||||
examples.depends = src
|
||||
}
|
||||
|
||||
# Can be enabled by CONFIG += build_tests when the qmake.exe for the project is called
|
||||
build_tests {
|
||||
SUBDIRS += tests
|
||||
tests.depends = src
|
||||
|
||||
!build_pass: message("Build TinyORM unit tests.")
|
||||
}
|
||||
|
||||
@@ -143,10 +143,12 @@ macro(tiny_init_tiny_variables_pre)
|
||||
# a main package name
|
||||
set(TinyOrm_ns TinyOrm)
|
||||
set(TinyUtils_ns TinyUtils)
|
||||
set(TomExample_ns tom)
|
||||
# Target names
|
||||
set(CommonConfig_target CommonConfig)
|
||||
set(TinyOrm_target TinyOrm)
|
||||
set(TinyUtils_target TinyUtils)
|
||||
set(TomExample_target tom)
|
||||
|
||||
get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
set(TINY_IS_MULTI_CONFIG "${isMultiConfig}" CACHE INTERNAL
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
# TinyORM library header and source files
|
||||
# Create header and source files lists and return them
|
||||
function(tiny_sources out_headers out_sources)
|
||||
function(tinyorm_sources out_headers out_sources)
|
||||
|
||||
# ORM headers section
|
||||
set(headers)
|
||||
|
||||
if(TINY_EXTERN_CONSTANTS)
|
||||
@@ -131,10 +132,17 @@ function(tiny_sources out_headers out_sources)
|
||||
tiny/types/connectionoverride.hpp
|
||||
tiny/types/syncchanges.hpp
|
||||
tiny/utils/attribute.hpp
|
||||
)
|
||||
endif()
|
||||
|
||||
# Headers used in both ORM and TOM
|
||||
if(ORM OR TOM)
|
||||
list(APPEND headers
|
||||
tiny/utils/string.hpp
|
||||
)
|
||||
endif()
|
||||
|
||||
# ORM sources section
|
||||
set(sources)
|
||||
|
||||
if(TINY_EXTERN_CONSTANTS)
|
||||
@@ -203,6 +211,12 @@ function(tiny_sources out_headers out_sources)
|
||||
tiny/tinytypes.cpp
|
||||
tiny/types/syncchanges.cpp
|
||||
tiny/utils/attribute.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
# Sources needed in both ORM and TOM
|
||||
if(ORM OR TOM)
|
||||
list(APPEND sources
|
||||
tiny/utils/string.cpp
|
||||
)
|
||||
endif()
|
||||
@@ -215,5 +229,91 @@ function(tiny_sources out_headers out_sources)
|
||||
|
||||
set(${out_headers} ${headers} PARENT_SCOPE)
|
||||
set(${out_sources} ${sources} PARENT_SCOPE)
|
||||
|
||||
endfunction()
|
||||
|
||||
# TinyTom application header and source files
|
||||
# Create header and source files lists and return them
|
||||
function(tinytom_sources out_headers out_sources)
|
||||
|
||||
# Tom headers section
|
||||
set(headers)
|
||||
|
||||
list(APPEND headers
|
||||
application.hpp
|
||||
commands/command.hpp
|
||||
commands/database/wipecommand.hpp
|
||||
commands/environmentcommand.hpp
|
||||
commands/helpcommand.hpp
|
||||
commands/inspirecommand.hpp
|
||||
commands/listcommand.hpp
|
||||
commands/make/migrationcommand.hpp
|
||||
# commands/make/projectcommand.hpp
|
||||
commands/make/stubs/migrationstubs.hpp
|
||||
commands/make/stubs/projectstubs.hpp
|
||||
commands/migrations/freshcommand.hpp
|
||||
commands/migrations/installcommand.hpp
|
||||
commands/migrations/migratecommand.hpp
|
||||
commands/migrations/refreshcommand.hpp
|
||||
commands/migrations/resetcommand.hpp
|
||||
commands/migrations/rollbackcommand.hpp
|
||||
commands/migrations/statuscommand.hpp
|
||||
concerns/callscommands.hpp
|
||||
concerns/confirmable.hpp
|
||||
concerns/interactswithio.hpp
|
||||
concerns/printsoptions.hpp
|
||||
config.hpp
|
||||
exceptions/invalidargumenterror.hpp
|
||||
exceptions/invalidtemplateargumenterror.hpp
|
||||
exceptions/logicerror.hpp
|
||||
exceptions/runtimeerror.hpp
|
||||
exceptions/tomerror.hpp
|
||||
migration.hpp
|
||||
migrationcreator.hpp
|
||||
migrationrepository.hpp
|
||||
migrator.hpp
|
||||
terminal.hpp
|
||||
tomtypes.hpp
|
||||
version.hpp
|
||||
)
|
||||
|
||||
# Tom sources section
|
||||
set(sources)
|
||||
|
||||
list(APPEND sources
|
||||
application.cpp
|
||||
commands/command.cpp
|
||||
commands/database/wipecommand.cpp
|
||||
commands/environmentcommand.cpp
|
||||
commands/helpcommand.cpp
|
||||
commands/inspirecommand.cpp
|
||||
commands/listcommand.cpp
|
||||
commands/make/migrationcommand.cpp
|
||||
# commands/make/projectcommand.cpp
|
||||
commands/migrations/freshcommand.cpp
|
||||
commands/migrations/installcommand.cpp
|
||||
commands/migrations/migratecommand.cpp
|
||||
commands/migrations/refreshcommand.cpp
|
||||
commands/migrations/resetcommand.cpp
|
||||
commands/migrations/rollbackcommand.cpp
|
||||
commands/migrations/statuscommand.cpp
|
||||
concerns/callscommands.cpp
|
||||
concerns/confirmable.cpp
|
||||
concerns/interactswithio.cpp
|
||||
concerns/printsoptions.cpp
|
||||
exceptions/tomlogicerror.cpp
|
||||
exceptions/tomruntimeerror.cpp
|
||||
migrationcreator.cpp
|
||||
migrationrepository.cpp
|
||||
migrator.cpp
|
||||
terminal.cpp
|
||||
)
|
||||
|
||||
list(SORT headers)
|
||||
list(SORT sources)
|
||||
|
||||
list(TRANSFORM headers PREPEND "${CMAKE_SOURCE_DIR}/tom/include/tom/")
|
||||
list(TRANSFORM sources PREPEND "${CMAKE_SOURCE_DIR}/tom/src/tom/")
|
||||
|
||||
set(${out_headers} ${headers} PARENT_SCOPE)
|
||||
set(${out_sources} ${sources} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
@@ -3,7 +3,7 @@ include(TinyResourceAndManifest)
|
||||
# Configure passed auto test
|
||||
function(tiny_configure_test name)
|
||||
|
||||
set(options INCLUDE_MODELS)
|
||||
set(options INCLUDE_MIGRATIONS INCLUDE_MODELS)
|
||||
cmake_parse_arguments(PARSE_ARGV 1 TINY "${options}" "" "")
|
||||
|
||||
if(DEFINED TINY_UNPARSED_ARGUMENTS)
|
||||
@@ -54,6 +54,12 @@ ${TINY_UNPARSED_ARGUMENTS}")
|
||||
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>"
|
||||
)
|
||||
|
||||
if(TINY_INCLUDE_MIGRATIONS)
|
||||
target_include_directories(${name} PRIVATE
|
||||
"$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/tests/database>"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(TINY_INCLUDE_MODELS)
|
||||
target_include_directories(${name} PRIVATE
|
||||
"$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/tests/models>"
|
||||
@@ -62,8 +68,6 @@ ${TINY_UNPARSED_ARGUMENTS}")
|
||||
|
||||
target_link_libraries(${name}
|
||||
PRIVATE
|
||||
Qt${QT_VERSION_MAJOR}::Core
|
||||
Qt${QT_VERSION_MAJOR}::Sql
|
||||
Qt${QT_VERSION_MAJOR}::Test
|
||||
${TinyOrm_ns}::${TinyUtils_target}
|
||||
${TinyOrm_ns}::${TinyOrm_target}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"supports": "!(uwp | arm | android | emscripten)",
|
||||
"dependencies": [
|
||||
"range-v3",
|
||||
"tabulate",
|
||||
"qt5-base",
|
||||
{
|
||||
"name": "vcpkg-cmake",
|
||||
|
||||
@@ -21,6 +21,11 @@ win32-g++|win32-clang-g++ {
|
||||
# Enable ccache wrapper
|
||||
CONFIG *= tiny_ccache
|
||||
|
||||
# Includes
|
||||
# tabulate
|
||||
INCLUDEPATH += $$quote(C:/msys64/home/xyz/vcpkg/installed/x64-mingw-dynamic/include/)
|
||||
QMAKE_CXXFLAGS += -isystem $$shell_quote(C:/msys64/home/xyz/vcpkg/installed/x64-mingw-dynamic/include/)
|
||||
|
||||
# Libraries
|
||||
# MySQL C library
|
||||
# Find with the pkg-config (preferred), shared build only
|
||||
@@ -64,7 +69,7 @@ else:win32-msvc {
|
||||
else:unix {
|
||||
# Includes
|
||||
# range-v3
|
||||
QMAKE_CXXFLAGS += -isystem $$quote(/home/xyz/vcpkg/installed/x64-linux/include/)
|
||||
QMAKE_CXXFLAGS += -isystem $$shell_quote(/home/xyz/vcpkg/installed/x64-linux/include/)
|
||||
|
||||
# Libraries
|
||||
# MySQL C library
|
||||
|
||||
@@ -617,7 +617,7 @@ TINY_TINYORM_BUILDS_DIR = $$quote($$TINY_MAIN_DIR/TinyOrm-builds-qmake)
|
||||
include($$TINY_MAIN_DIR/TinyORM/qmake/TinyOrm.pri)
|
||||
|
||||
# TinyORM header files
|
||||
QMAKE_CXXFLAGS += -isystem $$quote($$TINY_MAIN_DIR/TinyORM/include/)
|
||||
QMAKE_CXXFLAGS += -isystem $$shell_quote($$TINY_MAIN_DIR/TinyORM/include/)
|
||||
|
||||
# TinyORM library path
|
||||
LIBS += $$quote(-L$$TINY_TINYORM_BUILDS_DIR/build-TinyOrm-Desktop_Qt_5_15_2_GCC_64bit-Debug/src/debug/)
|
||||
@@ -625,7 +625,7 @@ LIBS += -lTinyOrm
|
||||
|
||||
# vcpkg - range-v3
|
||||
# ---
|
||||
QMAKE_CXXFLAGS += -isystem $$quote(../../../../vcpkg/installed/x64-linux/include/)
|
||||
QMAKE_CXXFLAGS += -isystem $$shell_quote(../../../../vcpkg/installed/x64-linux/include/)
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
|
||||
@@ -456,7 +456,7 @@ TINY_TINYORM_BUILDS_DIR = $$quote($$TINY_MAIN_DIR/TinyOrm-builds-qmake)
|
||||
include($$TINY_MAIN_DIR/TinyORM/qmake/TinyOrm.pri)
|
||||
|
||||
# TinyORM header files
|
||||
QMAKE_CXXFLAGS += -isystem $$quote($$TINY_MAIN_DIR/TinyORM/include/)
|
||||
QMAKE_CXXFLAGS += -isystem $$shell_quote($$TINY_MAIN_DIR/TinyORM/include/)
|
||||
|
||||
# TinyORM library path
|
||||
LIBS += $$quote(-L$$TINY_TINYORM_BUILDS_DIR/build-TinyOrm-Desktop_Qt_5_15_2_MSVC2019_64bit-Debug/src/debug/)
|
||||
@@ -464,7 +464,7 @@ LIBS += -lTinyOrm
|
||||
|
||||
# vcpkg - range-v3
|
||||
# ---
|
||||
QMAKE_CXXFLAGS += -isystem $$quote(../../../../vcpkg/installed/x64-linux/include/)
|
||||
QMAKE_CXXFLAGS += -isystem $$shell_quote(../../../../vcpkg/installed/x64-linux/include/)
|
||||
```
|
||||
|
||||
:::tip
|
||||
|
||||
3
examples/CMakeLists.txt
Normal file
3
examples/CMakeLists.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
if(TOM_EXAMPLE)
|
||||
add_subdirectory(tom)
|
||||
endif()
|
||||
7
examples/examples.pro
Normal file
7
examples/examples.pro
Normal file
@@ -0,0 +1,7 @@
|
||||
TEMPLATE = subdirs
|
||||
|
||||
tom_example:!disable_tom {
|
||||
SUBDIRS += tom
|
||||
|
||||
!build_pass: message("Build the tom example.")
|
||||
}
|
||||
74
examples/tom/CMakeLists.txt
Normal file
74
examples/tom/CMakeLists.txt
Normal file
@@ -0,0 +1,74 @@
|
||||
# Tom command-line application example
|
||||
# ---
|
||||
|
||||
# Initialize Project Version
|
||||
# ---
|
||||
|
||||
include(TinyHelpers)
|
||||
tiny_read_version(TINY_VERSION
|
||||
TINY_VERSION_MAJOR TINY_VERSION_MINOR TINY_VERSION_PATCH TINY_VERSION_TWEAK
|
||||
VERSION_HEADER "${CMAKE_SOURCE_DIR}/tom/include/tom/version.hpp"
|
||||
PREFIX TINYTOM
|
||||
HEADER_FOR "${TomExample_ns}"
|
||||
)
|
||||
|
||||
# Basic project
|
||||
# ---
|
||||
|
||||
project(${TomExample_ns}
|
||||
DESCRIPTION "Tom console for TinyORM"
|
||||
HOMEPAGE_URL "https://silverqx.github.io/TinyORM/"
|
||||
LANGUAGES CXX
|
||||
VERSION ${TINY_VERSION}
|
||||
)
|
||||
|
||||
# Tom command-line application
|
||||
# ---
|
||||
|
||||
add_executable(${TomExample_target}
|
||||
main.cpp
|
||||
)
|
||||
add_executable(${TomExample_ns}::${TomExample_target} ALIAS ${TomExample_target})
|
||||
|
||||
# Tom command-line application specific configuration
|
||||
# ---
|
||||
|
||||
set_target_properties(${TomExample_target}
|
||||
PROPERTIES
|
||||
C_VISIBILITY_PRESET "hidden"
|
||||
CXX_VISIBILITY_PRESET "hidden"
|
||||
VISIBILITY_INLINES_HIDDEN YES
|
||||
VERSION ${PROJECT_VERSION}
|
||||
)
|
||||
|
||||
target_include_directories(${TomExample_target} PRIVATE
|
||||
"$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/tests/database>"
|
||||
)
|
||||
|
||||
# Tom command-line application defines
|
||||
# ---
|
||||
|
||||
target_compile_definitions(${TomExample_target}
|
||||
PRIVATE
|
||||
PROJECT_TOMEXAMPLE
|
||||
)
|
||||
|
||||
# Windows resource and manifest files
|
||||
# ---
|
||||
|
||||
# Find icons, tom/version.hpp, and Windows manifest file for MinGW
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
tiny_set_rc_flags("-I \"${CMAKE_SOURCE_DIR}/tom/resources\"")
|
||||
endif()
|
||||
|
||||
include(TinyResourceAndManifest)
|
||||
tiny_resource_and_manifest(${TomExample_target}
|
||||
OUTPUT_DIR "${TINY_BUILD_GENDIR}/tmp/"
|
||||
RESOURCES_DIR "${CMAKE_SOURCE_DIR}/tom/resources"
|
||||
)
|
||||
|
||||
# Resolve and link dependencies
|
||||
# ---
|
||||
|
||||
# Unconditional dependencies
|
||||
target_link_libraries(${TomExample_target} PRIVATE ${TinyOrm_ns}::${TinyOrm_target})
|
||||
39
examples/tom/conf.pri.example
Normal file
39
examples/tom/conf.pri.example
Normal file
@@ -0,0 +1,39 @@
|
||||
# Migrations header files
|
||||
# ---
|
||||
|
||||
# Tests' migrations as example migrations
|
||||
include($$TINYORM_SOURCE_TREE/tests/database/migrations.pri)
|
||||
# Or include yours migrations
|
||||
#include(/home/xyz/your_project/database/migrations.pri)
|
||||
|
||||
# Dependencies include and library paths
|
||||
# ---
|
||||
|
||||
# MinGW
|
||||
win32-g++|win32-clang-g++ {
|
||||
# Enable ccache wrapper
|
||||
CONFIG *= tiny_ccache
|
||||
|
||||
# Includes
|
||||
# tabulate
|
||||
INCLUDEPATH += $$quote(C:/msys64/home/xyz/vcpkg/installed/x64-mingw-dynamic/include/)
|
||||
QMAKE_CXXFLAGS += -isystem $$shell_quote(C:/msys64/home/xyz/vcpkg/installed/x64-mingw-dynamic/include/)
|
||||
|
||||
# Use faster linker
|
||||
# CONFIG *= use_lld_linker does not work on MinGW
|
||||
QMAKE_LFLAGS *= -fuse-ld=lld
|
||||
}
|
||||
else:win32-msvc {
|
||||
# Includes
|
||||
# range-v3 and tabulate
|
||||
INCLUDEPATH += $$quote(E:/xyz/vcpkg/installed/x64-windows/include/)
|
||||
}
|
||||
else:unix {
|
||||
# Includes
|
||||
# range-v3 and tabulate
|
||||
QMAKE_CXXFLAGS += -isystem $$shell_quote(/home/xyz/vcpkg/installed/x64-linux/include/)
|
||||
|
||||
# Use faster linkers
|
||||
clang: CONFIG *= use_lld_linker
|
||||
else: CONFIG *= use_gold_linker
|
||||
}
|
||||
99
examples/tom/main.cpp
Normal file
99
examples/tom/main.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
#include <orm/db.hpp>
|
||||
|
||||
#include <tom/application.hpp>
|
||||
|
||||
#include "migrations/2014_10_12_000000_create_posts_table.hpp"
|
||||
#include "migrations/2014_10_12_100000_add_factor_column_to_posts_table.hpp"
|
||||
#include "migrations/2014_10_12_200000_create_properties_table.hpp"
|
||||
#include "migrations/2014_10_12_300000_create_phones_table.hpp"
|
||||
|
||||
using Orm::Constants::H127001;
|
||||
using Orm::Constants::P3306;
|
||||
using Orm::Constants::QMYSQL;
|
||||
using Orm::Constants::SYSTEM;
|
||||
using Orm::Constants::UTF8MB4;
|
||||
using Orm::Constants::charset_;
|
||||
using Orm::Constants::collation_;
|
||||
using Orm::Constants::database_;
|
||||
using Orm::Constants::driver_;
|
||||
using Orm::Constants::engine_;
|
||||
using Orm::Constants::host_;
|
||||
using Orm::Constants::InnoDB;
|
||||
using Orm::Constants::isolation_level;
|
||||
using Orm::Constants::options_;
|
||||
using Orm::Constants::password_;
|
||||
using Orm::Constants::port_;
|
||||
using Orm::Constants::prefix_;
|
||||
using Orm::Constants::prefix_indexes;
|
||||
using Orm::Constants::strict_;
|
||||
using Orm::Constants::timezone_;
|
||||
using Orm::Constants::username_;
|
||||
|
||||
using Orm::DatabaseManager;
|
||||
using Orm::DB;
|
||||
|
||||
using TomApplication = Tom::Application;
|
||||
|
||||
using namespace Migrations; // NOLINT(google-build-using-namespace)
|
||||
|
||||
/*! Build the database manager instance and add a database connection. */
|
||||
std::shared_ptr<DatabaseManager> setupManager();
|
||||
|
||||
/*! c++ main function. */
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
try {
|
||||
// Ownership of the shared_ptr()
|
||||
auto db = setupManager();
|
||||
|
||||
return TomApplication(argc, argv, db, "TOM_EXAMPLE_ENV")
|
||||
.migrations<
|
||||
_2014_10_12_000000_create_posts_table,
|
||||
_2014_10_12_100000_add_factor_column_to_posts_table,
|
||||
_2014_10_12_200000_create_properties_table,
|
||||
_2014_10_12_300000_create_phones_table>()
|
||||
// Fire it up 🔥🚀✨
|
||||
.run();
|
||||
|
||||
} catch (const std::exception &e) {
|
||||
|
||||
TomApplication::logException(e);
|
||||
}
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
std::shared_ptr<DatabaseManager> setupManager()
|
||||
{
|
||||
// Ownership of the shared_ptr()
|
||||
return DB::create({
|
||||
{driver_, QMYSQL},
|
||||
{host_, qEnvironmentVariable("DB_MYSQL_HOST", H127001)},
|
||||
{port_, qEnvironmentVariable("DB_MYSQL_PORT", P3306)},
|
||||
{database_, qEnvironmentVariable("DB_MYSQL_DATABASE", "")},
|
||||
{username_, qEnvironmentVariable("DB_MYSQL_USERNAME", "")},
|
||||
{password_, qEnvironmentVariable("DB_MYSQL_PASSWORD", "")},
|
||||
{charset_, qEnvironmentVariable("DB_MYSQL_CHARSET", UTF8MB4)},
|
||||
{collation_, qEnvironmentVariable("DB_MYSQL_COLLATION",
|
||||
QStringLiteral("utf8mb4_0900_ai_ci"))},
|
||||
{timezone_, SYSTEM},
|
||||
{prefix_, ""},
|
||||
{prefix_indexes, true},
|
||||
{strict_, true},
|
||||
{isolation_level, QStringLiteral("REPEATABLE READ")},
|
||||
{engine_, InnoDB},
|
||||
{options_, QVariantHash()},
|
||||
},
|
||||
QLatin1String("tinyorm_tom"));
|
||||
}
|
||||
|
||||
/* Alternative syntax to instantiate migration classes. */
|
||||
// return TomApplication(argc, argv, db, "TOM_EXAMPLE_ENV",
|
||||
// {
|
||||
// std::make_shared<_2014_10_12_000000_create_posts_table>(),
|
||||
// std::make_shared<_2014_10_12_100000_add_factor_column_to_posts_table>(),
|
||||
// std::make_shared<_2014_10_12_200000_create_properties_table>(),
|
||||
// std::make_shared<_2014_10_12_300000_create_phones_table>(),
|
||||
// })
|
||||
// // Fire it up 🔥🚀✨
|
||||
// .run();
|
||||
53
examples/tom/tom.pro
Normal file
53
examples/tom/tom.pro
Normal file
@@ -0,0 +1,53 @@
|
||||
QT *= core sql
|
||||
QT -= gui
|
||||
|
||||
TEMPLATE = app
|
||||
TARGET = tom
|
||||
|
||||
# TinyTom example application specific configuration
|
||||
# ---
|
||||
|
||||
CONFIG *= console
|
||||
|
||||
include($$TINYORM_SOURCE_TREE/qmake/tom.pri)
|
||||
|
||||
# TinyTom example application defines
|
||||
# ---
|
||||
|
||||
DEFINES += PROJECT_TOMEXAMPLE
|
||||
|
||||
# TinyTom defines
|
||||
# ---
|
||||
# this define is not provided in the qmake/tom.pri
|
||||
|
||||
# Enable code needed by tests (modify the migrate:status command for tests need)
|
||||
build_tests: \
|
||||
DEFINES *= TINYTOM_TESTS_CODE
|
||||
|
||||
# TinyTom example application header and source files
|
||||
# ---
|
||||
|
||||
SOURCES += $$PWD/main.cpp
|
||||
|
||||
# Deployment
|
||||
# ---
|
||||
|
||||
win32-msvc:CONFIG(debug, debug|release) {
|
||||
win32-msvc: target.path = C:/optx64/$${TARGET}
|
||||
# else: unix:!android: target.path = /opt/$${TARGET}/bin
|
||||
!isEmpty(target.path): INSTALLS += target
|
||||
}
|
||||
|
||||
# User Configuration
|
||||
# ---
|
||||
|
||||
exists(conf.pri): \
|
||||
include(conf.pri)
|
||||
|
||||
#else:is_vcpkg_build: \
|
||||
# include(../qmake/vcpkgconf.pri)
|
||||
|
||||
else: \
|
||||
error( "'conf.pri' for 'tom' example project does not exist. See an example\
|
||||
configuration in 'examples/tom/conf.pri.example' or call 'vcpkg install'\
|
||||
in the project's root." )
|
||||
@@ -126,6 +126,9 @@ headersList += \
|
||||
$$PWD/orm/tiny/types/connectionoverride.hpp \
|
||||
$$PWD/orm/tiny/types/syncchanges.hpp \
|
||||
$$PWD/orm/tiny/utils/attribute.hpp \
|
||||
|
||||
!disable_orm|!disable_tom: \
|
||||
headersList += \
|
||||
$$PWD/orm/tiny/utils/string.hpp \
|
||||
|
||||
HEADERS += $$sorted(headersList)
|
||||
|
||||
@@ -179,7 +179,7 @@ namespace SchemaNs
|
||||
/*! Get the query grammar used by the connection. */
|
||||
inline QueryGrammar &getQueryGrammar();
|
||||
/*! Get the schema grammar used by the connection. */
|
||||
inline const SchemaGrammar &getSchemaGrammar() const;
|
||||
const SchemaGrammar &getSchemaGrammar();
|
||||
/*! Get a schema builder instance for the connection. */
|
||||
virtual std::unique_ptr<SchemaBuilder> getSchemaBuilder();
|
||||
/*! Get the query post processor used by the connection. */
|
||||
@@ -401,11 +401,6 @@ namespace SchemaNs
|
||||
return *m_queryGrammar;
|
||||
}
|
||||
|
||||
const SchemaGrammar &DatabaseConnection::getSchemaGrammar() const
|
||||
{
|
||||
return *m_schemaGrammar;
|
||||
}
|
||||
|
||||
const QueryProcessor &DatabaseConnection::getPostProcessor() const
|
||||
{
|
||||
return *m_postProcessor;
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
#include "orm/macros/systemheader.hpp"
|
||||
TINY_SYSTEM_HEADER
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "orm/exceptions/logicerror.hpp"
|
||||
|
||||
TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
@@ -14,7 +12,7 @@ TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
namespace Orm::Exceptions
|
||||
{
|
||||
|
||||
/*! Domain exception. */
|
||||
/*! TinyORM Domain exception. */
|
||||
class DomainError : public LogicError
|
||||
{
|
||||
/*! Inherit constructors. */
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
#include "orm/macros/systemheader.hpp"
|
||||
TINY_SYSTEM_HEADER
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "orm/exceptions/logicerror.hpp"
|
||||
|
||||
TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
@@ -14,7 +12,7 @@ TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
namespace Orm::Exceptions
|
||||
{
|
||||
|
||||
/*! Invalid argument exception. */
|
||||
/*! TinyORM invalid argument exception. */
|
||||
class InvalidArgumentError : public LogicError
|
||||
{
|
||||
/*! Inherit constructors. */
|
||||
|
||||
@@ -12,7 +12,7 @@ TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
namespace Orm::Exceptions
|
||||
{
|
||||
|
||||
/*! Invalid format exception. */
|
||||
/*! TinyORM invalid format exception. */
|
||||
class InvalidFormatError : public LogicError
|
||||
{
|
||||
/*! Inherit constructors. */
|
||||
|
||||
@@ -12,7 +12,7 @@ TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
namespace Orm::Exceptions
|
||||
{
|
||||
|
||||
/*! Invalid template argument exception. */
|
||||
/*! TinyORM invalid template argument exception. */
|
||||
class InvalidTemplateArgumentError : public InvalidArgumentError
|
||||
{
|
||||
/*! Inherit constructors. */
|
||||
|
||||
@@ -10,7 +10,6 @@ TINY_SYSTEM_HEADER
|
||||
#include <stdexcept>
|
||||
|
||||
#include "orm/exceptions/ormerror.hpp"
|
||||
#include "orm/macros/commonnamespace.hpp"
|
||||
#include "orm/macros/export.hpp"
|
||||
|
||||
TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
@@ -18,7 +17,7 @@ TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
namespace Orm::Exceptions
|
||||
{
|
||||
|
||||
/*! Logic exception. */
|
||||
/*! TinyORM Logic exception. */
|
||||
class SHAREDLIB_EXPORT LogicError :
|
||||
public std::logic_error,
|
||||
public OrmError
|
||||
@@ -28,16 +27,18 @@ namespace Orm::Exceptions
|
||||
explicit LogicError(const char *message);
|
||||
/*! QString constructor. */
|
||||
explicit LogicError(const QString &message);
|
||||
/*! std::string constructor. */
|
||||
explicit LogicError(const std::string &message);
|
||||
|
||||
/*! Return exception message as a QString. */
|
||||
const QString &message() const;
|
||||
inline const QString &message() const noexcept;
|
||||
|
||||
protected:
|
||||
/*! Exception message. */
|
||||
QString m_message = what();
|
||||
};
|
||||
|
||||
inline const QString &LogicError::message() const
|
||||
const QString &LogicError::message() const noexcept
|
||||
{
|
||||
return m_message;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
namespace Orm::Exceptions
|
||||
{
|
||||
|
||||
/*! Database query exception. */
|
||||
/*! TinyORM Database query exception. */
|
||||
class SHAREDLIB_EXPORT QueryError : public SqlError
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -10,7 +10,6 @@ TINY_SYSTEM_HEADER
|
||||
#include <stdexcept>
|
||||
|
||||
#include "orm/exceptions/ormerror.hpp"
|
||||
#include "orm/macros/commonnamespace.hpp"
|
||||
#include "orm/macros/export.hpp"
|
||||
|
||||
TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
@@ -18,7 +17,7 @@ TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
namespace Orm::Exceptions
|
||||
{
|
||||
|
||||
/*! Runtime exception. */
|
||||
/*! TinyORM Runtime exception. */
|
||||
class SHAREDLIB_EXPORT RuntimeError :
|
||||
public std::runtime_error,
|
||||
public OrmError
|
||||
@@ -28,16 +27,18 @@ namespace Orm::Exceptions
|
||||
explicit RuntimeError(const char *message);
|
||||
/*! QString constructor. */
|
||||
explicit RuntimeError(const QString &message);
|
||||
/*! std::string constructor. */
|
||||
explicit RuntimeError(const std::string &message);
|
||||
|
||||
/*! Return exception message as a QString. */
|
||||
const QString &message() const;
|
||||
inline const QString &message() const noexcept;
|
||||
|
||||
protected:
|
||||
/*! Exception message. */
|
||||
QString m_message = what();
|
||||
};
|
||||
|
||||
inline const QString &RuntimeError::message() const
|
||||
const QString &RuntimeError::message() const noexcept
|
||||
{
|
||||
return m_message;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
namespace Orm::Exceptions
|
||||
{
|
||||
|
||||
/*! SqlError exception, wrapper for the QSqlError. */
|
||||
/*! TinyORM SqlError exception, wrapper for the QSqlError. */
|
||||
class SHAREDLIB_EXPORT SqlError : public RuntimeError
|
||||
{
|
||||
public:
|
||||
@@ -24,7 +24,7 @@ namespace Orm::Exceptions
|
||||
SqlError(const QString &message, const QSqlError &error);
|
||||
|
||||
/*! Get the original Qt SQL error. */
|
||||
const QSqlError &getSqlError() const;
|
||||
inline const QSqlError &getSqlError() const noexcept;
|
||||
|
||||
protected:
|
||||
/*! Internal ctor for use from descendants to avoid an error message
|
||||
@@ -38,6 +38,11 @@ namespace Orm::Exceptions
|
||||
QSqlError m_sqlError;
|
||||
};
|
||||
|
||||
const QSqlError &SqlError::getSqlError() const noexcept
|
||||
{
|
||||
return m_sqlError;
|
||||
}
|
||||
|
||||
} // namespace Orm::Exceptions
|
||||
|
||||
TINYORM_END_COMMON_NAMESPACE
|
||||
|
||||
@@ -12,7 +12,7 @@ TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
namespace Orm::Exceptions
|
||||
{
|
||||
|
||||
/*! Sql transaction exception. */
|
||||
/*! TinyORM Sql transaction exception. */
|
||||
class SqlTransactionError : public SqlError
|
||||
{
|
||||
/*! Inherit constructors. */
|
||||
|
||||
@@ -10,6 +10,7 @@ TINY_SYSTEM_HEADER
|
||||
# define TINYORM_BEGIN_COMMON_NAMESPACE namespace TINYORM_COMMON_NAMESPACE {
|
||||
# define TINYORM_END_COMMON_NAMESPACE }
|
||||
#else
|
||||
# define TINYORM_COMMON_NAMESPACE
|
||||
# define TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
# define TINYORM_END_COMMON_NAMESPACE
|
||||
#endif
|
||||
|
||||
@@ -9,7 +9,7 @@ TINY_SYSTEM_HEADER
|
||||
|
||||
#include "orm/macros/commonnamespace.hpp"
|
||||
#include "orm/macros/export.hpp"
|
||||
// CUR check this on clean project silverqx
|
||||
// CUR tom, check this on clean project silverqx
|
||||
// Include the blueprint here so a user doesn't have to
|
||||
#include "orm/schema/blueprint.hpp"
|
||||
|
||||
|
||||
@@ -16,17 +16,19 @@ TINY_SYSTEM_HEADER
|
||||
|
||||
TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
|
||||
namespace Orm::Tiny
|
||||
{
|
||||
namespace TinyUtils = Orm::Tiny::Utils;
|
||||
|
||||
namespace Concerns
|
||||
namespace Orm::Tiny::Concerns
|
||||
{
|
||||
|
||||
/*! Model attributes. */
|
||||
template<typename Derived, AllRelationsConcept ...AllRelations>
|
||||
class HasAttributes
|
||||
{
|
||||
// CUR utils, use this using pattern also for all Orm::Utils silverqx
|
||||
/*! Alias for the attribute utils. */
|
||||
using AttributeUtils = Orm::Tiny::Utils::Attribute;
|
||||
/*! Alias for the string utils. */
|
||||
using StringUtils = Orm::Tiny::Utils::String;
|
||||
|
||||
public:
|
||||
/*! Set a given attribute on the model. */
|
||||
Derived &setAttribute(const QString &key, QVariant value);
|
||||
@@ -258,7 +260,7 @@ namespace Concerns
|
||||
const bool sync)
|
||||
{
|
||||
m_attributes.reserve(attributes.size());
|
||||
m_attributes = TinyUtils::Attribute::removeDuplicitKeys(attributes);
|
||||
m_attributes = AttributeUtils::removeDuplicitKeys(attributes);
|
||||
|
||||
// Build attributes hash
|
||||
m_attributesHash.clear();
|
||||
@@ -831,7 +833,7 @@ namespace Concerns
|
||||
and format a Carbon object from this timestamp. This allows flexibility
|
||||
when defining your date fields as they might be UNIX timestamps here. */
|
||||
if (value.canConvert<QString>() &&
|
||||
TinyUtils::String::isNumber(value.value<QString>())
|
||||
StringUtils::isNumber(value.value<QString>())
|
||||
)
|
||||
// TODO switch ms accuracy? For the u_dateFormat too? silverqx
|
||||
return QDateTime::fromSecsSinceEpoch(value.value<qint64>());
|
||||
@@ -884,8 +886,7 @@ namespace Concerns
|
||||
/* Static cast this to a child's instance type (CRTP) */
|
||||
TINY_CRTP_MODEL_WITH_BASE_DEFINITIONS(HasAttributes)
|
||||
|
||||
} // namespace Concerns
|
||||
} // namespace Orm::Tiny
|
||||
} // namespace Orm::Tiny::Concerns
|
||||
|
||||
TINYORM_END_COMMON_NAMESPACE
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
TINY_SYSTEM_HEADER
|
||||
|
||||
#ifdef __GNUG__
|
||||
#include <map>
|
||||
# include <map>
|
||||
#else
|
||||
#include <unordered_map>
|
||||
# include <unordered_map>
|
||||
#endif
|
||||
#include <unordered_set>
|
||||
|
||||
@@ -955,7 +955,6 @@ namespace Concerns
|
||||
QString
|
||||
HasRelationships<Derived, AllRelations...>::guessBelongsToRelationInternal() const
|
||||
{
|
||||
// TODO reliability, also add Orm::Tiny::Utils::String::studly silverqx
|
||||
auto relation = Orm::Utils::Type::classPureBasename<Related>();
|
||||
|
||||
relation[0] = relation[0].toLower();
|
||||
|
||||
@@ -16,7 +16,7 @@ TINY_SYSTEM_HEADER
|
||||
#include "orm/tiny/modelproxies.hpp"
|
||||
#include "orm/tiny/tinybuilder.hpp"
|
||||
#ifdef TINYORM_TESTS_CODE
|
||||
#include "orm/tiny/types/connectionoverride.hpp"
|
||||
# include "orm/tiny/types/connectionoverride.hpp"
|
||||
#endif
|
||||
|
||||
TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
@@ -63,6 +63,10 @@ namespace Orm::Tiny
|
||||
// Used by TinyBuilder::eagerLoadRelations()
|
||||
friend TinyBuilder<Derived>;
|
||||
|
||||
/*! Alias for the attribute utils. */
|
||||
using AttributeUtils = Orm::Tiny::Utils::Attribute;
|
||||
/*! Alias for the string utils. */
|
||||
using StringUtils = Orm::Tiny::Utils::String;
|
||||
/*! Apply all the Model's template parameters to the passed T template
|
||||
argument. */
|
||||
template<template<typename ...> typename T>
|
||||
@@ -893,8 +897,7 @@ namespace Orm::Tiny
|
||||
if (table.isEmpty())
|
||||
const_cast<QString &>(model().u_table) =
|
||||
QStringLiteral("%1s").arg(
|
||||
TinyUtils::String::toSnake(
|
||||
Orm::Utils::Type::classPureBasename<Derived>()));
|
||||
StringUtils::snake(Orm::Utils::Type::classPureBasename<Derived>()));
|
||||
|
||||
return table;
|
||||
}
|
||||
@@ -940,8 +943,7 @@ namespace Orm::Tiny
|
||||
QString Model<Derived, AllRelations...>::getForeignKey() const
|
||||
{
|
||||
return QStringLiteral("%1_%2").arg(
|
||||
TinyUtils::String::toSnake(
|
||||
Orm::Utils::Type::classPureBasename<Derived>()),
|
||||
StringUtils::snake(Orm::Utils::Type::classPureBasename<Derived>()),
|
||||
getKeyName());
|
||||
}
|
||||
|
||||
@@ -1076,7 +1078,7 @@ namespace Orm::Tiny
|
||||
|
||||
if (!dirty.isEmpty()) {
|
||||
model().setKeysForSaveQuery(query).update(
|
||||
TinyUtils::Attribute::convertVectorToUpdateItem(dirty));
|
||||
AttributeUtils::convertVectorToUpdateItem(dirty));
|
||||
|
||||
this->syncChanges();
|
||||
|
||||
@@ -1327,3 +1329,22 @@ TINYORM_END_COMMON_NAMESPACE
|
||||
// CUR model, add whereBelongsTo, whereRelation, orWhereRelation silverqx
|
||||
// CUR schema, add tests for enum and set; and json and jsonb, storedAs / virtualAs silverqx
|
||||
// CUR propagation, https://ben.balter.com/2017/11/10/twelve-tips-for-growing-communities-around-your-open-source-project/ silverqx
|
||||
// CUR optimization, use Q_UNREACHABLE in all switch statements, of course where appropriate silverqx
|
||||
// TODO vcpkg, solve how to build tom (when solving vcpkg builds again), currently I have hardly added tabulate to the vcpkg.json port and also manifest file; it will have to be conditional base of the TINYORM_DISABLE_TOM macro silverqx
|
||||
// CUR tom docs, disable_tom and TINYORM_DISABLE_TOM to build.mdx, don't forget to add features and update dependencies (tabulate) in vcpkg.json silverqx
|
||||
// CUR schema, add tests for enum and set; and json and jsonb, storedAs / virtualAs silverqx
|
||||
// CUR compiler, enable /sdl on msvc https://docs.microsoft.com/en-us/cpp/build/reference/sdl-enable-additional-security-checks?view=msvc-170 silverqx
|
||||
// CUR cmake, update max. policy to 3.23 silverqx
|
||||
// CUR tom, add tabulate to comments where range-v3 is, all checked, only docs left silverqx
|
||||
// CUR tom, verify -isystem $$shell_quote() updated in docs silverqx
|
||||
// CUR tom, tom/conf.pri is used by who silverqx
|
||||
// CUR cmake, add messages about Building tom example, tests and ORM silverqx
|
||||
// CUR docs, remove target_link_libs() for transitive dependencies silverqx
|
||||
// CUR tests, move version test outside of the orm/ folder silverqx
|
||||
// CUR tom docs, write documentation silverqx
|
||||
// CUR tom, build on mingw, linux, build without pch and all common tasks that should run from time to time silverqx
|
||||
// CUR tom, update docs target_link_library() https://discourse.cmake.org/t/explicitly-link-against-public-interface-dependencies/5484/2 silverqx
|
||||
// CUR tom, provide somehow a custom path to migrations for the tom example, so the tom example can be used like real migration app silverqx
|
||||
// CUR tom, don't modify migrate:status command, rather extend it and add possibility to only call it through Application::runWithArguments() (this secure to not be able to call it from the cmd. line), do not show it in the list or help command output silverqx
|
||||
// CUR tom, think about remove TINYTOM_NO/_DEBUG and TINYTOM_TESTS_CODE and use TINYORM_ defines instead silverqx
|
||||
// BUG rc file © encoding silverqx
|
||||
|
||||
@@ -20,6 +20,9 @@ namespace Orm::Tiny::Relations
|
||||
template<typename PivotModel>
|
||||
class BasePivot : public Model<PivotModel>, public IsPivotModel
|
||||
{
|
||||
/*! Alias for the string utils. */
|
||||
using StringUtils = Orm::Tiny::Utils::String;
|
||||
|
||||
public:
|
||||
friend Model<PivotModel>;
|
||||
|
||||
@@ -234,8 +237,8 @@ namespace Orm::Tiny::Relations
|
||||
|
||||
// Get singularizes snake-case table name
|
||||
if (table.isEmpty())
|
||||
return TinyUtils::String::singular(
|
||||
TinyUtils::String::toSnake(
|
||||
return StringUtils::singular(
|
||||
StringUtils::snake(
|
||||
Orm::Utils::Type::classPureBasename<PivotModel>()));
|
||||
|
||||
return table;
|
||||
|
||||
@@ -25,8 +25,6 @@ TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
|
||||
namespace Orm::Tiny::Relations
|
||||
{
|
||||
namespace TinyUtils = Orm::Tiny::Utils;
|
||||
|
||||
class Pivot;
|
||||
|
||||
/*! TinyORM's 'Pivot' class. */
|
||||
@@ -46,6 +44,8 @@ namespace Orm::Tiny::Relations
|
||||
{
|
||||
Q_DISABLE_COPY(BelongsToMany)
|
||||
|
||||
/*! Alias for the attribute utils. */
|
||||
using AttributeUtils = Orm::Tiny::Utils::Attribute;
|
||||
/*! Model alias. */
|
||||
template<typename Derived>
|
||||
using BaseModel = Orm::Tiny::Model<Derived>;
|
||||
@@ -953,7 +953,7 @@ namespace Orm::Tiny::Relations
|
||||
return *instance;
|
||||
|
||||
return this->m_related->newInstance(
|
||||
TinyUtils::Attribute::joinAttributesForFirstOr(
|
||||
AttributeUtils::joinAttributesForFirstOr(
|
||||
attributes, values, this->m_relatedKey));
|
||||
}
|
||||
|
||||
@@ -969,7 +969,7 @@ namespace Orm::Tiny::Relations
|
||||
return *instance;
|
||||
|
||||
// NOTE api different, Eloquent doen't use values argument silverqx
|
||||
return create(TinyUtils::Attribute::joinAttributesForFirstOr(
|
||||
return create(AttributeUtils::joinAttributesForFirstOr(
|
||||
attributes, values, this->m_relatedKey),
|
||||
pivotValues, touch);
|
||||
}
|
||||
@@ -1154,7 +1154,7 @@ namespace Orm::Tiny::Relations
|
||||
we have inserted the records, we will touch the relationships if
|
||||
necessary and the function will return. */
|
||||
newPivotStatement()->insert(
|
||||
TinyUtils::Attribute::convertVectorsToMaps(
|
||||
AttributeUtils::convertVectorsToMaps(
|
||||
formatAttachRecords(ids, attributes)));
|
||||
else
|
||||
attachUsingCustomClass(ids, attributes);
|
||||
@@ -1200,7 +1200,7 @@ namespace Orm::Tiny::Relations
|
||||
we have inserted the records, we will touch the relationships if
|
||||
necessary and the function will return. */
|
||||
newPivotStatement()->insert(
|
||||
TinyUtils::Attribute::convertVectorsToMaps(
|
||||
AttributeUtils::convertVectorsToMaps(
|
||||
formatAttachRecords(idsWithAttributes)));
|
||||
else
|
||||
attachUsingCustomClass(idsWithAttributes);
|
||||
@@ -1334,7 +1334,7 @@ namespace Orm::Tiny::Relations
|
||||
int updated = -1;
|
||||
std::tie(updated, std::ignore) =
|
||||
newPivotStatementForId(id)->update(
|
||||
TinyUtils::Attribute::convertVectorToUpdateItem(
|
||||
AttributeUtils::convertVectorToUpdateItem(
|
||||
castAttributes(attributes)));
|
||||
|
||||
/* It will not touch if attributes size is 0, because this function is called
|
||||
|
||||
@@ -12,7 +12,6 @@ TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
|
||||
namespace Orm::Tiny::Relations
|
||||
{
|
||||
namespace TinyUtils = Orm::Tiny::Utils;
|
||||
|
||||
/*! Has one/many relation base class. */
|
||||
template<class Model, class Related>
|
||||
@@ -20,6 +19,9 @@ namespace Orm::Tiny::Relations
|
||||
{
|
||||
Q_DISABLE_COPY(HasOneOrMany)
|
||||
|
||||
/*! Alias for the attribute utils. */
|
||||
using AttributeUtils = Orm::Tiny::Utils::Attribute;
|
||||
|
||||
protected:
|
||||
/*! Protected constructor. */
|
||||
HasOneOrMany(std::unique_ptr<Related> &&related, Model &parent,
|
||||
@@ -199,7 +201,7 @@ namespace Orm::Tiny::Relations
|
||||
|
||||
auto newInstance =
|
||||
this->m_related->newInstance(
|
||||
TinyUtils::Attribute::joinAttributesForFirstOr(
|
||||
AttributeUtils::joinAttributesForFirstOr(
|
||||
attributes, values, this->m_relatedKey));
|
||||
|
||||
setForeignAttributesForCreate(newInstance);
|
||||
@@ -218,7 +220,7 @@ namespace Orm::Tiny::Relations
|
||||
if (instance)
|
||||
return *instance;
|
||||
|
||||
return create(TinyUtils::Attribute::joinAttributesForFirstOr(
|
||||
return create(AttributeUtils::joinAttributesForFirstOr(
|
||||
attributes, values, this->m_relatedKey));
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,9 @@ namespace Orm::Tiny
|
||||
// Used by TinyBuilderProxies::where/latest/oldest/update()
|
||||
friend BuilderProxies<Model>;
|
||||
|
||||
/*! Alias for the attribute utils. */
|
||||
using AttributeUtils = Orm::Tiny::Utils::Attribute;
|
||||
|
||||
public:
|
||||
/*! Constructor. */
|
||||
Builder(const QSharedPointer<QueryBuilder> &query, Model &model);
|
||||
@@ -348,9 +351,8 @@ namespace Orm::Tiny
|
||||
if (instance)
|
||||
return *instance;
|
||||
|
||||
return newModelInstance(
|
||||
TinyUtils::Attribute::joinAttributesForFirstOr(
|
||||
attributes, values, m_model.getKeyName()));
|
||||
return newModelInstance(AttributeUtils::joinAttributesForFirstOr(
|
||||
attributes, values, m_model.getKeyName()));
|
||||
}
|
||||
|
||||
template<typename Model>
|
||||
@@ -363,9 +365,8 @@ namespace Orm::Tiny
|
||||
return *instance;
|
||||
|
||||
auto newInstance =
|
||||
newModelInstance(
|
||||
TinyUtils::Attribute::joinAttributesForFirstOr(
|
||||
attributes, values, m_model.getKeyName()));
|
||||
newModelInstance(AttributeUtils::joinAttributesForFirstOr(
|
||||
attributes, values, m_model.getKeyName()));
|
||||
|
||||
newInstance.save();
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ namespace Query
|
||||
|
||||
namespace Tiny
|
||||
{
|
||||
namespace TinyUtils = Orm::Tiny::Utils;
|
||||
|
||||
/*! Contains proxy methods to the QueryBuilder. */
|
||||
template<typename Model>
|
||||
@@ -31,6 +30,8 @@ namespace Tiny
|
||||
{
|
||||
Q_DISABLE_COPY(BuilderProxies)
|
||||
|
||||
/*! Alias for the attribute utils. */
|
||||
using AttributeUtils = Orm::Tiny::Utils::Attribute;
|
||||
/*! JoinClause alias. */
|
||||
using JoinClause = Orm::Query::JoinClause;
|
||||
|
||||
@@ -439,14 +440,14 @@ namespace Tiny
|
||||
std::optional<QSqlQuery>
|
||||
BuilderProxies<Model>::insert(const QVector<AttributeItem> &values) const
|
||||
{
|
||||
return toBase().insert(TinyUtils::Attribute::convertVectorToMap(values));
|
||||
return toBase().insert(AttributeUtils::convertVectorToMap(values));
|
||||
}
|
||||
|
||||
template<typename Model>
|
||||
std::optional<QSqlQuery>
|
||||
BuilderProxies<Model>::insert(const QVector<QVector<AttributeItem>> &values) const
|
||||
{
|
||||
return toBase().insert(TinyUtils::Attribute::convertVectorsToMaps(values));
|
||||
return toBase().insert(AttributeUtils::convertVectorsToMaps(values));
|
||||
}
|
||||
|
||||
// FEATURE dilemma primarykey, Model::KeyType vs QVariant silverqx
|
||||
@@ -455,7 +456,7 @@ namespace Tiny
|
||||
BuilderProxies<Model>::insertGetId(const QVector<AttributeItem> &values,
|
||||
const QString &sequence) const
|
||||
{
|
||||
return toBase().insertGetId(TinyUtils::Attribute::convertVectorToMap(values),
|
||||
return toBase().insertGetId(AttributeUtils::convertVectorToMap(values),
|
||||
sequence);
|
||||
}
|
||||
|
||||
@@ -463,8 +464,7 @@ namespace Tiny
|
||||
std::tuple<int, std::optional<QSqlQuery>>
|
||||
BuilderProxies<Model>::insertOrIgnore(const QVector<AttributeItem> &values) const
|
||||
{
|
||||
return toBase().insertOrIgnore(
|
||||
TinyUtils::Attribute::convertVectorToMap(values));
|
||||
return toBase().insertOrIgnore(AttributeUtils::convertVectorToMap(values));
|
||||
}
|
||||
|
||||
template<typename Model>
|
||||
@@ -472,8 +472,7 @@ namespace Tiny
|
||||
BuilderProxies<Model>::insertOrIgnore(
|
||||
const QVector<QVector<AttributeItem>> &values) const
|
||||
{
|
||||
return toBase().insertOrIgnore(
|
||||
TinyUtils::Attribute::convertVectorsToMaps(values));
|
||||
return toBase().insertOrIgnore(AttributeUtils::convertVectorsToMaps(values));
|
||||
}
|
||||
|
||||
template<typename Model>
|
||||
|
||||
@@ -11,7 +11,7 @@ TINY_SYSTEM_HEADER
|
||||
#include <map>
|
||||
|
||||
#if defined(__clang__) || (defined(_MSC_VER) && _MSC_VER <= 1928)
|
||||
#include <range/v3/algorithm/unique.hpp>
|
||||
# include <range/v3/algorithm/unique.hpp>
|
||||
#endif
|
||||
|
||||
#include "orm/macros/commonnamespace.hpp"
|
||||
|
||||
@@ -9,33 +9,46 @@ TINY_SYSTEM_HEADER
|
||||
|
||||
TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
|
||||
namespace Orm::Tiny::Utils::Attribute
|
||||
namespace Orm::Tiny::Utils
|
||||
{
|
||||
/*! Convert a AttributeItem QVector to QVariantMap. */
|
||||
SHAREDLIB_EXPORT QVariantMap
|
||||
convertVectorToMap(const QVector<AttributeItem> &attributes);
|
||||
/*! Convert a vector of AttributeItem QVectors to the vector of QVariantMaps. */
|
||||
SHAREDLIB_EXPORT QVector<QVariantMap>
|
||||
convertVectorsToMaps(const QVector<QVector<AttributeItem>> &attributesVector);
|
||||
|
||||
/*! Convert a AttributeItem QVector to UpdateItem QVector. */
|
||||
SHAREDLIB_EXPORT QVector<UpdateItem>
|
||||
convertVectorToUpdateItem(const QVector<AttributeItem> &attributes);
|
||||
/*! Convert a AttributeItem QVector to UpdateItem QVector. */
|
||||
SHAREDLIB_EXPORT QVector<UpdateItem>
|
||||
convertVectorToUpdateItem(QVector<AttributeItem> &&attributes);
|
||||
/*! Library class for the database attribute. */
|
||||
class SHAREDLIB_EXPORT Attribute
|
||||
{
|
||||
Q_DISABLE_COPY(Attribute)
|
||||
|
||||
/*! Remove attributes which have duplicite keys and leave only the last one. */
|
||||
SHAREDLIB_EXPORT QVector<AttributeItem>
|
||||
removeDuplicitKeys(const QVector<AttributeItem> &attributes);
|
||||
public:
|
||||
/*! Deleted default constructor, this is a pure library class. */
|
||||
Attribute() = delete;
|
||||
/*! Deleted destructor. */
|
||||
~Attribute() = delete;
|
||||
|
||||
/*! Join attributes and values for firstOrXx methods. */
|
||||
SHAREDLIB_EXPORT QVector<AttributeItem>
|
||||
joinAttributesForFirstOr(const QVector<WhereItem> &attributes,
|
||||
const QVector<AttributeItem> &values,
|
||||
const QString &keyName);
|
||||
/*! Convert a AttributeItem QVector to QVariantMap. */
|
||||
static QVariantMap
|
||||
convertVectorToMap(const QVector<AttributeItem> &attributes);
|
||||
/*! Convert a vector of AttributeItem QVectors to the vector of QVariantMaps. */
|
||||
static QVector<QVariantMap>
|
||||
convertVectorsToMaps(const QVector<QVector<AttributeItem>> &attributesVector);
|
||||
|
||||
} // namespace Orm::Tiny::Utils::Attribute
|
||||
/*! Convert a AttributeItem QVector to UpdateItem QVector. */
|
||||
static QVector<UpdateItem>
|
||||
convertVectorToUpdateItem(const QVector<AttributeItem> &attributes);
|
||||
/*! Convert a AttributeItem QVector to UpdateItem QVector. */
|
||||
static QVector<UpdateItem>
|
||||
convertVectorToUpdateItem(QVector<AttributeItem> &&attributes);
|
||||
|
||||
/*! Remove attributes which have duplicite keys and leave only the last one. */
|
||||
static QVector<AttributeItem>
|
||||
removeDuplicitKeys(const QVector<AttributeItem> &attributes);
|
||||
|
||||
/*! Join attributes and values for firstOrXx methods. */
|
||||
static QVector<AttributeItem>
|
||||
joinAttributesForFirstOr(const QVector<WhereItem> &attributes,
|
||||
const QVector<AttributeItem> &values,
|
||||
const QString &keyName);
|
||||
};
|
||||
|
||||
} // namespace Orm::Tiny::Utils
|
||||
|
||||
TINYORM_END_COMMON_NAMESPACE
|
||||
|
||||
|
||||
@@ -7,23 +7,50 @@ TINY_SYSTEM_HEADER
|
||||
|
||||
#include <QString>
|
||||
|
||||
#ifndef TINYORM_DISABLE_TOM
|
||||
# include <vector>
|
||||
#endif
|
||||
|
||||
#include "orm/macros/commonnamespace.hpp"
|
||||
#include "orm/macros/export.hpp"
|
||||
|
||||
TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
|
||||
namespace Orm::Tiny::Utils::String
|
||||
namespace Orm::Tiny::Utils
|
||||
{
|
||||
/*! Convert a string to snake case. */
|
||||
SHAREDLIB_EXPORT QString toSnake(QString string);
|
||||
|
||||
/*! Get the singular form of an English word. */
|
||||
SHAREDLIB_EXPORT QString singular(const QString &string);
|
||||
/*! String related library class. */
|
||||
class SHAREDLIB_EXPORT String
|
||||
{
|
||||
Q_DISABLE_COPY(String)
|
||||
|
||||
/*! Check if the given string is the number, signed or unsigned. */
|
||||
SHAREDLIB_EXPORT bool isNumber(const QString &string);
|
||||
public:
|
||||
/*! Deleted default constructor, this is a pure library class. */
|
||||
String() = delete;
|
||||
/*! Deleted destructor. */
|
||||
~String() = delete;
|
||||
|
||||
} // namespace Orm::Tiny::Utils::String
|
||||
/*! Convert a string to snake case. */
|
||||
static QString snake(QString string, QChar delimiter = '_');
|
||||
/*! Convert a value to studly caps case. */
|
||||
static QString studly(QString string);
|
||||
|
||||
/*! Check if the given string is the number, signed or unsigned. */
|
||||
static bool isNumber(const QString &string, bool allowFloating = false);
|
||||
|
||||
#ifndef TINYORM_DISABLE_TOM
|
||||
/*! Split a string by the given width (not in the middle of a word). */
|
||||
static std::vector<QString>
|
||||
splitStringByWidth(const QString &string, int width);
|
||||
#endif
|
||||
|
||||
#ifndef TINYORM_DISABLE_ORM
|
||||
/*! Get the singular form of an English word. */
|
||||
static QString singular(const QString &string);
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace Orm::Tiny::Utils
|
||||
|
||||
TINYORM_END_COMMON_NAMESPACE
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ TINY_SYSTEM_HEADER
|
||||
#include <typeinfo>
|
||||
|
||||
#ifdef __GNUG__
|
||||
#include <cxxabi.h>
|
||||
# include <cxxabi.h>
|
||||
#endif
|
||||
|
||||
#include "orm/macros/commonnamespace.hpp"
|
||||
@@ -59,6 +59,9 @@ namespace Orm::Utils
|
||||
/*! Return a pretty function name in the following format: Xyz::function. */
|
||||
static QString prettyFunction(const QString &function);
|
||||
|
||||
/*! Determine whether a string is true bool value (false for "", "0", "false"). */
|
||||
static bool isTrue(const QString &value);
|
||||
|
||||
private:
|
||||
/*! Class name with or w/o a namespace and w/o template parameters, common
|
||||
code. */
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
// Excluded for the Resource compiler
|
||||
#ifndef RC_INVOKED
|
||||
#include "orm/macros/systemheader.hpp"
|
||||
# include "orm/macros/systemheader.hpp"
|
||||
TINY_SYSTEM_HEADER
|
||||
#endif
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#if defined __cplusplus
|
||||
/* Add C++ includes here */
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QHash>
|
||||
#include <QMap>
|
||||
#include <QSharedPointer>
|
||||
@@ -38,6 +39,7 @@
|
||||
#include <thread>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <typeindex>
|
||||
#include <typeinfo>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
@@ -30,3 +30,11 @@ CONFIG(release, debug|release): \
|
||||
# Log queries with a time measurement in debug build
|
||||
CONFIG(release, debug|release): \
|
||||
DEFINES *= TINYORM_NO_DEBUG_SQL
|
||||
|
||||
# TinyTom related defines
|
||||
# ---
|
||||
|
||||
# Release build
|
||||
CONFIG(release, debug|release): DEFINES += TINYTOM_NO_DEBUG
|
||||
# Debug build
|
||||
CONFIG(debug, debug|release): DEFINES *= TINYTOM_DEBUG
|
||||
|
||||
@@ -30,11 +30,25 @@ DEFINES *= QT_NO_CAST_FROM_BYTEARRAY
|
||||
DEFINES *= QT_USE_QSTRINGBUILDER
|
||||
DEFINES *= QT_STRICT_ITERATORS
|
||||
|
||||
# TinyORM configuration
|
||||
# ---
|
||||
|
||||
# Use extern constants for shared build
|
||||
CONFIG(shared, dll|shared|static|staticlib) | \
|
||||
CONFIG(dll, dll|shared|static|staticlib): \
|
||||
# Support override because inline_constants can be used in the shared build too
|
||||
!inline_constants: \
|
||||
CONFIG += extern_constants
|
||||
|
||||
# Archive library build (static build)
|
||||
else: \
|
||||
CONFIG += inline_constants
|
||||
|
||||
# TinyORM defines
|
||||
# ---
|
||||
|
||||
# Release build
|
||||
CONFIG(release, debug|release): DEFINES *= TINYORM_NO_DEBUG
|
||||
CONFIG(release, debug|release): DEFINES += TINYORM_NO_DEBUG
|
||||
# Debug build
|
||||
CONFIG(debug, debug|release): DEFINES *= TINYORM_DEBUG
|
||||
|
||||
@@ -42,9 +56,27 @@ CONFIG(debug, debug|release): DEFINES *= TINYORM_DEBUG
|
||||
mysql_ping: DEFINES *= TINYORM_MYSQL_PING
|
||||
|
||||
# Log queries with a time measurement
|
||||
CONFIG(release, debug|release): DEFINES *= TINYORM_NO_DEBUG_SQL
|
||||
CONFIG(release, debug|release): DEFINES += TINYORM_NO_DEBUG_SQL
|
||||
CONFIG(debug, debug|release): DEFINES *= TINYORM_DEBUG_SQL
|
||||
|
||||
# Enable code needed by tests, eg. connection overriding in the Model
|
||||
!disable_orm:build_tests: \
|
||||
DEFINES *= TINYORM_TESTS_CODE
|
||||
|
||||
# TinyTom related defines
|
||||
# ---
|
||||
|
||||
!disable_tom {
|
||||
# Release build
|
||||
CONFIG(release, debug|release): DEFINES += TINYTOM_NO_DEBUG
|
||||
# Debug build
|
||||
CONFIG(debug, debug|release): DEFINES *= TINYTOM_DEBUG
|
||||
|
||||
# Enable code needed by tests (modify the migrate:status command for tests need)
|
||||
build_tests: \
|
||||
DEFINES *= TINYTOM_TESTS_CODE
|
||||
}
|
||||
|
||||
# Platform specific configuration
|
||||
# ---
|
||||
win32: include(winconf.pri)
|
||||
@@ -62,17 +94,3 @@ debug_and_release: {
|
||||
TINY_RELEASE_TYPE = $$quote(/debug)
|
||||
}
|
||||
else: TINY_RELEASE_TYPE =
|
||||
|
||||
# Other
|
||||
# ---
|
||||
|
||||
# Use extern constants for shared build
|
||||
CONFIG(shared, dll|shared|static|staticlib) | \
|
||||
CONFIG(dll, dll|shared|static|staticlib): \
|
||||
# Support override because inline_constants can be used in the shared build too
|
||||
!inline_constants: \
|
||||
CONFIG += extern_constants
|
||||
|
||||
# Archive library build (static build)
|
||||
else: \
|
||||
CONFIG += inline_constants
|
||||
|
||||
2
qmake/features/disable_tom.prf
Normal file
2
qmake/features/disable_tom.prf
Normal file
@@ -0,0 +1,2 @@
|
||||
CONFIG *= disable_tom
|
||||
DEFINES *= TINYORM_DISABLE_TOM
|
||||
@@ -14,16 +14,12 @@ defineTest(tiny_resource_and_manifest) {
|
||||
isEmpty(2): resourcesFolder = $$absolute_path(resources, $$_PRO_FILE_PWD_)
|
||||
else: resourcesFolder = $$absolute_path($$2)
|
||||
|
||||
# Processing of RC file and manifest file for the test?
|
||||
defined(3, var):$$3: isTest = true
|
||||
else: isTest = false
|
||||
|
||||
# Target's extension
|
||||
contains(TEMPLATE, ".*app"): targetExt = ".exe"
|
||||
else:contains(TEMPLATE, ".*lib"): targetExt = ".dll"
|
||||
|
||||
# Windows Resource file
|
||||
rcFile = $$tiny_configure_cmake_rc($$resourcesFolder, $$targetExt, $$isTest)
|
||||
rcFile = $$tiny_configure_cmake_rc($$resourcesFolder, $$targetExt, $$3, $$4)
|
||||
|
||||
# Needed in the RC file, MinGW does not define _DEBUG macro
|
||||
mingw:CONFIG(debug, debug|release): DEFINES += _DEBUG
|
||||
@@ -34,8 +30,8 @@ defineTest(tiny_resource_and_manifest) {
|
||||
# Manifest file
|
||||
CONFIG -= embed_manifest_dll
|
||||
|
||||
# Use the same manifest file for all tests
|
||||
$$isTest: manifestBasename = TinyTest
|
||||
# Allow to pass RC/manifest file basename as 3. argument (default is a $$TARGET value)
|
||||
defined(3, var):!isEmpty(3): manifestBasename = $$3
|
||||
else: manifestBasename = $$TARGET
|
||||
|
||||
# On MSVC use EMBED and on MinGW injected through the RC file
|
||||
@@ -56,7 +52,7 @@ defineTest(tiny_resource_and_manifest) {
|
||||
# RC file than manage two practically the same files.
|
||||
defineReplace(tiny_configure_cmake_rc) {
|
||||
# All tests use the same test.rc.in file
|
||||
defined(3, var):$$3: rcBasename = TinyTest
|
||||
defined(3, var):!isEmpty(3): rcBasename = $$3
|
||||
else: rcBasename = $$TARGET
|
||||
|
||||
rcFile = $$absolute_path($$1/$${rcBasename}.rc.in)
|
||||
@@ -75,8 +71,9 @@ defineReplace(tiny_configure_cmake_rc) {
|
||||
|
||||
tiny_manifest_basename = $$rcBasename
|
||||
|
||||
# The same logic for the substitution token, is 'test' for tests and $$TARGET instead
|
||||
token = $$rcBasename
|
||||
# Allow to pass a custom token as 4. argument (default is a $$TARGET value)
|
||||
defined(4, var):!isEmpty(4): token = $$4
|
||||
else: token = $$rcBasename
|
||||
|
||||
rcFileContent = $$cat($$rcFile, blob)
|
||||
|
||||
|
||||
@@ -1,11 +1,29 @@
|
||||
# Find version numbers in the version header file and assign them to the
|
||||
# <TARGET>_VERSION_<MAJOR,MINOR,PATCH,TWEAK> and also to the VERSION variable.
|
||||
defineTest(tiny_version_numbers) {
|
||||
versionHeader = $$find(HEADERS, "(?:.*\/)?version\.h(?:pp)?$")
|
||||
exists(versionHeader)|isEmpty(versionHeader) {
|
||||
# version.hpp for the TinyORM library project
|
||||
contains(_PRO_FILE_, ".*\/src\/src\.pro$"): \
|
||||
versionHeader = $$absolute_path("../include/orm/version.hpp")
|
||||
|
||||
# version.hpp for the tom example project
|
||||
else:contains(_PRO_FILE_, ".*\/examples\/tom\/tom\.pro$"): \
|
||||
versionHeader = $$absolute_path("../tom/include/tom/version.hpp")
|
||||
|
||||
else {
|
||||
# Try to find in the HEADERS
|
||||
versionHeader = $$find(HEADERS, "(?:.*\/)?version\.h(?:pp)?$")
|
||||
|
||||
# Try to find on the INCLUDEPATH
|
||||
isEmpty(versionHeader) {
|
||||
versionHeaders = $$files("$$clean_path($$first(INCLUDEPATH))/version.hpp", \
|
||||
true)
|
||||
versionHeader = $$first(versionHeaders)
|
||||
}
|
||||
}
|
||||
|
||||
exists(versionHeader)|isEmpty(versionHeader): \
|
||||
error( "HEADERS does not contain a version header file version.hpp, needed\
|
||||
in the tiny_version_numbers.prf." )
|
||||
}
|
||||
|
||||
versionFileContent = $$cat($$quote($$absolute_path($$versionHeader)), lines)
|
||||
versionTokens = MAJOR MINOR BUGFIX BUILD STATUS
|
||||
@@ -38,9 +56,8 @@ defineTest(tiny_version_numbers) {
|
||||
$$hasStatus: versionStatus = $$take_last(versionList)
|
||||
|
||||
# Use 3 numbers version on other platforms
|
||||
!win32 {
|
||||
!win32: \
|
||||
$$take_last(versionList)
|
||||
}
|
||||
|
||||
VERSION = $$join(versionList, '.')$$versionStatus
|
||||
export(VERSION)
|
||||
|
||||
2
qmake/features/tom_example.prf
Normal file
2
qmake/features/tom_example.prf
Normal file
@@ -0,0 +1,2 @@
|
||||
CONFIG *= tom_example
|
||||
DEFINES *= TINYORM_TOM_EXAMPLE
|
||||
54
qmake/tom.pri
Normal file
54
qmake/tom.pri
Normal file
@@ -0,0 +1,54 @@
|
||||
TINYORM_SOURCE_TREE = $$clean_path($$quote($$PWD/..))
|
||||
TINYTOM_SOURCE_TREE = $$quote($$TINYORM_SOURCE_TREE/tom)
|
||||
|
||||
# Qt Common Configuration
|
||||
# ---
|
||||
|
||||
QT *= core sql
|
||||
|
||||
CONFIG *= link_prl
|
||||
|
||||
include($$TINYORM_SOURCE_TREE/qmake/common.pri)
|
||||
|
||||
# Configure TinyORM library
|
||||
# ---
|
||||
# everything other is defined in the qmake/common.pri
|
||||
|
||||
# Link with the shared library
|
||||
CONFIG(shared, dll|shared|static|staticlib) | \
|
||||
CONFIG(dll, dll|shared|static|staticlib): \
|
||||
DEFINES *= TINYORM_LINKING_SHARED
|
||||
|
||||
# File version
|
||||
# ---
|
||||
|
||||
# Find version numbers in the version header file and assign them to the
|
||||
# <TARGET>_VERSION_<MAJOR,MINOR,PATCH,TWEAK> and also to the VERSION variable.
|
||||
load(tiny_version_numbers)
|
||||
tiny_version_numbers()
|
||||
|
||||
# Windows resource and manifest files
|
||||
# ---
|
||||
|
||||
# Find version.hpp
|
||||
tinyRcIncludepath = $$quote($$TINYTOM_SOURCE_TREE/include/)
|
||||
# Find Windows manifest
|
||||
mingw: tinyRcIncludepath += $$quote($$TINYTOM_SOURCE_TREE/resources/)
|
||||
|
||||
load(tiny_resource_and_manifest)
|
||||
tiny_resource_and_manifest( \
|
||||
$$tinyRcIncludepath, $$TINYTOM_SOURCE_TREE/resources, tom, TomExample \
|
||||
)
|
||||
|
||||
# Link against TinyORM library
|
||||
# ---
|
||||
|
||||
INCLUDEPATH *= \
|
||||
$$quote($$TINYORM_SOURCE_TREE/include/) \
|
||||
$$quote($$TINYTOM_SOURCE_TREE/include/) \
|
||||
|
||||
!isEmpty(TINYORM_BUILD_TREE): \
|
||||
exists($$TINYORM_BUILD_TREE): {
|
||||
LIBS += $$quote(-L$$TINYORM_BUILD_TREE/src$${TINY_RELEASE_TYPE}/)
|
||||
LIBS += -lTinyOrm
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
#include "orm/concerns/logsqueries.hpp"
|
||||
|
||||
#ifdef TINYORM_DEBUG_SQL
|
||||
#include <QDebug>
|
||||
# include <QDebug>
|
||||
#endif
|
||||
|
||||
#include "orm/databaseconnection.hpp"
|
||||
#include "orm/macros/likely.hpp"
|
||||
#ifdef TINYORM_DEBUG_SQL
|
||||
#include "orm/utils/query.hpp"
|
||||
# include "orm/utils/query.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef TINYORM_DEBUG_SQL
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <QDateTime>
|
||||
#if defined(TINYORM_MYSQL_PING)
|
||||
#include <QDebug>
|
||||
# include <QDebug>
|
||||
#endif
|
||||
|
||||
#include "orm/query/querybuilder.hpp"
|
||||
@@ -400,6 +400,14 @@ void DatabaseConnection::disconnect()
|
||||
m_qtConnectionResolver = nullptr;
|
||||
}
|
||||
|
||||
const SchemaGrammar &DatabaseConnection::getSchemaGrammar()
|
||||
{
|
||||
if (!m_schemaGrammar)
|
||||
useDefaultSchemaGrammar();
|
||||
|
||||
return *m_schemaGrammar;
|
||||
}
|
||||
|
||||
std::unique_ptr<SchemaBuilder> DatabaseConnection::getSchemaBuilder()
|
||||
{
|
||||
if (!m_schemaGrammar)
|
||||
@@ -432,7 +440,7 @@ namespace
|
||||
{
|
||||
using DriverNameMapType = std::unordered_map<QString, const QString &>;
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
/*! Map Qt driver name to the pretty name. */
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(DriverNameMapType, DRIVER_NAME_MAP, ({
|
||||
{QMYSQL, MYSQL_},
|
||||
{QPSQL, POSTGRESQL},
|
||||
|
||||
@@ -13,6 +13,10 @@ LogicError::LogicError(const QString &message)
|
||||
: std::logic_error(message.toUtf8().constData())
|
||||
{}
|
||||
|
||||
LogicError::LogicError(const std::string &message)
|
||||
: std::logic_error(message)
|
||||
{}
|
||||
|
||||
} // namespace Orm::Exceptions
|
||||
|
||||
TINYORM_END_COMMON_NAMESPACE
|
||||
|
||||
@@ -13,6 +13,10 @@ RuntimeError::RuntimeError(const QString &message)
|
||||
: std::runtime_error(message.toUtf8().constData())
|
||||
{}
|
||||
|
||||
RuntimeError::RuntimeError(const std::string &message)
|
||||
: std::runtime_error(message)
|
||||
{}
|
||||
|
||||
} // namespace Orm::Exceptions
|
||||
|
||||
TINYORM_END_COMMON_NAMESPACE
|
||||
|
||||
@@ -26,11 +26,6 @@ SqlError::SqlError(const QString &message, const QSqlError &error, const int /*u
|
||||
, m_sqlError(error)
|
||||
{}
|
||||
|
||||
const QSqlError &SqlError::getSqlError() const
|
||||
{
|
||||
return m_sqlError;
|
||||
}
|
||||
|
||||
QString SqlError::formatMessage(const char *message, const QSqlError &error) const
|
||||
{
|
||||
QString result(message);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "orm/mysqlconnection.hpp"
|
||||
|
||||
#ifdef TINYORM_MYSQL_PING
|
||||
#include <QDebug>
|
||||
# include <QDebug>
|
||||
#endif
|
||||
#include <QtSql/QSqlDriver>
|
||||
|
||||
|
||||
@@ -9,11 +9,10 @@
|
||||
|
||||
TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
|
||||
namespace Orm::Tiny::Utils::Attribute
|
||||
namespace Orm::Tiny::Utils
|
||||
{
|
||||
|
||||
QVariantMap
|
||||
convertVectorToMap(const QVector<AttributeItem> &attributes)
|
||||
QVariantMap Attribute::convertVectorToMap(const QVector<AttributeItem> &attributes)
|
||||
{
|
||||
QVariantMap result;
|
||||
|
||||
@@ -24,7 +23,7 @@ convertVectorToMap(const QVector<AttributeItem> &attributes)
|
||||
}
|
||||
|
||||
QVector<QVariantMap>
|
||||
convertVectorsToMaps(const QVector<QVector<AttributeItem>> &attributesVector)
|
||||
Attribute::convertVectorsToMaps(const QVector<QVector<AttributeItem>> &attributesVector)
|
||||
{
|
||||
const auto size = attributesVector.size();
|
||||
QVector<QVariantMap> result(size);
|
||||
@@ -37,7 +36,7 @@ convertVectorsToMaps(const QVector<QVector<AttributeItem>> &attributesVector)
|
||||
}
|
||||
|
||||
QVector<UpdateItem>
|
||||
convertVectorToUpdateItem(const QVector<AttributeItem> &attributes)
|
||||
Attribute::convertVectorToUpdateItem(const QVector<AttributeItem> &attributes)
|
||||
{
|
||||
QVector<UpdateItem> result;
|
||||
result.reserve(attributes.size());
|
||||
@@ -49,7 +48,7 @@ convertVectorToUpdateItem(const QVector<AttributeItem> &attributes)
|
||||
}
|
||||
|
||||
QVector<UpdateItem>
|
||||
convertVectorToUpdateItem(QVector<AttributeItem> &&attributes)
|
||||
Attribute::convertVectorToUpdateItem(QVector<AttributeItem> &&attributes)
|
||||
{
|
||||
QVector<UpdateItem> result;
|
||||
result.reserve(attributes.size());
|
||||
@@ -62,7 +61,7 @@ convertVectorToUpdateItem(QVector<AttributeItem> &&attributes)
|
||||
}
|
||||
|
||||
QVector<AttributeItem>
|
||||
removeDuplicitKeys(const QVector<AttributeItem> &attributes)
|
||||
Attribute::removeDuplicitKeys(const QVector<AttributeItem> &attributes)
|
||||
{
|
||||
const auto size = attributes.size();
|
||||
std::unordered_set<QString> added(static_cast<std::size_t>(size));
|
||||
@@ -87,9 +86,9 @@ removeDuplicitKeys(const QVector<AttributeItem> &attributes)
|
||||
}
|
||||
|
||||
QVector<AttributeItem>
|
||||
joinAttributesForFirstOr(const QVector<WhereItem> &attributes,
|
||||
const QVector<AttributeItem> &values,
|
||||
const QString &keyName)
|
||||
Attribute::joinAttributesForFirstOr(const QVector<WhereItem> &attributes,
|
||||
const QVector<AttributeItem> &values,
|
||||
const QString &keyName)
|
||||
{
|
||||
// Remove the primary key from attributes
|
||||
auto attributesFiltered =
|
||||
@@ -126,6 +125,6 @@ joinAttributesForFirstOr(const QVector<WhereItem> &attributes,
|
||||
return attributesFiltered + valuesFiltered;
|
||||
}
|
||||
|
||||
} // namespace Orm::Tiny::Utils::Attribute
|
||||
} // namespace Orm::Tiny::Utils
|
||||
|
||||
TINYORM_END_COMMON_NAMESPACE
|
||||
|
||||
@@ -1,20 +1,47 @@
|
||||
#include "orm/tiny/utils/string.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <QStringList>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "orm/constants.hpp"
|
||||
|
||||
using Orm::Constants::DASH;
|
||||
using Orm::Constants::DOT;
|
||||
using Orm::Constants::MINUS;
|
||||
using Orm::Constants::PLUS;
|
||||
using Orm::Constants::SPACE;
|
||||
using Orm::Constants::UNDERSCORE;
|
||||
|
||||
TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
|
||||
namespace Orm::Tiny::Utils::String
|
||||
namespace Orm::Tiny::Utils
|
||||
{
|
||||
|
||||
QString toSnake(QString string)
|
||||
/* This is only one translation unit from the Tiny namespace also used in the tom
|
||||
project, so I leave it enabled in the build system when the tom is going to build,
|
||||
I will not extract these 3 used methods to own dll or static library, they simply
|
||||
will be built into the tinyorm shared library because of this
|
||||
#ifndef TINYORM_DISABLE_ORM/TOM exists, methods are enabled/disabled on the base of
|
||||
whether the orm or tom is built. */
|
||||
|
||||
/* public */
|
||||
|
||||
namespace
|
||||
{
|
||||
using SnakeCache = std::unordered_map<QString, QString>;
|
||||
|
||||
/*! Snake cache for already computed strings. */
|
||||
Q_GLOBAL_STATIC(SnakeCache, snakeCache); // NOLINT(readability-redundant-member-init)
|
||||
} // namespace
|
||||
|
||||
QString String::snake(QString string, const QChar delimiter)
|
||||
{
|
||||
auto key = string;
|
||||
|
||||
if (snakeCache->contains(key))
|
||||
return (*snakeCache)[key];
|
||||
|
||||
// RegExp not used for performance reasons
|
||||
std::vector<int> positions;
|
||||
positions.reserve(static_cast<std::size_t>(string.size() / 2) + 2);
|
||||
@@ -33,23 +60,60 @@ QString toSnake(QString string)
|
||||
}
|
||||
|
||||
// Positions stay valid after inserts because reverse iterators used
|
||||
std::for_each(positions.crbegin(), positions.crend(), [&string](const int pos)
|
||||
std::for_each(positions.crbegin(), positions.crend(),
|
||||
[&string, delimiter](const int pos)
|
||||
{
|
||||
string.insert(pos, UNDERSCORE);
|
||||
string.insert(pos, delimiter);
|
||||
});
|
||||
|
||||
return string.toLower();
|
||||
return (*snakeCache)[std::move(key)] = string.toLower();;
|
||||
}
|
||||
|
||||
QString singular(const QString &string)
|
||||
namespace
|
||||
{
|
||||
if (!string.endsWith(QChar('s')))
|
||||
using StudlyCache = std::unordered_map<QString, QString>;
|
||||
|
||||
/*! Studly cache for already computed strings. */
|
||||
Q_GLOBAL_STATIC(StudlyCache, studlyCache); // NOLINT(readability-redundant-member-init)
|
||||
} // namespace
|
||||
|
||||
QString String::studly(QString string)
|
||||
{
|
||||
auto value = string.trimmed();
|
||||
|
||||
// Nothing to do
|
||||
if (value.isEmpty())
|
||||
return string;
|
||||
|
||||
return string.chopped(1);
|
||||
// Cache key
|
||||
auto key = value;
|
||||
|
||||
if (studlyCache->contains(key))
|
||||
return (*studlyCache)[key];
|
||||
|
||||
value.replace(DASH, SPACE)
|
||||
.replace(UNDERSCORE, SPACE);
|
||||
|
||||
auto size = value.size();
|
||||
|
||||
// Always upper a first character
|
||||
if (size > 1)
|
||||
value[0] = value[0].toUpper();
|
||||
|
||||
QString::size_type pos = 0;
|
||||
|
||||
while ((pos = value.indexOf(SPACE, pos)) != -1) {
|
||||
// Avoid out of bound exception
|
||||
if (++pos >= size)
|
||||
break;
|
||||
|
||||
value[pos] = value[pos].toUpper();
|
||||
}
|
||||
|
||||
return (*studlyCache)[std::move(key)] = value.replace(SPACE, "");
|
||||
}
|
||||
|
||||
bool isNumber(const QString &string)
|
||||
bool String::isNumber(const QString &string, const bool allowFloating)
|
||||
{
|
||||
/* Performance boost was amazing after the QRegularExpression has been removed,
|
||||
around 50% on the Playground app 👀, from 800ms to 400ms. */
|
||||
@@ -60,15 +124,152 @@ bool isNumber(const QString &string)
|
||||
if (string.front() == PLUS || string.front() == MINUS)
|
||||
++itBegin;
|
||||
|
||||
// Only one dot allowed
|
||||
auto dotAlreadyFound = false;
|
||||
|
||||
const auto *nonDigit = std::find_if(itBegin, string.cend(),
|
||||
[](const auto &ch)
|
||||
[allowFloating, &dotAlreadyFound](const auto &ch)
|
||||
{
|
||||
return !std::isdigit(ch.toLatin1());
|
||||
// Integer type
|
||||
if (!allowFloating)
|
||||
return !std::isdigit(ch.toLatin1());
|
||||
|
||||
// Floating-point type
|
||||
// Only one dot allowed
|
||||
const auto isDot = ch.toLatin1() == DOT;
|
||||
|
||||
const auto result = !std::isdigit(ch.toLatin1()) &&
|
||||
(!isDot || (isDot && dotAlreadyFound));
|
||||
|
||||
if (isDot)
|
||||
dotAlreadyFound = true;
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
return nonDigit == string.cend();
|
||||
}
|
||||
|
||||
} // namespace Orm::Tiny::Utils::String
|
||||
#ifndef TINYORM_DISABLE_TOM
|
||||
namespace
|
||||
{
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
using StringViewType = QStringView;
|
||||
#else
|
||||
using StringViewType = QStringRef;
|
||||
#endif
|
||||
|
||||
/*! Split the token to multiple lines by the given width. */
|
||||
bool splitLongToken(StringViewType token, const int width, QString &line,
|
||||
std::vector<QString> &lines)
|
||||
{
|
||||
auto shouldContinue = false;
|
||||
|
||||
const auto spaceSize = line.isEmpty() ? 0 : 1;
|
||||
|
||||
if (const auto emptySpace = width - line.size() + spaceSize;
|
||||
token.size() > emptySpace
|
||||
) {
|
||||
// If on the line is still more than 30% of an empty space, use/fill it
|
||||
if (emptySpace > std::llround(static_cast<float>(width) * 0.3F)) {
|
||||
// Position where to split the token
|
||||
auto pos = width - line.size() - spaceSize;
|
||||
|
||||
// Don't prepend the space at beginning of the line
|
||||
if (!line.isEmpty())
|
||||
line.append(SPACE);
|
||||
|
||||
line.append(token.left(pos));
|
||||
// Cut the appended part
|
||||
token = token.mid(pos);
|
||||
}
|
||||
|
||||
// In every case no more space on the line here, push to lines
|
||||
lines.emplace_back(std::move(line));
|
||||
// Start a new line
|
||||
line.clear(); // NOLINT(bugprone-use-after-move)
|
||||
|
||||
// Process a long token or rest of the token after the previous 30% filling
|
||||
while (!token.isEmpty()) {
|
||||
// Token is shorter than the width, indicates processing of the last token
|
||||
if (token.size() <= width) {
|
||||
line.append(token); // NOLINT(bugprone-use-after-move)
|
||||
break;
|
||||
}
|
||||
|
||||
// Fill the whole line
|
||||
line.append(token.left(width));
|
||||
// Cut the appended part
|
||||
token = token.mid(width);
|
||||
// Push to lines
|
||||
lines.emplace_back(std::move(line));
|
||||
// Start a new line
|
||||
line.clear(); // NOLINT(bugprone-use-after-move)
|
||||
}
|
||||
|
||||
shouldContinue = true;
|
||||
}
|
||||
|
||||
return shouldContinue;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
/*! Split a string by the given width (not in the middle of a word). */
|
||||
std::vector<QString> String::splitStringByWidth(const QString &string, const int width)
|
||||
{
|
||||
// Nothing to split
|
||||
if (string.size() <= width)
|
||||
return {string};
|
||||
|
||||
std::vector<QString> lines;
|
||||
QString line;
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
for (auto token : string.tokenize(SPACE)) {
|
||||
#else
|
||||
for (auto token : string.splitRef(SPACE)) { // NOLINT(performance-for-range-copy) clazy:exclude=range-loop
|
||||
#endif
|
||||
/* If there is still a space on the line then append the token */
|
||||
if (line.size() + token.size() + 1 <= width) {
|
||||
// Don't prepend the space at beginning of an empty line
|
||||
if (!line.isEmpty())
|
||||
line.append(SPACE);
|
||||
|
||||
line.append(token);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If a token is longer than the width or an empty space on the current line */
|
||||
if (splitLongToken(token, width, line, lines))
|
||||
continue;
|
||||
|
||||
// No space on the line, push to lines and start a new line
|
||||
lines.emplace_back(std::move(line));
|
||||
|
||||
// Start a new line
|
||||
line.clear(); // NOLINT(bugprone-use-after-move)
|
||||
line.append(token);
|
||||
}
|
||||
|
||||
/* This can happen if a simple append of the token was the last operation, can happen
|
||||
on the two places above. */
|
||||
if (!line.isEmpty())
|
||||
lines.emplace_back(std::move(line));
|
||||
|
||||
return lines;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef TINYORM_DISABLE_ORM
|
||||
QString String::singular(const QString &string)
|
||||
{
|
||||
if (!string.endsWith(QChar('s')))
|
||||
return string;
|
||||
|
||||
return string.chopped(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace Orm::Tiny::Utils
|
||||
|
||||
TINYORM_END_COMMON_NAMESPACE
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
|
||||
#if !defined(__clang__) && \
|
||||
!defined(TINYORM_NO_DEBUG) && defined(_MSC_VER) && !defined(Q_OS_WINRT)
|
||||
#include <qt_windows.h>
|
||||
# include <qt_windows.h>
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_LINUX) && !defined(QT_LINUXBASE)
|
||||
#include <sys/prctl.h>
|
||||
# include <sys/prctl.h>
|
||||
#endif
|
||||
|
||||
TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
#include <QRegularExpression>
|
||||
|
||||
#if !defined(_MSC_VER)
|
||||
#include <memory>
|
||||
# include <memory>
|
||||
#endif
|
||||
|
||||
#include "orm/constants.hpp"
|
||||
#if !defined(_MSC_VER)
|
||||
#include "orm/exceptions/runtimeerror.hpp"
|
||||
# include "orm/exceptions/runtimeerror.hpp"
|
||||
#endif
|
||||
|
||||
using Orm::Constants::ASTERISK_C;
|
||||
@@ -57,6 +57,11 @@ QString Type::prettyFunction(const QString &function)
|
||||
return QStringLiteral("%1::%2").arg(match.captured(1), match.captured(2));
|
||||
}
|
||||
|
||||
bool Type::isTrue(const QString &value)
|
||||
{
|
||||
return !value.isEmpty() && value != "0" && value != "false";
|
||||
}
|
||||
|
||||
QString
|
||||
Type::classPureBasenameInternal(const std::type_info &typeInfo, const bool withNamespace)
|
||||
{
|
||||
|
||||
@@ -61,6 +61,9 @@ sourcesList += \
|
||||
$$PWD/orm/tiny/tinytypes.cpp \
|
||||
$$PWD/orm/tiny/types/syncchanges.cpp \
|
||||
$$PWD/orm/tiny/utils/attribute.cpp \
|
||||
|
||||
!disable_orm|!disable_tom: \
|
||||
sourcesList += \
|
||||
$$PWD/orm/tiny/utils/string.cpp \
|
||||
|
||||
SOURCES += $$sorted(sourcesList)
|
||||
|
||||
24
src/src.pro
24
src/src.pro
@@ -39,10 +39,6 @@ CONFIG(shared, dll|shared|static|staticlib) | \
|
||||
CONFIG(dll, dll|shared|static|staticlib): \
|
||||
DEFINES *= TINYORM_BUILDING_SHARED
|
||||
|
||||
# Enable code needed by tests, eg. connection overriding in the Model
|
||||
build_tests: \
|
||||
DEFINES *= TINYORM_TESTS_CODE
|
||||
|
||||
# TinyORM library header and source files
|
||||
# ---
|
||||
|
||||
@@ -50,6 +46,14 @@ build_tests: \
|
||||
include(../include/include.pri)
|
||||
include(src.pri)
|
||||
|
||||
# TinyTom header and source files
|
||||
# ---
|
||||
|
||||
!disable_tom {
|
||||
include(../tom/include/include.pri)
|
||||
include(../tom/src/src.pri)
|
||||
}
|
||||
|
||||
# File version
|
||||
# ---
|
||||
|
||||
@@ -85,8 +89,16 @@ win32-msvc:CONFIG(debug, debug|release) {
|
||||
# Some info output
|
||||
# ---
|
||||
|
||||
CONFIG(debug, debug|release):!build_pass: message( "Project is built in DEBUG mode." )
|
||||
CONFIG(release, debug|release):!build_pass: message( "Project is built in RELEASE mode." )
|
||||
!build_pass {
|
||||
CONFIG(debug, debug|release): message( "Project is built in DEBUG mode." )
|
||||
CONFIG(release, debug|release): message( "Project is built in RELEASE mode." )
|
||||
|
||||
!disable_orm: message("Build ORM-related source code.")
|
||||
else: message("Disable ORM-related source code (build the query builder \
|
||||
only).")
|
||||
|
||||
mysql_ping: message("Enable MySQL ping on Orm::MySqlConnection.")
|
||||
}
|
||||
|
||||
# User Configuration
|
||||
# ---
|
||||
|
||||
@@ -39,6 +39,10 @@ using Orm::DB;
|
||||
|
||||
using Orm::Exceptions::RuntimeError;
|
||||
|
||||
#ifndef TINYORM_SQLITE_DATABASE
|
||||
# define TINYORM_SQLITE_DATABASE ""
|
||||
#endif
|
||||
|
||||
namespace TestUtils
|
||||
{
|
||||
|
||||
@@ -49,6 +53,14 @@ namespace TestUtils
|
||||
correctly.
|
||||
Tests don't fail but are skipped when a connection is not available. */
|
||||
|
||||
namespace
|
||||
{
|
||||
/*! DatabaseManager instance. */
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(std::shared_ptr<Orm::DatabaseManager>, db, {nullptr});
|
||||
}
|
||||
|
||||
/* public */
|
||||
|
||||
const QStringList &Databases::createConnections(const QStringList &connections)
|
||||
{
|
||||
throwIfConnectionsInitialized();
|
||||
@@ -57,7 +69,7 @@ const QStringList &Databases::createConnections(const QStringList &connections)
|
||||
/* The default connection is empty for tests, there is no default connection
|
||||
because it can produce hard to find bugs, I have to be explicit about
|
||||
the connection which will be used. */
|
||||
static const auto manager = DB::create(getConfigurations(connections), "");
|
||||
static const auto manager = *db = DB::create(getConfigurations(connections), "");
|
||||
|
||||
static const auto cachedConnectionNames = manager->connectionNames();
|
||||
|
||||
@@ -88,6 +100,16 @@ bool Databases::allEnvVariablesEmpty(const std::vector<const char *> &envVariabl
|
||||
});
|
||||
}
|
||||
|
||||
const std::shared_ptr<Orm::DatabaseManager> &Databases::manager()
|
||||
{
|
||||
if (db() == nullptr)
|
||||
throw RuntimeError("The global static 'db' was already destroyed.");
|
||||
|
||||
return *db;
|
||||
}
|
||||
|
||||
/* private */
|
||||
|
||||
const Databases::ConfigurationsType &
|
||||
Databases::getConfigurations(const QStringList &connections)
|
||||
{
|
||||
|
||||
@@ -6,6 +6,11 @@
|
||||
|
||||
#include "export.hpp"
|
||||
|
||||
namespace Orm
|
||||
{
|
||||
class DatabaseManager;
|
||||
}
|
||||
|
||||
namespace TestUtils
|
||||
{
|
||||
|
||||
@@ -34,6 +39,9 @@ namespace TestUtils
|
||||
/*! Check whether all env. variables are empty. */
|
||||
static bool allEnvVariablesEmpty(const std::vector<const char *> &envVariables);
|
||||
|
||||
/*! Get a reference to the database manager. */
|
||||
static const std::shared_ptr<Orm::DatabaseManager> &manager();
|
||||
|
||||
private:
|
||||
/*! Obtain configurations for the given connection names. */
|
||||
static const ConfigurationsType &
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
/* Add C++ includes here */
|
||||
//#include <QCoreApplication>
|
||||
#include <QDateTime>
|
||||
//#include <QDebug>
|
||||
#include <QHash>
|
||||
#include <QMap>
|
||||
#include <QSharedPointer>
|
||||
@@ -38,7 +39,8 @@
|
||||
//#include <thread>
|
||||
#include <tuple>
|
||||
//#include <type_traits>
|
||||
#include <typeinfo>
|
||||
//#include <typeindex>
|
||||
//#include <typeinfo>
|
||||
//#include <unordered_map>
|
||||
//#include <vector>
|
||||
#endif
|
||||
|
||||
@@ -1 +1,5 @@
|
||||
add_subdirectory(orm)
|
||||
|
||||
if(TOM)
|
||||
add_subdirectory(tom)
|
||||
endif()
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS = \
|
||||
subdirsList = \
|
||||
orm \
|
||||
|
||||
!disable_tom: \
|
||||
subdirsList += \
|
||||
tom \
|
||||
|
||||
SUBDIRS = $$sorted(subdirsList)
|
||||
|
||||
unset(subdirsList)
|
||||
|
||||
1
tests/auto/functional/tom/CMakeLists.txt
Normal file
1
tests/auto/functional/tom/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
||||
add_subdirectory(migrate)
|
||||
18
tests/auto/functional/tom/migrate/CMakeLists.txt
Normal file
18
tests/auto/functional/tom/migrate/CMakeLists.txt
Normal file
@@ -0,0 +1,18 @@
|
||||
# migrate auto test
|
||||
# ---
|
||||
|
||||
set(migrate_ns migrate)
|
||||
set(migrate_target ${migrate_ns})
|
||||
|
||||
project(${migrate_ns}
|
||||
LANGUAGES CXX
|
||||
)
|
||||
|
||||
add_executable(${migrate_target}
|
||||
tst_migrate.cpp
|
||||
)
|
||||
|
||||
add_test(NAME ${migrate_target} COMMAND ${migrate_target})
|
||||
|
||||
include(TinyTestCommon)
|
||||
tiny_configure_test(${migrate_target} INCLUDE_MIGRATIONS)
|
||||
5
tests/auto/functional/tom/migrate/migrate.pro
Normal file
5
tests/auto/functional/tom/migrate/migrate.pro
Normal file
@@ -0,0 +1,5 @@
|
||||
include($$TINYORM_SOURCE_TREE/tests/qmake/common.pri)
|
||||
include($$TINYORM_SOURCE_TREE/tests/qmake/TinyUtils.pri)
|
||||
include($$TINYORM_SOURCE_TREE/tests/database/migrations.pri)
|
||||
|
||||
SOURCES += tst_migrate.cpp
|
||||
585
tests/auto/functional/tom/migrate/tst_migrate.cpp
Normal file
585
tests/auto/functional/tom/migrate/tst_migrate.cpp
Normal file
@@ -0,0 +1,585 @@
|
||||
#include <QCoreApplication>
|
||||
#include <QtTest>
|
||||
|
||||
#include "tom/application.hpp"
|
||||
#include "tom/commands/migrations/statuscommand.hpp"
|
||||
|
||||
#include "databases.hpp"
|
||||
|
||||
#include "migrations/2014_10_12_000000_create_posts_table.hpp"
|
||||
#include "migrations/2014_10_12_100000_add_factor_column_to_posts_table.hpp"
|
||||
#include "migrations/2014_10_12_200000_create_properties_table.hpp"
|
||||
#include "migrations/2014_10_12_300000_create_phones_table.hpp"
|
||||
|
||||
using namespace Migrations; // NOLINT(google-build-using-namespace)
|
||||
|
||||
using TomApplication = Tom::Application;
|
||||
|
||||
using Tom::Commands::Migrations::StatusCommand;
|
||||
|
||||
using TestUtils::Databases;
|
||||
|
||||
class tst_Migrate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/*! Alias for the test output row. */
|
||||
using StatusRow = StatusCommand::StatusRow;
|
||||
/*! Type used for comparing results of the status command. */
|
||||
using Status = std::vector<StatusRow>;
|
||||
|
||||
private slots:
|
||||
void initTestCase();
|
||||
void cleanup() const;
|
||||
|
||||
void reset() const;
|
||||
|
||||
void migrate() const;
|
||||
void migrate_Step() const;
|
||||
|
||||
void rollback_OnMigrate() const;
|
||||
void rollback_OnMigrateWithStep() const;
|
||||
|
||||
void rollback_Step_OnMigrate() const;
|
||||
void rollback_Step_OnMigrateWithStep() const;
|
||||
|
||||
void refresh_OnMigrate() const;
|
||||
void refresh_OnMigrateWithStep() const;
|
||||
|
||||
void refresh_Step() const;
|
||||
void refresh_StepMigrate() const;
|
||||
void refresh_Step_StepMigrate() const;
|
||||
|
||||
// NOLINTNEXTLINE(readability-redundant-access-specifiers)
|
||||
private:
|
||||
/*! Prepare arguments and invoke runCommand(). */
|
||||
[[nodiscard]] int
|
||||
invokeCommand(const QString &name, std::vector<const char *> &&arguments = {}) const;
|
||||
/*! Create a tom application instance and invoke the given command. */
|
||||
int runCommand(int &argc, const std::vector<const char *> &argv) const;
|
||||
|
||||
/*! Invoke the status command to obtain results. */
|
||||
inline int invokeTestStatusCommand() const;
|
||||
/*! Get result of the last status command. */
|
||||
Status status() const;
|
||||
/*! Create a status object for comparing with the result of the status(). */
|
||||
Status createStatus(std::initializer_list<StatusRow> rows) const;
|
||||
/*! Create a status object to be equal after complete rollback. */
|
||||
Status createResetStatus() const;
|
||||
|
||||
/*! Connection name used in this test case. */
|
||||
QString m_connection {};
|
||||
};
|
||||
|
||||
/*! Alias for the test output row. */
|
||||
using Status = tst_Migrate::Status;
|
||||
/*! Type used for comparing results of the status command. */
|
||||
using StatusRow = tst_Migrate::StatusRow;
|
||||
|
||||
/* Extracted common code to re-use. */
|
||||
namespace
|
||||
{
|
||||
// Status
|
||||
inline const auto *Yes = "Yes";
|
||||
inline const auto *No = "No";
|
||||
|
||||
// Batches
|
||||
inline const auto *s_1 = "1";
|
||||
inline const auto *s_2 = "2";
|
||||
inline const auto *s_3 = "3";
|
||||
inline const auto *s_4 = "4";
|
||||
|
||||
// Migration names
|
||||
inline const auto *
|
||||
s_2014_10_12_000000_create_posts_table =
|
||||
"2014_10_12_000000_create_posts_table";
|
||||
inline const auto *
|
||||
s_2014_10_12_100000_add_factor_column_to_posts_table =
|
||||
"2014_10_12_100000_add_factor_column_to_posts_table";
|
||||
inline const auto *
|
||||
s_2014_10_12_200000_create_properties_table =
|
||||
"2014_10_12_200000_create_properties_table";
|
||||
inline const auto *
|
||||
s_2014_10_12_300000_create_phones_table =
|
||||
"2014_10_12_300000_create_phones_table";
|
||||
|
||||
// Fully migrated w/o --step
|
||||
inline const std::initializer_list<StatusRow>
|
||||
FullyMigrated = {
|
||||
{Yes, s_2014_10_12_000000_create_posts_table, s_1},
|
||||
{Yes, s_2014_10_12_100000_add_factor_column_to_posts_table, s_1},
|
||||
{Yes, s_2014_10_12_200000_create_properties_table, s_1},
|
||||
{Yes, s_2014_10_12_300000_create_phones_table, s_1},
|
||||
};
|
||||
|
||||
// Fully migrated with --step
|
||||
inline const std::initializer_list<StatusRow>
|
||||
FullyStepMigrated = {
|
||||
{Yes, s_2014_10_12_000000_create_posts_table, s_1},
|
||||
{Yes, s_2014_10_12_100000_add_factor_column_to_posts_table, s_2},
|
||||
{Yes, s_2014_10_12_200000_create_properties_table, s_3},
|
||||
{Yes, s_2014_10_12_300000_create_phones_table, s_4},
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
/* private slots */
|
||||
|
||||
void tst_Migrate::initTestCase()
|
||||
{
|
||||
m_connection = Databases::createConnection(Databases::MYSQL);
|
||||
|
||||
if (m_connection.isEmpty())
|
||||
QSKIP(QStringLiteral("%1 autotest skipped, environment variables "
|
||||
"for '%2' connection have not been defined.")
|
||||
.arg("tst_Migrate", Databases::MYSQL).toUtf8().constData(), );
|
||||
|
||||
/* Modify the migrate:status command to not output a status table to the console but
|
||||
instead return a result as the vector, this vector is then used for comparing
|
||||
results. */
|
||||
TomApplication::enableInUnitTests();
|
||||
}
|
||||
|
||||
void tst_Migrate::cleanup() const
|
||||
{
|
||||
/* All test methods need this except for two of them (reset and I don't remember
|
||||
second), I will not implement special logic to skip this for these two methods. */
|
||||
{
|
||||
auto exitCode = invokeCommand("migrate:reset");
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
{
|
||||
auto exitCode = invokeTestStatusCommand();
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
QCOMPARE(createResetStatus(), status());
|
||||
}
|
||||
}
|
||||
|
||||
void tst_Migrate::reset() const
|
||||
{
|
||||
{
|
||||
auto exitCode = invokeCommand("migrate:reset");
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
{
|
||||
auto exitCode = invokeTestStatusCommand();
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
QCOMPARE(createResetStatus(), status());
|
||||
}
|
||||
}
|
||||
|
||||
void tst_Migrate::migrate() const
|
||||
{
|
||||
{
|
||||
auto exitCode = invokeCommand("migrate");
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
{
|
||||
auto exitCode = invokeTestStatusCommand();
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
QCOMPARE(createStatus(FullyMigrated), status());
|
||||
}
|
||||
}
|
||||
|
||||
void tst_Migrate::migrate_Step() const
|
||||
{
|
||||
{
|
||||
auto exitCode = invokeCommand("migrate", {"--step"});
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
{
|
||||
auto exitCode = invokeTestStatusCommand();
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
QCOMPARE(createStatus(FullyStepMigrated), status());
|
||||
}
|
||||
}
|
||||
|
||||
void tst_Migrate::rollback_OnMigrate() const
|
||||
{
|
||||
{
|
||||
auto exitCode = invokeCommand("migrate");
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
{
|
||||
auto exitCode = invokeTestStatusCommand();
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
QCOMPARE(createStatus(FullyMigrated), status());
|
||||
}
|
||||
|
||||
// rollback on previous migrate w/o --step
|
||||
{
|
||||
auto exitCode = invokeCommand("migrate:rollback");
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
{
|
||||
auto exitCode = invokeTestStatusCommand();
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
QCOMPARE(createResetStatus(), status());
|
||||
}
|
||||
}
|
||||
|
||||
void tst_Migrate::rollback_OnMigrateWithStep() const
|
||||
{
|
||||
{
|
||||
auto exitCode = invokeCommand("migrate", {"--step"});
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
{
|
||||
auto exitCode = invokeTestStatusCommand();
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
QCOMPARE(createStatus(FullyStepMigrated), status());
|
||||
}
|
||||
|
||||
// rollback on previous migrate with --step
|
||||
{
|
||||
auto exitCode = invokeCommand("migrate:rollback");
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
{
|
||||
auto exitCode = invokeTestStatusCommand();
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
QCOMPARE(createStatus({
|
||||
{Yes, s_2014_10_12_000000_create_posts_table, s_1},
|
||||
{Yes, s_2014_10_12_100000_add_factor_column_to_posts_table, s_2},
|
||||
{Yes, s_2014_10_12_200000_create_properties_table, s_3},
|
||||
{No, s_2014_10_12_300000_create_phones_table},
|
||||
}), status());
|
||||
}
|
||||
}
|
||||
|
||||
void tst_Migrate::rollback_Step_OnMigrate() const
|
||||
{
|
||||
{
|
||||
auto exitCode = invokeCommand("migrate");
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
{
|
||||
auto exitCode = invokeTestStatusCommand();
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
QCOMPARE(createStatus(FullyMigrated), status());
|
||||
}
|
||||
|
||||
// rollback on previous migrate w/o --step
|
||||
{
|
||||
auto exitCode = invokeCommand("migrate:rollback", {"--step=2"});
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
{
|
||||
auto exitCode = invokeTestStatusCommand();
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
QCOMPARE(createStatus({
|
||||
{Yes, s_2014_10_12_000000_create_posts_table, s_1},
|
||||
{Yes, s_2014_10_12_100000_add_factor_column_to_posts_table, s_1},
|
||||
{No, s_2014_10_12_200000_create_properties_table},
|
||||
{No, s_2014_10_12_300000_create_phones_table},
|
||||
}), status());
|
||||
}
|
||||
}
|
||||
|
||||
void tst_Migrate::rollback_Step_OnMigrateWithStep() const
|
||||
{
|
||||
{
|
||||
auto exitCode = invokeCommand("migrate", {"--step"});
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
{
|
||||
auto exitCode = invokeTestStatusCommand();
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
QCOMPARE(createStatus(FullyStepMigrated), status());
|
||||
}
|
||||
|
||||
// rollback on previous migrate with --step
|
||||
{
|
||||
auto exitCode = invokeCommand("migrate:rollback", {"--step=2"});
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
{
|
||||
auto exitCode = invokeTestStatusCommand();
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
QCOMPARE(createStatus({
|
||||
{Yes, s_2014_10_12_000000_create_posts_table, s_1},
|
||||
{Yes, s_2014_10_12_100000_add_factor_column_to_posts_table, s_2},
|
||||
{No, s_2014_10_12_200000_create_properties_table},
|
||||
{No, s_2014_10_12_300000_create_phones_table},
|
||||
}), status());
|
||||
}
|
||||
}
|
||||
|
||||
void tst_Migrate::refresh_OnMigrate() const
|
||||
{
|
||||
{
|
||||
auto exitCode = invokeCommand("migrate");
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
{
|
||||
auto exitCode = invokeTestStatusCommand();
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
QCOMPARE(createStatus(FullyMigrated), status());
|
||||
}
|
||||
|
||||
// refresh on previous migrate w/o --step
|
||||
{
|
||||
auto exitCode = invokeCommand("migrate:refresh");
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
{
|
||||
auto exitCode = invokeTestStatusCommand();
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
QCOMPARE(createStatus(FullyMigrated), status());
|
||||
}
|
||||
}
|
||||
|
||||
void tst_Migrate::refresh_OnMigrateWithStep() const
|
||||
{
|
||||
{
|
||||
auto exitCode = invokeCommand("migrate", {"--step"});
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
{
|
||||
auto exitCode = invokeTestStatusCommand();
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
QCOMPARE(createStatus(FullyStepMigrated), status());
|
||||
}
|
||||
|
||||
// refresh on previous migrate with --step
|
||||
{
|
||||
auto exitCode = invokeCommand("migrate:refresh");
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
{
|
||||
auto exitCode = invokeTestStatusCommand();
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
QCOMPARE(createStatus(FullyMigrated), status());
|
||||
}
|
||||
}
|
||||
|
||||
void tst_Migrate::refresh_Step() const
|
||||
{
|
||||
{
|
||||
auto exitCode = invokeCommand("migrate");
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
{
|
||||
auto exitCode = invokeTestStatusCommand();
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
QCOMPARE(createStatus(FullyMigrated), status());
|
||||
}
|
||||
|
||||
// refresh on previous migrate w/o --step
|
||||
{
|
||||
auto exitCode = invokeCommand("migrate:refresh", {"--step=2"});
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
{
|
||||
auto exitCode = invokeTestStatusCommand();
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
QCOMPARE(createStatus({
|
||||
{Yes, s_2014_10_12_000000_create_posts_table, s_1},
|
||||
{Yes, s_2014_10_12_100000_add_factor_column_to_posts_table, s_1},
|
||||
{Yes, s_2014_10_12_200000_create_properties_table, s_2},
|
||||
{Yes, s_2014_10_12_300000_create_phones_table, s_2},
|
||||
}), status());
|
||||
}
|
||||
}
|
||||
|
||||
void tst_Migrate::refresh_StepMigrate() const
|
||||
{
|
||||
{
|
||||
auto exitCode = invokeCommand("migrate");
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
{
|
||||
auto exitCode = invokeTestStatusCommand();
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
QCOMPARE(createStatus(FullyMigrated), status());
|
||||
}
|
||||
|
||||
// refresh on previous migrate w/o --step
|
||||
{
|
||||
auto exitCode = invokeCommand("migrate:refresh", {"--step-migrate"});
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
{
|
||||
auto exitCode = invokeTestStatusCommand();
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
QCOMPARE(createStatus(FullyStepMigrated), status());
|
||||
}
|
||||
}
|
||||
|
||||
void tst_Migrate::refresh_Step_StepMigrate() const
|
||||
{
|
||||
{
|
||||
auto exitCode = invokeCommand("migrate");
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
{
|
||||
auto exitCode = invokeTestStatusCommand();
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
QCOMPARE(createStatus(FullyMigrated), status());
|
||||
}
|
||||
|
||||
// refresh on previous migrate w/o --step
|
||||
{
|
||||
auto exitCode = invokeCommand("migrate:refresh", {"--step=2", "--step-migrate"});
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
{
|
||||
auto exitCode = invokeTestStatusCommand();
|
||||
|
||||
QVERIFY(exitCode == EXIT_SUCCESS);
|
||||
QCOMPARE(createStatus({
|
||||
{Yes, s_2014_10_12_000000_create_posts_table, s_1},
|
||||
{Yes, s_2014_10_12_100000_add_factor_column_to_posts_table, s_1},
|
||||
{Yes, s_2014_10_12_200000_create_properties_table, s_2},
|
||||
{Yes, s_2014_10_12_300000_create_phones_table, s_3},
|
||||
}), status());
|
||||
}
|
||||
}
|
||||
|
||||
/* private */
|
||||
|
||||
int tst_Migrate::invokeCommand(const QString &name,
|
||||
std::vector<const char *> &&arguments) const
|
||||
{
|
||||
static const auto connectionTmpl = QStringLiteral("--database=%1");
|
||||
|
||||
// Prepare fake argc and argv
|
||||
const auto nameArr = name.toUtf8();
|
||||
// FUTURE tests tom, when the schema builder will support more db drivers, I can run it on all supported connections, code will look like in the tst_querybuilder.cpp, then I will fetch connection name in every test method using QFETCH_GLOBAL() and I will pass this connection name to the invokeCommand(), so I will discard m_connection and will use method parameter connection here silverqx
|
||||
/* Schema builder is implemented only for the MySQL driver, so I can use m_connection
|
||||
here as the default connection. */
|
||||
// DB connection to use
|
||||
const auto connectionArr = connectionTmpl.arg(m_connection).toUtf8();
|
||||
|
||||
std::vector<const char *> argv {
|
||||
#ifdef _WIN32
|
||||
"tom.exe",
|
||||
#else
|
||||
"tom",
|
||||
#endif
|
||||
nameArr.constData(),
|
||||
connectionArr.constData(),
|
||||
};
|
||||
std::ranges::move(arguments, std::back_inserter(argv));
|
||||
|
||||
int argc = static_cast<int>(argv.size());
|
||||
|
||||
return runCommand(argc, argv);
|
||||
}
|
||||
|
||||
int tst_Migrate::runCommand(int &argc, const std::vector<const char *> &argv) const
|
||||
{
|
||||
try {
|
||||
// env. should be always development so passed {} for env. name
|
||||
return TomApplication(argc, const_cast<char **>(argv.data()),
|
||||
Databases::manager(), {})
|
||||
.migrations<
|
||||
_2014_10_12_000000_create_posts_table,
|
||||
_2014_10_12_100000_add_factor_column_to_posts_table,
|
||||
_2014_10_12_200000_create_properties_table,
|
||||
_2014_10_12_300000_create_phones_table>()
|
||||
// Fire it up 🔥🚀✨
|
||||
.runWithArguments({argv.cbegin(), argv.cend()});
|
||||
|
||||
} catch (const std::exception &e) {
|
||||
|
||||
TomApplication::logException(e, true);
|
||||
}
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int tst_Migrate::invokeTestStatusCommand() const
|
||||
{
|
||||
return invokeCommand("migrate:status");
|
||||
}
|
||||
|
||||
Status tst_Migrate::status() const
|
||||
{
|
||||
return TomApplication::status();
|
||||
}
|
||||
|
||||
Status tst_Migrate::createStatus(std::initializer_list<StatusRow> rows) const
|
||||
{
|
||||
return Status({rows});
|
||||
}
|
||||
|
||||
Status tst_Migrate::createResetStatus() const
|
||||
{
|
||||
return Status({
|
||||
{No, s_2014_10_12_000000_create_posts_table},
|
||||
{No, s_2014_10_12_100000_add_factor_column_to_posts_table},
|
||||
{No, s_2014_10_12_200000_create_properties_table},
|
||||
{No, s_2014_10_12_300000_create_phones_table},
|
||||
});
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_Migrate)
|
||||
|
||||
#include "tst_migrate.moc"
|
||||
4
tests/auto/functional/tom/tom.pro
Normal file
4
tests/auto/functional/tom/tom.pro
Normal file
@@ -0,0 +1,4 @@
|
||||
TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS = \
|
||||
migrate \
|
||||
@@ -21,6 +21,15 @@ if(BUILD_SHARED_LIBS)
|
||||
target_compile_definitions(version PRIVATE TINYTEST_VERSION_IS_SHARED_BUILD)
|
||||
endif()
|
||||
|
||||
if(TOM_EXAMPLE)
|
||||
target_compile_definitions(version PRIVATE TINYTOM_EXAMPLE)
|
||||
|
||||
# To find tom/include/version.hpp
|
||||
target_include_directories(version PRIVATE
|
||||
"$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/tom/include>"
|
||||
)
|
||||
endif()
|
||||
|
||||
target_include_directories(version PRIVATE
|
||||
"$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/${TINY_BUILD_GENDIR}/include>"
|
||||
)
|
||||
|
||||
@@ -4,5 +4,6 @@
|
||||
|
||||
#define TINYTEST_VERSION_TINYORM_PATH "$<TARGET_FILE:@TinyOrm_target@>"
|
||||
#define TINYTEST_VERSION_TINYUTILS_PATH "$<TARGET_FILE:@TinyUtils_target@>"
|
||||
#define TINYTEST_VERSION_TOMEXAMPLE_PATH "$<$<TARGET_EXISTS:@TomExample_target@>:$<TARGET_FILE:@TomExample_target@>>"
|
||||
|
||||
#endif // TINYTESTS_VERSIONDEBUG_CMAKE_HPP
|
||||
|
||||
@@ -4,5 +4,6 @@
|
||||
|
||||
#define TINYTEST_VERSION_TINYORM_PATH \"$${TINYTEST_VERSION_TINYORM_PATH}\"
|
||||
#define TINYTEST_VERSION_TINYUTILS_PATH \"$${TINYTEST_VERSION_TINYUTILS_PATH}\"
|
||||
#define TINYTEST_VERSION_TOMEXAMPLE_PATH \"$${TINYTEST_VERSION_TOMEXAMPLE_PATH}\"
|
||||
|
||||
#endif // TINYTEST_VERSIONDEBUG_QMAKE_HPP
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include <QtTest>
|
||||
|
||||
#if defined(_WIN32) && defined(TINYTEST_VERSION_IS_SHARED_BUILD)
|
||||
#include <qt_windows.h>
|
||||
# include <qt_windows.h>
|
||||
#endif
|
||||
|
||||
#include "fs.hpp"
|
||||
@@ -11,6 +11,10 @@
|
||||
#include "orm/version.hpp"
|
||||
// TinyUtils
|
||||
#include "version.hpp"
|
||||
// Tom example
|
||||
#ifdef TINYTOM_EXAMPLE
|
||||
# include "tom/version.hpp"
|
||||
#endif
|
||||
|
||||
// Used by checkFileVersion_*() tests
|
||||
#if defined(_WIN32) && defined(TINYTEST_VERSION_IS_SHARED_BUILD)
|
||||
@@ -22,6 +26,7 @@
|
||||
#else
|
||||
# define TINYTEST_VERSION_TINYORM_PATH
|
||||
# define TINYTEST_VERSION_TINYUTILS_PATH
|
||||
# define TINYTEST_VERSION_TOMEXAMPLE_PATH
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
@@ -35,9 +40,15 @@ class tst_Version : public QObject
|
||||
private slots:
|
||||
void versions_TinyOrm() const;
|
||||
void versions_TinyUtils() const;
|
||||
#ifdef TINYTOM_EXAMPLE
|
||||
void versions_TomExample() const;
|
||||
#endif
|
||||
|
||||
void checkFileVersion_TinyOrm() const;
|
||||
void checkFileVersion_TinyUtils() const;
|
||||
#ifdef TINYTOM_EXAMPLE
|
||||
void checkFileVersion_TomExample() const;
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && defined(TINYTEST_VERSION_IS_SHARED_BUILD)
|
||||
// NOLINTNEXTLINE(readability-redundant-access-specifiers)
|
||||
@@ -125,6 +136,43 @@ void tst_Version::versions_TinyUtils() const
|
||||
QCOMPARE(TINYUTILS_VERSION, version);
|
||||
}
|
||||
|
||||
#ifdef TINYTOM_EXAMPLE
|
||||
void tst_Version::versions_TomExample() const
|
||||
{
|
||||
// Test types
|
||||
QCOMPARE(typeid (TINYTOM_VERSION_MAJOR), typeid (int));
|
||||
QCOMPARE(typeid (TINYTOM_VERSION_MINOR), typeid (int));
|
||||
QCOMPARE(typeid (TINYTOM_VERSION_BUGFIX), typeid (int));
|
||||
QCOMPARE(typeid (TINYTOM_VERSION_BUILD), typeid (int));
|
||||
|
||||
// Individual version numbers have to be greater than zero
|
||||
QVERIFY(TINYTOM_VERSION_MAJOR >= 0);
|
||||
QVERIFY(TINYTOM_VERSION_MINOR >= 0);
|
||||
QVERIFY(TINYTOM_VERSION_BUGFIX >= 0);
|
||||
QVERIFY(TINYTOM_VERSION_BUILD >= 0);
|
||||
|
||||
// Project and File Version strings
|
||||
QString versionStr = QString::number(TINYTOM_VERSION_MAJOR) + QChar('.') +
|
||||
QString::number(TINYTOM_VERSION_MINOR) + QChar('.') +
|
||||
QString::number(TINYTOM_VERSION_BUGFIX);
|
||||
QString fileVersionStr = versionStr + QChar('.') +
|
||||
QString::number(TINYTOM_VERSION_BUILD);
|
||||
if constexpr (TINYTOM_VERSION_BUILD > 0)
|
||||
versionStr += QChar('.') + QString::number(TINYTOM_VERSION_BUILD);
|
||||
versionStr += TINYTOM_VERSION_STATUS;
|
||||
|
||||
QCOMPARE(TINYTOM_FILEVERSION_STR, fileVersionStr);
|
||||
QCOMPARE(TINYTOM_VERSION_STR, versionStr);
|
||||
QCOMPARE(TINYTOM_VERSION_STR_2, QChar('v') + versionStr);
|
||||
|
||||
// Project Version number, to check API compatibility
|
||||
const auto version = TINYTOM_VERSION_MAJOR * 10000 +
|
||||
TINYTOM_VERSION_MINOR * 100 +
|
||||
TINYTOM_VERSION_BUGFIX;
|
||||
QCOMPARE(TINYTOM_VERSION, version);
|
||||
}
|
||||
#endif
|
||||
|
||||
void tst_Version::checkFileVersion_TinyOrm() const
|
||||
{
|
||||
#if !defined(_WIN32)
|
||||
@@ -167,6 +215,29 @@ void tst_Version::checkFileVersion_TinyUtils() const
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef TINYTOM_EXAMPLE
|
||||
void tst_Version::checkFileVersion_TomExample() const
|
||||
{
|
||||
#if !defined(_WIN32)
|
||||
QSKIP("checkFileVersion_*() related tests are supported on MSVC only.", );
|
||||
#elif !defined(TINYTEST_VERSION_IS_SHARED_BUILD)
|
||||
QSKIP("checkFileVersion_*() related tests are enabled for shared builds only.", );
|
||||
#else
|
||||
const auto fileVersions =
|
||||
getExeVersionString(Fs::absolutePath(TINYTEST_VERSION_TOMEXAMPLE_PATH));
|
||||
|
||||
// Project and File Version strings
|
||||
const QString versionStr = QString::number(TINYTOM_VERSION_MAJOR) + QChar('.') +
|
||||
QString::number(TINYTOM_VERSION_MINOR) + QChar('.') +
|
||||
QString::number(TINYTOM_VERSION_BUGFIX) + QChar('.') +
|
||||
QString::number(TINYTOM_VERSION_BUILD);
|
||||
|
||||
QCOMPARE(fileVersions.productVersion, versionStr);
|
||||
QCOMPARE(fileVersions.fileVersion, fileVersions.productVersion);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && defined(TINYTEST_VERSION_IS_SHARED_BUILD)
|
||||
tst_Version::FileVersions
|
||||
tst_Version::getExeVersionString(const QString &fileName) const
|
||||
|
||||
@@ -7,6 +7,9 @@ SOURCES = tst_version.cpp
|
||||
win32 {
|
||||
DEFINES += TINYTEST_VERSION_IS_QMAKE
|
||||
|
||||
tom_example:!disable_tom: \
|
||||
DEFINES += TINYTOM_EXAMPLE
|
||||
|
||||
CONFIG(shared, dll|shared|static|staticlib) | \
|
||||
CONFIG(dll, dll|shared|static|staticlib): \
|
||||
DEFINES += TINYTEST_VERSION_IS_SHARED_BUILD
|
||||
@@ -15,6 +18,8 @@ win32 {
|
||||
$$quote($${TINYORM_BUILD_TREE}/src$${TINY_RELEASE_TYPE}/TinyOrm0.dll)
|
||||
TINYTEST_VERSION_TINYUTILS_PATH = \
|
||||
$$quote($${TINYORM_BUILD_TREE}/tests/TinyUtils$${TINY_RELEASE_TYPE}/TinyUtils0.dll)
|
||||
TINYTEST_VERSION_TOMEXAMPLE_PATH = \
|
||||
$$quote($${TINYORM_BUILD_TREE}/examples/tom$${TINY_RELEASE_TYPE}/tom.exe)
|
||||
|
||||
QMAKE_SUBSTITUTES += $$quote(include/versiondebug_qmake.hpp.in)
|
||||
|
||||
@@ -22,5 +27,9 @@ win32 {
|
||||
|
||||
INCLUDEPATH += $$quote($$OUT_PWD/include/)
|
||||
|
||||
# To find tom/include/version.hpp (don't need to include whole qmake/tom.pri)
|
||||
tom_example:!disable_tom: \
|
||||
INCLUDEPATH += $$quote($$TINYORM_SOURCE_TREE/tom/include/)
|
||||
|
||||
LIBS += -lVersion
|
||||
}
|
||||
|
||||
@@ -6,19 +6,24 @@ win32-g++|win32-clang-g++ {
|
||||
# Enable ccache wrapper
|
||||
CONFIG *= tiny_ccache
|
||||
|
||||
# Includes
|
||||
# tabulate
|
||||
INCLUDEPATH += $$quote(C:/msys64/home/xyz/vcpkg/installed/x64-mingw-dynamic/include/)
|
||||
QMAKE_CXXFLAGS += -isystem $$shell_quote(C:/msys64/home/xyz/vcpkg/installed/x64-mingw-dynamic/include/)
|
||||
|
||||
# Use faster linker
|
||||
# CONFIG *= use_lld_linker does not work on MinGW
|
||||
QMAKE_LFLAGS *= -fuse-ld=lld
|
||||
}
|
||||
else:win32-msvc {
|
||||
# Includes
|
||||
# range-v3
|
||||
# range-v3 and tabulate
|
||||
INCLUDEPATH += $$quote(E:/xyz/vcpkg/installed/x64-windows/include/)
|
||||
}
|
||||
else:unix {
|
||||
# Includes
|
||||
# range-v3
|
||||
QMAKE_CXXFLAGS += -isystem $$quote(/home/xyz/vcpkg/installed/x64-linux/include/)
|
||||
# range-v3 and tabulate
|
||||
QMAKE_CXXFLAGS += -isystem $$shell_quote(/home/xyz/vcpkg/installed/x64-linux/include/)
|
||||
|
||||
# Use faster linkers
|
||||
clang: CONFIG *= use_lld_linker
|
||||
|
||||
7
tests/database/migrations.pri
Normal file
7
tests/database/migrations.pri
Normal file
@@ -0,0 +1,7 @@
|
||||
INCLUDEPATH += $$PWD
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/migrations/2014_10_12_000000_create_posts_table.hpp \
|
||||
$$PWD/migrations/2014_10_12_100000_add_factor_column_to_posts_table.hpp \
|
||||
$$PWD/migrations/2014_10_12_200000_create_properties_table.hpp \
|
||||
$$PWD/migrations/2014_10_12_300000_create_phones_table.hpp \
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <tom/migration.hpp>
|
||||
|
||||
namespace Migrations
|
||||
{
|
||||
|
||||
struct _2014_10_12_000000_create_posts_table : Migration
|
||||
{
|
||||
/*! Run the migrations. */
|
||||
void up() const override
|
||||
{
|
||||
Schema::create("posts", [](Blueprint &table)
|
||||
{
|
||||
table.id();
|
||||
|
||||
table.string(NAME);
|
||||
table.timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/*! Reverse the migrations. */
|
||||
void down() const override
|
||||
{
|
||||
Schema::dropIfExists("posts");
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Migrations
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <tom/migration.hpp>
|
||||
|
||||
namespace Migrations
|
||||
{
|
||||
|
||||
struct _2014_10_12_100000_add_factor_column_to_posts_table : Migration
|
||||
{
|
||||
/*! Run the migrations. */
|
||||
void up() const override
|
||||
{
|
||||
Schema::table("posts", [](Blueprint &table)
|
||||
{
|
||||
table.integer("factor");
|
||||
});
|
||||
}
|
||||
|
||||
/*! Reverse the migrations. */
|
||||
void down() const override
|
||||
{
|
||||
Schema::table("posts", [](Blueprint &table)
|
||||
{
|
||||
table.dropColumn("factor");
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Migrations
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <tom/migration.hpp>
|
||||
|
||||
namespace Migrations
|
||||
{
|
||||
|
||||
struct _2014_10_12_200000_create_properties_table : Migration
|
||||
{
|
||||
/*! Run the migrations. */
|
||||
void up() const override
|
||||
{
|
||||
Schema::create("properties", [](Blueprint &table)
|
||||
{
|
||||
table.id();
|
||||
|
||||
table.string(NAME);
|
||||
table.timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/*! Reverse the migrations. */
|
||||
void down() const override
|
||||
{
|
||||
Schema::dropIfExists("properties");
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Migrations
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <tom/migration.hpp>
|
||||
|
||||
namespace Migrations
|
||||
{
|
||||
|
||||
struct _2014_10_12_300000_create_phones_table : Migration
|
||||
{
|
||||
/*! Run the migrations. */
|
||||
void up() const override
|
||||
{
|
||||
Schema::create("phones", [](Blueprint &table)
|
||||
{
|
||||
table.id();
|
||||
|
||||
table.string(NAME);
|
||||
table.timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/*! Reverse the migrations. */
|
||||
void down() const override
|
||||
{
|
||||
Schema::dropIfExists("phones");
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Migrations
|
||||
@@ -13,7 +13,7 @@
|
||||
#include "models/user.hpp"
|
||||
|
||||
#ifdef PROJECT_TINYORM_PLAYGROUND
|
||||
#include "configuration.hpp"
|
||||
# include "configuration.hpp"
|
||||
#endif
|
||||
|
||||
namespace Models
|
||||
|
||||
@@ -10,6 +10,12 @@ CONFIG(dll, dll|shared|static|staticlib): \
|
||||
|
||||
INCLUDEPATH += $$quote($$TINYORM_SOURCE_TREE/include/)
|
||||
|
||||
# TinyTom include path
|
||||
# ---
|
||||
|
||||
!disable_tom: \
|
||||
INCLUDEPATH += $$quote($$TINYORM_SOURCE_TREE/tom/include/)
|
||||
|
||||
# Link against TinyORM library
|
||||
# ---
|
||||
|
||||
|
||||
@@ -31,12 +31,6 @@ DEFINES += PROJECT_TINYORM_TEST
|
||||
CONFIG(release, debug|release): \
|
||||
DEFINES *= QT_NO_DEBUG_OUTPUT
|
||||
|
||||
# TinyORM library defines
|
||||
# ---
|
||||
|
||||
# Enable code needed by tests, eg connection overriding in the Model
|
||||
DEFINES *= TINYORM_TESTS_CODE
|
||||
|
||||
# Link against TinyORM library (also adds defines and include headers)
|
||||
# ---
|
||||
|
||||
@@ -51,7 +45,7 @@ mingw: tinyRcIncludepath += $$quote($$TINYORM_SOURCE_TREE/tests/resources/)
|
||||
load(tiny_resource_and_manifest)
|
||||
tiny_resource_and_manifest($$tinyRcIncludepath, \
|
||||
$$quote($$TINYORM_SOURCE_TREE/tests/resources), \
|
||||
true \
|
||||
TinyTest \
|
||||
)
|
||||
|
||||
unset(tinyRcIncludepath)
|
||||
|
||||
38
tom/include/include.pri
Normal file
38
tom/include/include.pri
Normal file
@@ -0,0 +1,38 @@
|
||||
INCLUDEPATH += $$PWD
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/tom/application.hpp \
|
||||
$$PWD/tom/commands/command.hpp \
|
||||
$$PWD/tom/commands/database/wipecommand.hpp \
|
||||
$$PWD/tom/commands/environmentcommand.hpp \
|
||||
$$PWD/tom/commands/helpcommand.hpp \
|
||||
$$PWD/tom/commands/inspirecommand.hpp \
|
||||
$$PWD/tom/commands/listcommand.hpp \
|
||||
$$PWD/tom/commands/make/migrationcommand.hpp \
|
||||
# $$PWD/tom/commands/make/projectcommand.hpp \
|
||||
$$PWD/tom/commands/make/stubs/migrationstubs.hpp \
|
||||
$$PWD/tom/commands/make/stubs/projectstubs.hpp \
|
||||
$$PWD/tom/commands/migrations/freshcommand.hpp \
|
||||
$$PWD/tom/commands/migrations/installcommand.hpp \
|
||||
$$PWD/tom/commands/migrations/migratecommand.hpp \
|
||||
$$PWD/tom/commands/migrations/refreshcommand.hpp \
|
||||
$$PWD/tom/commands/migrations/resetcommand.hpp \
|
||||
$$PWD/tom/commands/migrations/rollbackcommand.hpp \
|
||||
$$PWD/tom/commands/migrations/statuscommand.hpp \
|
||||
$$PWD/tom/concerns/callscommands.hpp \
|
||||
$$PWD/tom/concerns/confirmable.hpp \
|
||||
$$PWD/tom/concerns/interactswithio.hpp \
|
||||
$$PWD/tom/concerns/printsoptions.hpp \
|
||||
$$PWD/tom/config.hpp \
|
||||
$$PWD/tom/exceptions/invalidargumenterror.hpp \
|
||||
$$PWD/tom/exceptions/invalidtemplateargumenterror.hpp \
|
||||
$$PWD/tom/exceptions/logicerror.hpp \
|
||||
$$PWD/tom/exceptions/runtimeerror.hpp \
|
||||
$$PWD/tom/exceptions/tomerror.hpp \
|
||||
$$PWD/tom/migration.hpp \
|
||||
$$PWD/tom/migrationcreator.hpp \
|
||||
$$PWD/tom/migrationrepository.hpp \
|
||||
$$PWD/tom/migrator.hpp \
|
||||
$$PWD/tom/terminal.hpp \
|
||||
$$PWD/tom/tomtypes.hpp \
|
||||
$$PWD/tom/version.hpp \
|
||||
259
tom/include/tom/application.hpp
Normal file
259
tom/include/tom/application.hpp
Normal file
@@ -0,0 +1,259 @@
|
||||
#pragma once
|
||||
#ifndef TOM_APPLICATION_HPP
|
||||
#define TOM_APPLICATION_HPP
|
||||
|
||||
#include <orm/macros/systemheader.hpp>
|
||||
TINY_SYSTEM_HEADER
|
||||
|
||||
#include <QCommandLineParser>
|
||||
|
||||
#include "tom/config.hpp"
|
||||
|
||||
#include "tom/concerns/interactswithio.hpp"
|
||||
|
||||
TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
|
||||
namespace Orm
|
||||
{
|
||||
class DatabaseManager;
|
||||
}
|
||||
|
||||
namespace Tom {
|
||||
|
||||
namespace Commands
|
||||
{
|
||||
class Command;
|
||||
class HelpCommand;
|
||||
class ListCommand;
|
||||
} // namespace Commands
|
||||
namespace Concerns
|
||||
{
|
||||
class CallsCommands;
|
||||
class PrintsOptions;
|
||||
} // namespace Concerns
|
||||
|
||||
class Migration;
|
||||
class MigrationRepository;
|
||||
class Migrator;
|
||||
|
||||
/*! Tom application. */
|
||||
class SHAREDLIB_EXPORT Application : public Concerns::InteractsWithIO
|
||||
{
|
||||
Q_DISABLE_COPY(Application)
|
||||
|
||||
// To access saveOptions()
|
||||
friend Commands::Command;
|
||||
// To access createCommand()
|
||||
friend Commands::HelpCommand;
|
||||
// To access showVersion()
|
||||
friend Commands::ListCommand;
|
||||
// To access m_options
|
||||
friend Concerns::PrintsOptions;
|
||||
// To access initializeParser() and createCommand()
|
||||
friend Concerns::CallsCommands;
|
||||
|
||||
/*! Alias for the DatabaseManager. */
|
||||
using DatabaseManager = Orm::DatabaseManager;
|
||||
|
||||
public:
|
||||
/*! Constructor. */
|
||||
Application(int &argc, char **argv, std::shared_ptr<DatabaseManager> db,
|
||||
const char *environmentEnvName = "TOM_ENV",
|
||||
QString migrationTable = QLatin1String("migrations"),
|
||||
std::vector<std::shared_ptr<Migration>> migrations = {});
|
||||
/*! Default destructor. */
|
||||
inline ~Application() = default;
|
||||
|
||||
/*! Instantiate/initialize all migration classes. */
|
||||
template<typename ...M>
|
||||
Application &migrations();
|
||||
|
||||
/*! Run the tom application. */
|
||||
int run();
|
||||
|
||||
/*! Log exception caught in the main exception handler in a current thread. */
|
||||
static void logException(const std::exception &e, bool noAnsi = false);
|
||||
|
||||
/* Getters / Setters */
|
||||
/*! Get a current application environment. */
|
||||
inline const QString &environment() const noexcept;
|
||||
/*! Get database manager. */
|
||||
inline DatabaseManager &db() const noexcept;
|
||||
|
||||
/*! Get command-line parser. */
|
||||
inline const QCommandLineParser &parser() const noexcept;
|
||||
/*! Is the application running in an interactive mode? */
|
||||
inline bool isInteractive() const noexcept;
|
||||
/*! Obtain current command-line arguments. */
|
||||
QStringList arguments() const;
|
||||
|
||||
/*! Set the migration repository table name. */
|
||||
inline Application &migrationTable(QString table);
|
||||
|
||||
#ifdef TINYTOM_TESTS_CODE
|
||||
/*! Alias for the test output row from the status command. */
|
||||
using StatusRow = std::vector<std::string>;
|
||||
|
||||
/*! Get result of the status command (used in auto tests). */
|
||||
static std::vector<StatusRow> status() noexcept;
|
||||
/*! Enable logic for unit testing? */
|
||||
static void enableInUnitTests() noexcept;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
/*! Alias for the commands' base class. */
|
||||
using Command = Commands::Command;
|
||||
|
||||
/*! Fix m_argc/m_argv data members if the argv is empty. */
|
||||
void fixEmptyArgv();
|
||||
/*! Processes the specified function at application's normal exit. */
|
||||
void initializeAtExit() const;
|
||||
|
||||
/*! Initialize the command-line parser. */
|
||||
void initializeParser(QCommandLineParser &parser);
|
||||
/*! Save a copy of application options passed to the Qt's parser. */
|
||||
const QList<QCommandLineOption> &
|
||||
saveOptions(QList<QCommandLineOption> &&options);
|
||||
|
||||
/*! Prepend command options before common options (used by the help command). */
|
||||
QList<QCommandLineOption>
|
||||
prependOptions(QList<QCommandLineOption> &&options);
|
||||
|
||||
/* Run command */
|
||||
/*! Parse current application's command line. */
|
||||
void parseCommandLine();
|
||||
|
||||
/*! Initialize environment value, order:
|
||||
development -> value from env. variable -> --env command-line argument. */
|
||||
void initializeEnvironment();
|
||||
/*! Obtain command name to run. */
|
||||
QString getCommandName();
|
||||
|
||||
/* Early exit during parse command-line */
|
||||
/*! Display the version information and exits. */
|
||||
Q_NORETURN void showVersion() const;
|
||||
/*! Display the version information. */
|
||||
void printVersion() const;
|
||||
/*! Invoke the list command. */
|
||||
Q_NORETURN void showCommandsList(int exitCode);
|
||||
/*! Exit the application with post routines. */
|
||||
Q_NORETURN void exitApplication(int exitCode) const;
|
||||
|
||||
/* Commands factory */
|
||||
/*! Alias for an optional command-line parser reference. */
|
||||
using OptionalParserRef =
|
||||
std::optional<std::reference_wrapper<QCommandLineParser>>;
|
||||
|
||||
/*! Create command by the given name. */
|
||||
std::unique_ptr<Command>
|
||||
createCommand(const QString &command, OptionalParserRef parser = std::nullopt,
|
||||
bool showHelp = true);
|
||||
|
||||
/*! Migration repository instance. */
|
||||
std::shared_ptr<MigrationRepository> createMigrationRepository();
|
||||
/*! Migrator instance. */
|
||||
std::shared_ptr<Migrator> createMigrator();
|
||||
|
||||
/* Others */
|
||||
/*! Get all supported commands list (used by the list command). */
|
||||
const std::vector<std::shared_ptr<Command>> &createCommandsVector();
|
||||
/*! Get all supported commands' names. */
|
||||
const std::vector<const char *> &commandNames() const;
|
||||
/*! Get arguments list from the m_argv array. */
|
||||
QStringList prepareArguments() const;
|
||||
|
||||
/*! Current application argc. */
|
||||
int &m_argc;
|
||||
/*! Current application argv. */
|
||||
char **m_argv;
|
||||
|
||||
/*! DatabaseManager instance. */
|
||||
std::shared_ptr<DatabaseManager> m_db;
|
||||
/*! The migration repository instance. */
|
||||
std::shared_ptr<MigrationRepository> m_repository = nullptr;
|
||||
/*! The migrator service instance. */
|
||||
std::shared_ptr<Migrator> m_migrator = nullptr;
|
||||
|
||||
/* Only one instance can exist in the whole application, auto tests create their
|
||||
own QCoreApplication instance so this has to be excluded. */
|
||||
#ifndef TINYTOM_TESTS_CODE
|
||||
/*! Qt's application instance. */
|
||||
QCoreApplication m_qtApplication;
|
||||
/*! Determine whether the TomApplication has its own QCoreApplication instance. */
|
||||
bool hasQtApplication = true;
|
||||
#else
|
||||
/*! Determine whether the TomApplication has its own QCoreApplication instance. */
|
||||
bool hasQtApplication = false;
|
||||
#endif
|
||||
/*! Command line parser. */
|
||||
QCommandLineParser m_parser {};
|
||||
|
||||
/*! Current environment. */
|
||||
QString m_environment = QStringLiteral("development");
|
||||
/*! Environment variable name that holds a current environment value. */
|
||||
const char *m_environmentEnvName;
|
||||
/*! Migration repository table name. */
|
||||
QString m_migrationTable;
|
||||
|
||||
/*! Migrations vector to process. */
|
||||
std::vector<std::shared_ptr<Migration>> m_migrations;
|
||||
/*! Is this input means interactive? */
|
||||
bool m_interactive = true;
|
||||
|
||||
/*! Application options. */
|
||||
QList<QCommandLineOption> m_options {};
|
||||
|
||||
/* Auto tests helpers */
|
||||
#ifdef TINYTOM_TESTS_CODE
|
||||
public:
|
||||
/*! Run the tom application with the given arguments (used in auto tests). */
|
||||
int runWithArguments(QStringList &&arguments);
|
||||
#endif
|
||||
};
|
||||
|
||||
/* public */
|
||||
|
||||
template<typename ...Migrations>
|
||||
Application &Application::migrations()
|
||||
{
|
||||
m_migrations = {std::make_shared<Migrations>()...};
|
||||
|
||||
// Correct sort order is checked in the Migrator::createMigrationNamesMap()
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* Getters / Setters */
|
||||
|
||||
const QString &Application::environment() const noexcept
|
||||
{
|
||||
return m_environment;
|
||||
}
|
||||
|
||||
Application::DatabaseManager &Application::db() const noexcept
|
||||
{
|
||||
return *m_db;
|
||||
}
|
||||
|
||||
const QCommandLineParser &Application::parser() const noexcept
|
||||
{
|
||||
return m_parser;
|
||||
}
|
||||
|
||||
bool Application::isInteractive() const noexcept
|
||||
{
|
||||
return m_interactive;
|
||||
}
|
||||
|
||||
Application &Application::migrationTable(QString table)
|
||||
{
|
||||
m_migrationTable = std::move(table);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace Tom
|
||||
|
||||
TINYORM_END_COMMON_NAMESPACE
|
||||
|
||||
#endif // TOM_APPLICATION_HPP
|
||||
153
tom/include/tom/commands/command.hpp
Normal file
153
tom/include/tom/commands/command.hpp
Normal file
@@ -0,0 +1,153 @@
|
||||
#pragma once
|
||||
#ifndef TOM_COMMANDS_COMMAND_HPP
|
||||
#define TOM_COMMANDS_COMMAND_HPP
|
||||
|
||||
#include <orm/macros/systemheader.hpp>
|
||||
TINY_SYSTEM_HEADER
|
||||
|
||||
#include "tom/concerns/callscommands.hpp"
|
||||
#include "tom/concerns/interactswithio.hpp"
|
||||
|
||||
TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
|
||||
class QCommandLineOption;
|
||||
|
||||
namespace Orm
|
||||
{
|
||||
class DatabaseConnection;
|
||||
}
|
||||
|
||||
namespace Tom::Commands
|
||||
{
|
||||
|
||||
/*! Positional argument item for a console command. */
|
||||
struct PositionalArgument
|
||||
{
|
||||
/*! Argument name. */
|
||||
QString name;
|
||||
/*! Argument description. */
|
||||
QString description;
|
||||
/*! Appended to the Usage line, if empty the name is used. */
|
||||
QString syntax {};
|
||||
/*! Is argument optional? */
|
||||
bool optional = false;
|
||||
/*! Argument's default value (optional argument only). */
|
||||
QString defaultValue {};
|
||||
};
|
||||
|
||||
/*! Abstract base class for the console command. */
|
||||
class Command : public Concerns::CallsCommands,
|
||||
public Concerns::InteractsWithIO
|
||||
{
|
||||
Q_DISABLE_COPY(Command)
|
||||
|
||||
public:
|
||||
/*! Constructor. */
|
||||
Command(Application &application, QCommandLineParser &parser);
|
||||
/*! Pure virtual destructor. */
|
||||
inline virtual ~Command() = 0;
|
||||
|
||||
/*! The console command name. */
|
||||
virtual QString name() const = 0;
|
||||
/*! The console command description. */
|
||||
virtual QString description() const = 0;
|
||||
|
||||
/*! The console command positional arguments signature. */
|
||||
inline virtual const std::vector<PositionalArgument> &
|
||||
positionalArguments() const;
|
||||
/*! The signature of the console command. */
|
||||
virtual QList<QCommandLineOption> optionsSignature() const;
|
||||
|
||||
/*! The console command help. */
|
||||
inline virtual QString help() const;
|
||||
|
||||
/*! Execute the console command. */
|
||||
virtual int run();
|
||||
/*! Execute the console command with the given arguments. */
|
||||
int runWithArguments(QStringList &&arguments);
|
||||
|
||||
/* Getters */
|
||||
/*! Get the tom application. */
|
||||
inline Application &application() const noexcept;
|
||||
/*! Determine whether a command has own positional arguments. */
|
||||
bool hasPositionalArguments() const;
|
||||
/*! Determine whether a command has own options. */
|
||||
bool hasOptions() const;
|
||||
|
||||
protected:
|
||||
/* Getters */
|
||||
/*! Obtain passed arguments to parse (can come from three sources). */
|
||||
QStringList passedArguments() const;
|
||||
|
||||
/* Parser helpers */
|
||||
/*! Check whether the option name was set in the parser. */
|
||||
bool isSet(const QString &name) const;
|
||||
/*! Returns the option value found for the given option name or empty string. */
|
||||
QString value(const QString &name) const;
|
||||
/*! Get a full command-line value option if value is set in the parser. */
|
||||
QString valueCmd(const QString &name, const QString &key = "") const;
|
||||
/*! Get a full command-line boolean option if it's set in the parser. */
|
||||
QString boolCmd(const QString &name, const QString &key = "") const;
|
||||
|
||||
/*! Check whether a positional argument at the given index was set. */
|
||||
bool hasArgument(QList<QString>::size_type index) const;
|
||||
/*! Get a list of positional arguments. */
|
||||
QStringList arguments() const;
|
||||
/*! Get a positional argument at the given index position. */
|
||||
QString argument(QList<QString>::size_type index) const;
|
||||
/*! Get a positional argument by the given name. */
|
||||
QString argument(const QString &name) const;
|
||||
|
||||
/*! Get a database connection. */
|
||||
Orm::DatabaseConnection &connection(const QString &name) const;
|
||||
/*! Get a command-line parser. */
|
||||
QCommandLineParser &parser() const noexcept;
|
||||
|
||||
/*! Reference to the tom application. */
|
||||
std::reference_wrapper<Application> m_application;
|
||||
/*! Command line parser. */
|
||||
std::reference_wrapper<QCommandLineParser> m_parser;
|
||||
|
||||
/*! Passed command's arguments. */
|
||||
QStringList m_arguments {};
|
||||
|
||||
/*! Alias for the QList command-line option size type. */
|
||||
using OptionsSizeType = QList<QCommandLineOption>::size_type;
|
||||
/*! Map positional argument names to the index for obtaining values. */
|
||||
std::unordered_map<QString, OptionsSizeType> m_positionalArguments {};
|
||||
|
||||
private:
|
||||
/*! Initialize positional arguments map. */
|
||||
void initializePositionalArguments();
|
||||
/*! Show help if --help argument was passed. */
|
||||
void checkHelpArgument() const;
|
||||
/*! Show the error wall and exit the application if the parser fails. */
|
||||
void showParserError(const QCommandLineParser &parser) const;
|
||||
};
|
||||
|
||||
/* public */
|
||||
|
||||
Command::~Command() = default;
|
||||
|
||||
const std::vector<PositionalArgument> &Command::positionalArguments() const
|
||||
{
|
||||
static const std::vector<PositionalArgument> cached;
|
||||
|
||||
return cached;
|
||||
}
|
||||
|
||||
QString Command::help() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
Application &Command::application() const noexcept
|
||||
{
|
||||
return m_application;
|
||||
}
|
||||
|
||||
} // namespace Tom::Commands
|
||||
|
||||
TINYORM_END_COMMON_NAMESPACE
|
||||
|
||||
#endif // TOM_COMMANDS_COMMAND_HPP
|
||||
67
tom/include/tom/commands/database/wipecommand.hpp
Normal file
67
tom/include/tom/commands/database/wipecommand.hpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
#ifndef TOM_COMMANDS_DATABASE_WIPECOMMAND_HPP
|
||||
#define TOM_COMMANDS_DATABASE_WIPECOMMAND_HPP
|
||||
|
||||
#include <orm/macros/systemheader.hpp>
|
||||
TINY_SYSTEM_HEADER
|
||||
|
||||
#include "tom/commands/command.hpp"
|
||||
#include "tom/concerns/confirmable.hpp"
|
||||
|
||||
TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
|
||||
namespace Tom::Commands::Database
|
||||
{
|
||||
|
||||
/*! Drop all tables, views, and types. */
|
||||
class WipeCommand : public Command,
|
||||
public Concerns::Confirmable
|
||||
{
|
||||
Q_DISABLE_COPY(WipeCommand)
|
||||
|
||||
/*! Alias for the Command. */
|
||||
using Command = Commands::Command;
|
||||
|
||||
public:
|
||||
/*! Constructor. */
|
||||
WipeCommand(Application &application, QCommandLineParser &parser);
|
||||
/*! Virtual destructor. */
|
||||
inline ~WipeCommand() override = default;
|
||||
|
||||
/*! The console command name. */
|
||||
inline QString name() const override;
|
||||
/*! The console command description. */
|
||||
inline QString description() const override;
|
||||
|
||||
/*! The signature of the console command. */
|
||||
QList<QCommandLineOption> optionsSignature() const override;
|
||||
|
||||
/*! Execute the console command. */
|
||||
int run() override;
|
||||
|
||||
protected:
|
||||
/*! Drop all of the database tables. */
|
||||
void dropAllTables(const QString &database) const;
|
||||
/*! Drop all of the database views. */
|
||||
void dropAllViews(const QString &database) const;
|
||||
/*! Drop all of the database types. */
|
||||
void dropAllTypes(const QString &database) const;
|
||||
};
|
||||
|
||||
/* public */
|
||||
|
||||
QString WipeCommand::name() const
|
||||
{
|
||||
return QStringLiteral("db:wipe");
|
||||
}
|
||||
|
||||
QString WipeCommand::description() const
|
||||
{
|
||||
return QLatin1String("Drop all tables, views, and types");
|
||||
}
|
||||
|
||||
} // namespace Tom::Commands::Database
|
||||
|
||||
TINYORM_END_COMMON_NAMESPACE
|
||||
|
||||
#endif // TOM_COMMANDS_DATABASE_WIPECOMMAND_HPP
|
||||
51
tom/include/tom/commands/environmentcommand.hpp
Normal file
51
tom/include/tom/commands/environmentcommand.hpp
Normal file
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
#ifndef TOM_COMMANDS_ENVIRONMENTCOMMAND_HPP
|
||||
#define TOM_COMMANDS_ENVIRONMENTCOMMAND_HPP
|
||||
|
||||
#include <orm/macros/systemheader.hpp>
|
||||
TINY_SYSTEM_HEADER
|
||||
|
||||
#include "tom/commands/command.hpp"
|
||||
|
||||
TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
|
||||
namespace Tom::Commands
|
||||
{
|
||||
|
||||
/*! Display the current environment. */
|
||||
class EnvironmentCommand : public Command
|
||||
{
|
||||
Q_DISABLE_COPY(EnvironmentCommand)
|
||||
|
||||
public:
|
||||
/*! Constructor. */
|
||||
EnvironmentCommand(Application &application, QCommandLineParser &parser);
|
||||
/*! Virtual destructor. */
|
||||
inline ~EnvironmentCommand() override = default;
|
||||
|
||||
/*! The console command name. */
|
||||
inline QString name() const override;
|
||||
/*! The console command description. */
|
||||
inline QString description() const override;
|
||||
|
||||
/*! Execute the console command. */
|
||||
int run() override;
|
||||
};
|
||||
|
||||
/* public */
|
||||
|
||||
QString EnvironmentCommand::name() const
|
||||
{
|
||||
return QStringLiteral("env");
|
||||
}
|
||||
|
||||
QString EnvironmentCommand::description() const
|
||||
{
|
||||
return QLatin1String("Display the current framework environment");
|
||||
}
|
||||
|
||||
} // namespace Tom::Commands
|
||||
|
||||
TINYORM_END_COMMON_NAMESPACE
|
||||
|
||||
#endif // TOM_COMMANDS_ENVIRONMENTCOMMAND_HPP
|
||||
85
tom/include/tom/commands/helpcommand.hpp
Normal file
85
tom/include/tom/commands/helpcommand.hpp
Normal file
@@ -0,0 +1,85 @@
|
||||
#pragma once
|
||||
#ifndef TOM_COMMANDS_HELPCOMMAND_HPP
|
||||
#define TOM_COMMANDS_HELPCOMMAND_HPP
|
||||
|
||||
#include <orm/macros/systemheader.hpp>
|
||||
TINY_SYSTEM_HEADER
|
||||
|
||||
#include "tom/commands/command.hpp"
|
||||
#include "tom/concerns/printsoptions.hpp"
|
||||
|
||||
TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
|
||||
namespace Tom::Commands
|
||||
{
|
||||
|
||||
/*! Display help for a command. */
|
||||
class HelpCommand : public Command,
|
||||
public Concerns::PrintsOptions
|
||||
{
|
||||
Q_DISABLE_COPY(HelpCommand)
|
||||
|
||||
public:
|
||||
/*! Constructor. */
|
||||
HelpCommand(Application &application, QCommandLineParser &parser);
|
||||
/*! Virtual destructor. */
|
||||
inline ~HelpCommand() override = default;
|
||||
|
||||
/*! The console command name. */
|
||||
inline QString name() const override;
|
||||
/*! The console command description. */
|
||||
inline QString description() const override;
|
||||
|
||||
/*! The console command positional arguments signature. */
|
||||
const std::vector<PositionalArgument> &positionalArguments() const override;
|
||||
/*! The console command help. */
|
||||
QString help() const override;
|
||||
|
||||
/*! Execute the console command. */
|
||||
int run() override;
|
||||
|
||||
protected:
|
||||
/*! Create command by the given name. */
|
||||
std::unique_ptr<Command> createCommand(const QString &name) const;
|
||||
/*! Validate if all required positional arguments are after optional arguments. */
|
||||
bool validateRequiredArguments(
|
||||
const std::vector<PositionalArgument> &arguments) const;
|
||||
|
||||
/*! Print description section. */
|
||||
void printDescriptionSection(const Command &command) const;
|
||||
/*! Print usage section. */
|
||||
void printUsageSection(
|
||||
const QString &commandNameArg, const Command &command,
|
||||
const std::vector<PositionalArgument> &arguments) const;
|
||||
|
||||
/*! Print positional arguments section. */
|
||||
void printArgumentsSection(
|
||||
const std::vector<PositionalArgument> &arguments) const;
|
||||
/*! Get max. positional argument size in all command arguments. */
|
||||
int argumentsMaxSize(const std::vector<PositionalArgument> &arguments) const;
|
||||
/*! Print a positional's argument default value part. */
|
||||
void printArgumentDefaultValue(const PositionalArgument &argument) const;
|
||||
|
||||
/*! Print options section. */
|
||||
int printOptionsSection(const Command &command) const;
|
||||
/*! Print help section. */
|
||||
void printHelpSection(const Command &command) const;
|
||||
};
|
||||
|
||||
/* public */
|
||||
|
||||
QString HelpCommand::name() const
|
||||
{
|
||||
return QStringLiteral("help");
|
||||
}
|
||||
|
||||
QString HelpCommand::description() const
|
||||
{
|
||||
return QLatin1String("Display help for a command");
|
||||
}
|
||||
|
||||
} // namespace Tom::Commands
|
||||
|
||||
TINYORM_END_COMMON_NAMESPACE
|
||||
|
||||
#endif // TOM_COMMANDS_HELPCOMMAND_HPP
|
||||
51
tom/include/tom/commands/inspirecommand.hpp
Normal file
51
tom/include/tom/commands/inspirecommand.hpp
Normal file
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
#ifndef TOM_COMMANDS_INSPIRECOMMAND_HPP
|
||||
#define TOM_COMMANDS_INSPIRECOMMAND_HPP
|
||||
|
||||
#include <orm/macros/systemheader.hpp>
|
||||
TINY_SYSTEM_HEADER
|
||||
|
||||
#include "tom/commands/command.hpp"
|
||||
|
||||
TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
|
||||
namespace Tom::Commands
|
||||
{
|
||||
|
||||
/*! Display an inspiring quote. */
|
||||
class InspireCommand : public Command
|
||||
{
|
||||
Q_DISABLE_COPY(InspireCommand)
|
||||
|
||||
public:
|
||||
/*! Constructor. */
|
||||
InspireCommand(Application &application, QCommandLineParser &parser);
|
||||
/*! Virtual destructor. */
|
||||
inline ~InspireCommand() override = default;
|
||||
|
||||
/*! The console command name. */
|
||||
inline QString name() const override;
|
||||
/*! The console command description. */
|
||||
inline QString description() const override;
|
||||
|
||||
/*! Execute the console command. */
|
||||
int run() override;
|
||||
};
|
||||
|
||||
/* public */
|
||||
|
||||
QString InspireCommand::name() const
|
||||
{
|
||||
return QStringLiteral("inspire");
|
||||
}
|
||||
|
||||
QString InspireCommand::description() const
|
||||
{
|
||||
return QLatin1String("Display an inspiring quote");
|
||||
}
|
||||
|
||||
} // namespace Tom::Commands
|
||||
|
||||
TINYORM_END_COMMON_NAMESPACE
|
||||
|
||||
#endif // TOM_COMMANDS_INSPIRECOMMAND_HPP
|
||||
89
tom/include/tom/commands/listcommand.hpp
Normal file
89
tom/include/tom/commands/listcommand.hpp
Normal file
@@ -0,0 +1,89 @@
|
||||
#pragma once
|
||||
#ifndef TOM_COMMANDS_LISTCOMMAND_HPP
|
||||
#define TOM_COMMANDS_LISTCOMMAND_HPP
|
||||
|
||||
#include <orm/macros/systemheader.hpp>
|
||||
TINY_SYSTEM_HEADER
|
||||
|
||||
#include "tom/commands/command.hpp"
|
||||
#include "tom/concerns/printsoptions.hpp"
|
||||
|
||||
TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
|
||||
namespace Tom::Commands
|
||||
{
|
||||
|
||||
/*! List all available commands. */
|
||||
class ListCommand : public Command,
|
||||
public Concerns::PrintsOptions
|
||||
{
|
||||
Q_DISABLE_COPY(ListCommand)
|
||||
|
||||
public:
|
||||
/*! Constructor. */
|
||||
ListCommand(Application &application, QCommandLineParser &parser);
|
||||
/*! Virtual destructor. */
|
||||
inline ~ListCommand() override = default;
|
||||
|
||||
/*! The console command name. */
|
||||
inline QString name() const override;
|
||||
/*! The console command description. */
|
||||
inline QString description() const override;
|
||||
|
||||
/*! The console command positional arguments signature. */
|
||||
const std::vector<PositionalArgument> &positionalArguments() const override;
|
||||
/*! The signature of the console command. */
|
||||
QList<QCommandLineOption> optionsSignature() const override;
|
||||
|
||||
/*! The console command help. */
|
||||
QString help() const override;
|
||||
|
||||
/*! Execute the console command. */
|
||||
int run() override;
|
||||
|
||||
protected:
|
||||
/*! Output full commands list. */
|
||||
int full(const QString &namespaceArg);
|
||||
/*! Output raw commands list and nothing else (can be consumed by scripts). */
|
||||
int raw(const QString &namespaceArg);
|
||||
|
||||
/* Commands section */
|
||||
/*! Print commands section. */
|
||||
void printCommandsSection(const QString &namespaceArg, int optionsMaxSize) const;
|
||||
/*! Get max. command size in all command names. */
|
||||
int commandsMaxSize(const std::vector<std::shared_ptr<Command>> &commands,
|
||||
int optionsMaxSize) const;
|
||||
/*! Print commands to the console. */
|
||||
void printCommands(const std::vector<std::shared_ptr<Command>> &commands,
|
||||
int commandsMaxSize, bool hasNamespaceArg) const;
|
||||
/*! Print a new namespace section. */
|
||||
void tryBeginNsSection(QString &renderingNamespace,
|
||||
const QString &commandName, bool hasNamespaceArg) const;
|
||||
/*! Get command's namespace from a command name. */
|
||||
QString commandNamespace(const QString &commandName) const;
|
||||
|
||||
/*! Wrapper for the two methods below, helps to avoid one copy. */
|
||||
const std::vector<std::shared_ptr<Command>> &
|
||||
getCommandsByNamespace(const QString &name) const;
|
||||
/*! Obtain all commands in the given namespace. */
|
||||
std::vector<std::shared_ptr<Command>>
|
||||
getCommandsInNamespace(const QString &name) const;
|
||||
};
|
||||
|
||||
/* public */
|
||||
|
||||
QString ListCommand::name() const
|
||||
{
|
||||
return QStringLiteral("list");
|
||||
}
|
||||
|
||||
QString ListCommand::description() const
|
||||
{
|
||||
return QLatin1String("List commands");
|
||||
}
|
||||
|
||||
} // namespace Tom::Commands
|
||||
|
||||
TINYORM_END_COMMON_NAMESPACE
|
||||
|
||||
#endif // TOM_COMMANDS_LISTCOMMAND_HPP
|
||||
72
tom/include/tom/commands/make/migrationcommand.hpp
Normal file
72
tom/include/tom/commands/make/migrationcommand.hpp
Normal file
@@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
#ifndef TOM_COMMANDS_MAKE_MIGRATIONCOMMAND_HPP
|
||||
#define TOM_COMMANDS_MAKE_MIGRATIONCOMMAND_HPP
|
||||
|
||||
#include <orm/macros/systemheader.hpp>
|
||||
TINY_SYSTEM_HEADER
|
||||
|
||||
#include "tom/commands/command.hpp"
|
||||
#include "tom/migrationcreator.hpp"
|
||||
|
||||
TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
|
||||
namespace Tom::Commands::Make
|
||||
{
|
||||
|
||||
/*! Create a new migration file. */
|
||||
class MigrationCommand : public Command
|
||||
{
|
||||
Q_DISABLE_COPY(MigrationCommand)
|
||||
|
||||
/*! Alias for the filesystem path. */
|
||||
using fspath = std::filesystem::path;
|
||||
|
||||
public:
|
||||
/*! Constructor. */
|
||||
MigrationCommand(Application &application, QCommandLineParser &parser);
|
||||
/*! Virtual destructor. */
|
||||
inline ~MigrationCommand() override = default;
|
||||
|
||||
/*! The console command name. */
|
||||
inline QString name() const override;
|
||||
/*! The console command description. */
|
||||
inline QString description() const override;
|
||||
|
||||
/*! The console command positional arguments signature. */
|
||||
const std::vector<PositionalArgument> &positionalArguments() const override;
|
||||
/*! The signature of the console command. */
|
||||
QList<QCommandLineOption> optionsSignature() const override;
|
||||
|
||||
/*! Execute the console command. */
|
||||
int run() override;
|
||||
|
||||
protected:
|
||||
/*! Write the migration file to disk. */
|
||||
void writeMigration(const QString &name, const QString &table,
|
||||
bool create) const;
|
||||
|
||||
/*! Get migration path (either specified by '--path' option or default
|
||||
location). */
|
||||
fspath getMigrationPath() const;
|
||||
|
||||
/*! The migration creator instance. */
|
||||
MigrationCreator m_creator {};
|
||||
};
|
||||
|
||||
/* public */
|
||||
|
||||
QString MigrationCommand::name() const
|
||||
{
|
||||
return QStringLiteral("make:migration");
|
||||
}
|
||||
|
||||
QString MigrationCommand::description() const
|
||||
{
|
||||
return QLatin1String("Create a new migration file");
|
||||
}
|
||||
|
||||
} // namespace Tom::Commands::Make
|
||||
|
||||
TINYORM_END_COMMON_NAMESPACE
|
||||
|
||||
#endif // TOM_COMMANDS_MAKE_MIGRATIONCOMMAND_HPP
|
||||
78
tom/include/tom/commands/make/projectcommand.hpp
Normal file
78
tom/include/tom/commands/make/projectcommand.hpp
Normal file
@@ -0,0 +1,78 @@
|
||||
#pragma once
|
||||
#ifndef TOM_COMMANDS_MAKE_PROJECTCOMMAND_HPP
|
||||
#define TOM_COMMANDS_MAKE_PROJECTCOMMAND_HPP
|
||||
|
||||
#include <orm/macros/systemheader.hpp>
|
||||
TINY_SYSTEM_HEADER
|
||||
|
||||
#include "tom/commands/command.hpp"
|
||||
//#include "tom/migrationcreator.hpp"
|
||||
|
||||
TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
|
||||
namespace Tom::Commands::Make
|
||||
{
|
||||
|
||||
/*! Create a new Tom application project. */
|
||||
class ProjectCommand : public Command
|
||||
{
|
||||
Q_DISABLE_COPY(ProjectCommand)
|
||||
|
||||
/*! Alias for the filesystem path. */
|
||||
// using path = std::filesystem::path;
|
||||
|
||||
public:
|
||||
/*! Constructor. */
|
||||
ProjectCommand(Application &application, QCommandLineParser &parser);
|
||||
/*! Virtual destructor. */
|
||||
inline ~ProjectCommand() override = default;
|
||||
|
||||
/*! The console command name. */
|
||||
inline QString name() const override;
|
||||
/*! The console command description. */
|
||||
inline QString description() const override;
|
||||
|
||||
/*! The console command positional arguments signature. */
|
||||
const std::vector<PositionalArgument> &positionalArguments() const override;
|
||||
/*! The signature of the console command. */
|
||||
QList<QCommandLineOption> signature() const override;
|
||||
|
||||
/*! Execute the console command. */
|
||||
int run() override;
|
||||
|
||||
protected:
|
||||
/*! Write the migration file to disk. */
|
||||
// void writeMigration(const QString &name, const QString &table,
|
||||
// bool create) const;
|
||||
/*! Get migration path (either specified by '--path' option or default
|
||||
location). */
|
||||
// inline path getMigrationPath() const;
|
||||
|
||||
/*! The migration creator instance. */
|
||||
// MigrationCreator m_creator {};
|
||||
};
|
||||
|
||||
/* public */
|
||||
|
||||
QString ProjectCommand::name() const
|
||||
{
|
||||
return QStringLiteral("make:project");
|
||||
}
|
||||
|
||||
QString ProjectCommand::description() const
|
||||
{
|
||||
return QLatin1String("Create a new Tom application project");
|
||||
}
|
||||
|
||||
/* protected */
|
||||
|
||||
// std::filesystem::path ProjectCommand::getMigrationPath() const
|
||||
// {
|
||||
// return path(__FILE__).parent_path().parent_path().parent_path() / "migrations";
|
||||
// }
|
||||
|
||||
} // namespace Tom::Commands::Make
|
||||
|
||||
TINYORM_END_COMMON_NAMESPACE
|
||||
|
||||
#endif // TOM_COMMANDS_MAKE_PROJECTCOMMAND_HPP
|
||||
110
tom/include/tom/commands/make/stubs/migrationstubs.hpp
Normal file
110
tom/include/tom/commands/make/stubs/migrationstubs.hpp
Normal file
@@ -0,0 +1,110 @@
|
||||
#pragma once
|
||||
#ifndef TOM_COMMANDS_MAKE_STUBS_MIGRATIONSTUBS_HPP
|
||||
#define TOM_COMMANDS_MAKE_STUBS_MIGRATIONSTUBS_HPP
|
||||
|
||||
#include <orm/macros/systemheader.hpp>
|
||||
TINY_SYSTEM_HEADER
|
||||
|
||||
#include <orm/macros/commonnamespace.hpp>
|
||||
|
||||
TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
|
||||
namespace Tom::Commands::Make::Stubs
|
||||
{
|
||||
|
||||
/*! Empty migration stub. */
|
||||
inline const auto *const MigrationStub = R"T(#pragma once
|
||||
|
||||
#include <tom/migration.hpp>
|
||||
|
||||
namespace Migrations
|
||||
{
|
||||
|
||||
struct {{ class }} : Migration
|
||||
{
|
||||
|
||||
/*! Run the migrations. */
|
||||
void up() const override
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/*! Reverse the migrations. */
|
||||
void down() const override
|
||||
{
|
||||
//
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Migrations
|
||||
)T";
|
||||
|
||||
/*! Migration stub for creating a new table. */
|
||||
inline const auto *const MigrationCreateStub = R"T(#pragma once
|
||||
|
||||
#include <tom/migration.hpp>
|
||||
|
||||
namespace Migrations
|
||||
{
|
||||
|
||||
struct {{ class }} : Migration
|
||||
{
|
||||
|
||||
/*! Run the migrations. */
|
||||
void up() const override
|
||||
{
|
||||
Schema::create("{{ table }}", [](Blueprint &table)
|
||||
{
|
||||
table.id();
|
||||
table.timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/*! Reverse the migrations. */
|
||||
void down() const override
|
||||
{
|
||||
Schema::dropIfExists("{{ table }}");
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Migrations
|
||||
)T";
|
||||
|
||||
/*! Migration stub for updating an existing table. */
|
||||
inline const auto *const MigrationUpdateStub = R"T(#pragma once
|
||||
|
||||
#include <tom/migration.hpp>
|
||||
|
||||
namespace Migrations
|
||||
{
|
||||
|
||||
struct {{ class }} : Migration
|
||||
{
|
||||
|
||||
/*! Run the migrations. */
|
||||
void up() const override
|
||||
{
|
||||
Schema::table("{{ table }}", [](Blueprint &table)
|
||||
{
|
||||
//
|
||||
});
|
||||
}
|
||||
|
||||
/*! Reverse the migrations. */
|
||||
void down() const override
|
||||
{
|
||||
Schema::table("{{ table }}", [](Blueprint &table)
|
||||
{
|
||||
//
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Migrations
|
||||
)T";
|
||||
|
||||
} // namespace Tom::Commands::Make::Stubs
|
||||
|
||||
TINYORM_END_COMMON_NAMESPACE
|
||||
|
||||
#endif // TOM_COMMANDS_MAKE_STUBS_MIGRATIONSTUBS_HPP
|
||||
22
tom/include/tom/commands/make/stubs/projectstubs.hpp
Normal file
22
tom/include/tom/commands/make/stubs/projectstubs.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#ifndef TOM_COMMANDS_MAKE_STUBS_PROJECTSTUBS_HPP
|
||||
#define TOM_COMMANDS_MAKE_STUBS_PROJECTSTUBS_HPP
|
||||
|
||||
#include <orm/macros/systemheader.hpp>
|
||||
TINY_SYSTEM_HEADER
|
||||
|
||||
#include <orm/macros/commonnamespace.hpp>
|
||||
|
||||
TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
|
||||
namespace Tom::Commands::Make::Stubs
|
||||
{
|
||||
|
||||
inline const auto *const XyzStub = R"T(#pragma once
|
||||
)T";
|
||||
|
||||
} // namespace Tom::Commands::Make::Stubs
|
||||
|
||||
TINYORM_END_COMMON_NAMESPACE
|
||||
|
||||
#endif // TOM_COMMANDS_MAKE_STUBS_PROJECTSTUBS_HPP
|
||||
74
tom/include/tom/commands/migrations/freshcommand.hpp
Normal file
74
tom/include/tom/commands/migrations/freshcommand.hpp
Normal file
@@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
#ifndef TOM_COMMANDS_MIGRATIONS_FRESHCOMMAND_HPP
|
||||
#define TOM_COMMANDS_MIGRATIONS_FRESHCOMMAND_HPP
|
||||
|
||||
#include <orm/macros/systemheader.hpp>
|
||||
TINY_SYSTEM_HEADER
|
||||
|
||||
#include "tom/commands/command.hpp"
|
||||
#include "tom/concerns/confirmable.hpp"
|
||||
|
||||
TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
|
||||
namespace Tom
|
||||
{
|
||||
class Migrator;
|
||||
|
||||
namespace Commands::Migrations
|
||||
{
|
||||
|
||||
/*! Rollback the last database migration/s. */
|
||||
class FreshCommand : public Command,
|
||||
public Concerns::Confirmable
|
||||
{
|
||||
Q_DISABLE_COPY(FreshCommand)
|
||||
|
||||
/*! Alias for the Command. */
|
||||
using Command = Commands::Command;
|
||||
|
||||
public:
|
||||
/*! Constructor. */
|
||||
FreshCommand(Application &application, QCommandLineParser &parser,
|
||||
std::shared_ptr<Migrator> migrator);
|
||||
/*! Virtual destructor. */
|
||||
inline ~FreshCommand() override = default;
|
||||
|
||||
/*! The console command name. */
|
||||
inline QString name() const override;
|
||||
/*! The console command description. */
|
||||
inline QString description() const override;
|
||||
|
||||
/*! The signature of the console command. */
|
||||
QList<QCommandLineOption> optionsSignature() const override;
|
||||
|
||||
/*! Execute the console command. */
|
||||
int run() override;
|
||||
|
||||
protected:
|
||||
/*! Determine if the developer has requested database seeding. */
|
||||
bool needsSeeding() const;
|
||||
/*! Run the database seeder command. */
|
||||
void runSeeder(QString &&databaseCmd) const;
|
||||
|
||||
/*! The migrator service instance. */
|
||||
std::shared_ptr<Migrator> m_migrator;
|
||||
};
|
||||
|
||||
/* public */
|
||||
|
||||
QString FreshCommand::name() const
|
||||
{
|
||||
return QStringLiteral("migrate:fresh");
|
||||
}
|
||||
|
||||
QString FreshCommand::description() const
|
||||
{
|
||||
return QLatin1String("Drop all tables and re-run all migrations");
|
||||
}
|
||||
|
||||
} // namespace Commands::Migrations
|
||||
} // namespace Tom
|
||||
|
||||
TINYORM_END_COMMON_NAMESPACE
|
||||
|
||||
#endif // TOM_COMMANDS_MIGRATIONS_FRESHCOMMAND_HPP
|
||||
64
tom/include/tom/commands/migrations/installcommand.hpp
Normal file
64
tom/include/tom/commands/migrations/installcommand.hpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
#ifndef TOM_COMMANDS_MIGRATIONS_INSTALLCOMMAND_HPP
|
||||
#define TOM_COMMANDS_MIGRATIONS_INSTALLCOMMAND_HPP
|
||||
|
||||
#include <orm/macros/systemheader.hpp>
|
||||
TINY_SYSTEM_HEADER
|
||||
|
||||
#include "tom/commands/command.hpp"
|
||||
|
||||
TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
|
||||
namespace Tom
|
||||
{
|
||||
class MigrationRepository;
|
||||
|
||||
namespace Commands::Migrations
|
||||
{
|
||||
|
||||
/*! Create the migration database repository. */
|
||||
class InstallCommand : public Command
|
||||
{
|
||||
Q_DISABLE_COPY(InstallCommand)
|
||||
|
||||
public:
|
||||
/*! Constructor. */
|
||||
InstallCommand(Application &application, QCommandLineParser &parser,
|
||||
std::shared_ptr<MigrationRepository> repository);
|
||||
/*! Virtual destructor. */
|
||||
inline ~InstallCommand() override = default;
|
||||
|
||||
/*! The console command name. */
|
||||
inline QString name() const override;
|
||||
/*! The console command description. */
|
||||
inline QString description() const override;
|
||||
|
||||
/*! The signature of the console command. */
|
||||
QList<QCommandLineOption> optionsSignature() const override;
|
||||
|
||||
/*! Execute the console command. */
|
||||
int run() override;
|
||||
|
||||
protected:
|
||||
/*! The repository instance. */
|
||||
std::shared_ptr<MigrationRepository> m_repository;
|
||||
};
|
||||
|
||||
/* public */
|
||||
|
||||
QString InstallCommand::name() const
|
||||
{
|
||||
return QStringLiteral("migrate:install");
|
||||
}
|
||||
|
||||
QString InstallCommand::description() const
|
||||
{
|
||||
return QLatin1String("Create the migration repository");
|
||||
}
|
||||
|
||||
} // namespace Commands::Migrations
|
||||
} // namespace Tom
|
||||
|
||||
TINYORM_END_COMMON_NAMESPACE
|
||||
|
||||
#endif // TOM_COMMANDS_MIGRATIONS_INSTALLCOMMAND_HPP
|
||||
79
tom/include/tom/commands/migrations/migratecommand.hpp
Normal file
79
tom/include/tom/commands/migrations/migratecommand.hpp
Normal file
@@ -0,0 +1,79 @@
|
||||
#pragma once
|
||||
#ifndef TOM_COMMANDS_MIGRATIONS_MIGRATECOMMAND_HPP
|
||||
#define TOM_COMMANDS_MIGRATIONS_MIGRATECOMMAND_HPP
|
||||
|
||||
#include <orm/macros/systemheader.hpp>
|
||||
TINY_SYSTEM_HEADER
|
||||
|
||||
#include "tom/commands/command.hpp"
|
||||
#include "tom/concerns/confirmable.hpp"
|
||||
|
||||
TINYORM_BEGIN_COMMON_NAMESPACE
|
||||
|
||||
namespace Tom
|
||||
{
|
||||
class Migrator;
|
||||
|
||||
namespace Commands::Migrations
|
||||
{
|
||||
|
||||
/*! Run the database migrations up/down. */
|
||||
class MigrateCommand : public Command,
|
||||
public Concerns::Confirmable
|
||||
{
|
||||
Q_DISABLE_COPY(MigrateCommand)
|
||||
|
||||
/*! Alias for the Command. */
|
||||
using Command = Commands::Command;
|
||||
|
||||
public:
|
||||
/*! Constructor. */
|
||||
MigrateCommand(Application &application, QCommandLineParser &parser,
|
||||
std::shared_ptr<Migrator> migrator);
|
||||
/*! Virtual destructor. */
|
||||
inline ~MigrateCommand() override = default;
|
||||
|
||||
/*! The console command name. */
|
||||
inline QString name() const override;
|
||||
/*! The console command description. */
|
||||
inline QString description() const override;
|
||||
|
||||
/*! The signature of the console command. */
|
||||
QList<QCommandLineOption> optionsSignature() const override;
|
||||
|
||||
/*! Execute the console command. */
|
||||
int run() override;
|
||||
|
||||
protected:
|
||||
/*! Prepare the migration database for running. */
|
||||
void prepareDatabase() const;
|
||||
/*! Load the schema state to seed the initial database schema structure. */
|
||||
void loadSchemaState() const;
|
||||
|
||||
/*! Determine if the developer has requested database seeding. */
|
||||
bool needsSeeding() const;
|
||||
/*! Run the database seeder command. */
|
||||
void runSeeder() const;
|
||||
|
||||
/*! The migrator service instance. */
|
||||
std::shared_ptr<Migrator> m_migrator;
|
||||
};
|
||||
|
||||
/* public */
|
||||
|
||||
QString MigrateCommand::name() const
|
||||
{
|
||||
return QStringLiteral("migrate");
|
||||
}
|
||||
|
||||
QString MigrateCommand::description() const
|
||||
{
|
||||
return QLatin1String("Run the database migrations");
|
||||
}
|
||||
|
||||
} // namespace Commands::Migrations
|
||||
} // namespace Tom
|
||||
|
||||
TINYORM_END_COMMON_NAMESPACE
|
||||
|
||||
#endif // TOM_COMMANDS_MIGRATIONS_MIGRATECOMMAND_HPP
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user