From 202ddf76584da9c501fa118c05637a4810e9bcd5 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Tue, 2 Apr 2019 18:19:32 +0430 Subject: [PATCH 001/232] Change travis config to use cmake. (see #256) --- .travis.yml | 172 +++++++++++++++++++++++++++++----------------------- 1 file changed, 97 insertions(+), 75 deletions(-) diff --git a/.travis.yml b/.travis.yml index bf1cc60f9..543a3cc65 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,81 +1,103 @@ +# ITNOA +# Copyright (c) 2012-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com) +# request for Ubuntu 14.04 Trusty VM +sudo: true +dist: trusty language: cpp -sudo: required -compiler: - - clang +cache: + apt: true -os: - - osx +matrix: + include: + - name: "gcc default (4.8)" + compiler: gcc + env: + - CC=gcc + - CXX=g++ + - name: "gcc 4.9" + compiler: gcc + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-4.9 + env: + - CC=gcc-4.9 + - CXX=g++-4.9 + name: "gcc 5" + compiler: gcc + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-5 + env: + - CC=gcc-5 + - CXX=g++-5 + name: "gcc 6" + compiler: gcc + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-6 + env: + - CC=gcc-6 + - CXX=g++-6 + - name: "gcc 7" + compiler: gcc + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-7 + env: + - CC=gcc-7 + - CXX=g++-7 + - name: "clang default" + compiler: clang + env: + - CC=clang + - CXX=clang++ + - name: "osx" + compiler: clang + os: osx + env: + - CC=clang + - CXX=clang +before_install: + addons: + apt: + packages: + - cmake + - git + - cd thrid_party + - git clone https://github.com/Microsoft/vcpkg.git vcpkg + - cd vcpkg + - ./bootstarp-vcpkg.bat + - ./vcpkg install gtest + - cd ../.. + # coveralls test coverage: + - if [[ "$CXX" == "g++" ]]; then pip install --user cpp-coveralls ; fi + +# scripts to run before build +before_script: + - mkdir compile + - cd compile + - cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../third_party/vcpkg/scripts/buildsystems/vcpkg.cmake .. + +# build examples, and run tests (ie make & make test) script: - - wget https://sqlite.org/2017/sqlite-amalgamation-3190300.zip - - unzip sqlite-amalgamation-3190300.zip - - mkdir sqlite_amalgamation - - cp -r sqlite-amalgamation-3190300/* sqlite_amalgamation - - rm sqlite-amalgamation-3190300.zip - - clang -c sqlite-amalgamation-3190300/sqlite3.c -o sqlite.static - - clang++ -std=c++1y tests/tests.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -stdlib=libc++ -o tests.out - - ./tests.out - - clang++ -std=c++1y tests/tests.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -stdlib=libc++ -D SQLITE_ORM_OMITS_CODECVT -o tests_without_codecvt.out - - ./tests_without_codecvt.out - - clang++ -std=c++1y tests/static_tests.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -stdlib=libc++ -o static_tests.out - - ./static_tests.out - - clang++ -std=c++1y examples/core_functions.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -o a.out - - ./a.out - - clang++ -std=c++1y examples/distinct.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -o a.out - - ./a.out - - clang++ -std=c++1y examples/enum_binding.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -o a.out - - ./a.out - - clang++ -std=c++1y examples/group_by.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -o a.out - - ./a.out - - clang++ -std=c++1y examples/in_memory.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -o a.out - - ./a.out - - clang++ -std=c++1y examples/iteration.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -o a.out - - ./a.out - - clang++ -std=c++1y examples/key_value.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -o a.out - - ./a.out - - clang++ -std=c++1y examples/nullable_enum_binding.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -o a.out - - ./a.out - - clang++ -std=c++1y examples/select.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -o a.out - - ./a.out - - clang++ -std=c++1y examples/subentities.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -o a.out - - ./a.out - - clang++ -std=c++1y examples/insert.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -o a.out - - ./a.out - - clang++ -std=c++1y examples/update.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -o a.out - - ./a.out - - clang++ -std=c++1y examples/multi_table_select.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -o a.out - - ./a.out - - clang++ -std=c++1y examples/cross_join.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -o a.out - - ./a.out - - clang++ -std=c++1y examples/blob.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -o a.out - - ./a.out - - clang++ -std=c++1y examples/foreign_key.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -o a.out - - ./a.out - - clang++ -std=c++1y examples/index.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -o a.out - - ./a.out - - clang++ -std=c++1y examples/date_time.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -o a.out - - ./a.out - - clang++ -std=c++1y examples/composite_key.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -o a.out - - ./a.out - - clang++ -std=c++1y examples/unique.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -o a.out - - ./a.out - - clang++ -std=c++1y examples/synchronous.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -o a.out - - ./a.out - - clang++ -std=c++1y examples/self_join.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -o a.out - - ./a.out - - clang++ -std=c++1y examples/natural_join.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -o a.out - - ./a.out - - clang++ -std=c++1y examples/union.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -o a.out - - ./a.out - - clang++ -std=c++1y examples/subquery.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -o a.out - - ./a.out - - clang++ -std=c++1y examples/having.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -o a.out - - ./a.out - - clang++ -std=c++1y examples/exists.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -o a.out - - ./a.out - - clang++ -std=c++1y examples/except_intersection.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -o a.out - - ./a.out - - clang++ -std=c++1y examples/custom_aliases.cpp sqlite.static -I include/ -I sqlite_amalgamation/ -ldl -lpthread -o a.out - - ./a.out + - cmake --build . --config Debug + - ctest --verbose --output-on-failure -C Debug + +# generate and publish GCov coveralls results +after_success: + - if [[ "$CXX" == "g++" ]]; then coveralls --root .. -e examples -e googletest -e sqlite3 -e tests -E ".*feature_tests.*" -E ".*CompilerId.*" --gcov-options '\-lp' ; fi \ No newline at end of file From 65f0b94b9276f21613452b669ea80b65178bf1b0 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Tue, 2 Apr 2019 18:35:15 +0430 Subject: [PATCH 002/232] Comment vcpkg for testing. (see #256) --- .travis.yml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index 543a3cc65..40418855e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -73,17 +73,17 @@ matrix: - CXX=clang before_install: - addons: - apt: - packages: - - cmake - - git - - cd thrid_party - - git clone https://github.com/Microsoft/vcpkg.git vcpkg - - cd vcpkg - - ./bootstarp-vcpkg.bat - - ./vcpkg install gtest - - cd ../.. + # addons: + # apt: + # packages: + # - cmake + # - git + # - cd thrid_party + # - git clone https://github.com/Microsoft/vcpkg.git vcpkg + # - cd vcpkg + # - ./bootstarp-vcpkg.bat + # - ./vcpkg install gtest + # - cd ../.. # coveralls test coverage: - if [[ "$CXX" == "g++" ]]; then pip install --user cpp-coveralls ; fi From 2c3362372302f89dab3e8975bb21eac401e410ea Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Tue, 2 Apr 2019 18:43:15 +0430 Subject: [PATCH 003/232] Add install git. (see #256) --- .travis.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 40418855e..b9d18e195 100644 --- a/.travis.yml +++ b/.travis.yml @@ -73,11 +73,11 @@ matrix: - CXX=clang before_install: - # addons: - # apt: - # packages: - # - cmake - # - git + addons: + apt: + packages: + - cmake + - git # - cd thrid_party # - git clone https://github.com/Microsoft/vcpkg.git vcpkg # - cd vcpkg From 957c43b29476f4bf7fb7a120d3564f8375d85878 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Tue, 2 Apr 2019 18:47:52 +0430 Subject: [PATCH 004/232] Add install git in global. (see #256) --- .travis.yml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index b9d18e195..e024891d7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,16 @@ language: cpp cache: apt: true +addons: + apt: + packages: + - cmake + - git + homeberaw: + packages: + - cmake + - git + matrix: include: - name: "gcc default (4.8)" @@ -73,11 +83,6 @@ matrix: - CXX=clang before_install: - addons: - apt: - packages: - - cmake - - git # - cd thrid_party # - git clone https://github.com/Microsoft/vcpkg.git vcpkg # - cd vcpkg From 1d1777939c90f3f0374a0fc33fc45cf538127068 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Tue, 2 Apr 2019 18:49:36 +0430 Subject: [PATCH 005/232] uncomment vcpkg. (see #256) --- .travis.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index e024891d7..e4194dcc7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -83,12 +83,12 @@ matrix: - CXX=clang before_install: - # - cd thrid_party - # - git clone https://github.com/Microsoft/vcpkg.git vcpkg - # - cd vcpkg - # - ./bootstarp-vcpkg.bat - # - ./vcpkg install gtest - # - cd ../.. + - cd thrid_party + - git clone https://github.com/Microsoft/vcpkg.git vcpkg + - cd vcpkg + - ./bootstarp-vcpkg.bat + - ./vcpkg install gtest + - cd ../.. # coveralls test coverage: - if [[ "$CXX" == "g++" ]]; then pip install --user cpp-coveralls ; fi From bf3bd5a7a9a52e43d6dd24e37f92894c352e6f15 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Tue, 2 Apr 2019 18:56:35 +0430 Subject: [PATCH 006/232] change vcpkg to before_script. (see #256) --- .travis.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index e4194dcc7..e8a07e87a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -82,18 +82,19 @@ matrix: - CC=clang - CXX=clang + before_install: + # coveralls test coverage: + - if [[ "$CXX" == "g++" ]]; then pip install --user cpp-coveralls ; fi + +# scripts to run before build +before_script: - cd thrid_party - git clone https://github.com/Microsoft/vcpkg.git vcpkg - cd vcpkg - ./bootstarp-vcpkg.bat - ./vcpkg install gtest - cd ../.. - # coveralls test coverage: - - if [[ "$CXX" == "g++" ]]; then pip install --user cpp-coveralls ; fi - -# scripts to run before build -before_script: - mkdir compile - cd compile - cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../third_party/vcpkg/scripts/buildsystems/vcpkg.cmake .. From d2f4d5e93bf18ac72b406a39d853dce579609681 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Tue, 2 Apr 2019 19:02:35 +0430 Subject: [PATCH 007/232] Correct thrid_party name. (see #256) --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e8a07e87a..b4670de96 100644 --- a/.travis.yml +++ b/.travis.yml @@ -89,7 +89,8 @@ before_install: # scripts to run before build before_script: - - cd thrid_party + - ls -a + - cd third_party - git clone https://github.com/Microsoft/vcpkg.git vcpkg - cd vcpkg - ./bootstarp-vcpkg.bat From 0895cc1a58de541f260ec0af12d6cd1a54b1193c Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Tue, 2 Apr 2019 19:08:00 +0430 Subject: [PATCH 008/232] Correct bootstrap name. (see #256) --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index b4670de96..3a87e1677 100644 --- a/.travis.yml +++ b/.travis.yml @@ -89,11 +89,10 @@ before_install: # scripts to run before build before_script: - - ls -a - cd third_party - git clone https://github.com/Microsoft/vcpkg.git vcpkg - cd vcpkg - - ./bootstarp-vcpkg.bat + - ./bootstrap-vcpkg.bat - ./vcpkg install gtest - cd ../.. - mkdir compile From 7fab5ea2df59bd611db1f8c4a446b425c264a08b Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Tue, 2 Apr 2019 19:12:25 +0430 Subject: [PATCH 009/232] chmod script. (see #256) --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3a87e1677..1a71fd8c2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -92,7 +92,9 @@ before_script: - cd third_party - git clone https://github.com/Microsoft/vcpkg.git vcpkg - cd vcpkg - - ./bootstrap-vcpkg.bat + - chmod +x bootstrap-vcpkg.sh + - ./bootstrap-vcpkg.sh + - chmod +x vcpkg - ./vcpkg install gtest - cd ../.. - mkdir compile From ee2d4ccc442c48fcb6afb262f7b21bae4328e78c Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Tue, 2 Apr 2019 19:28:12 +0430 Subject: [PATCH 010/232] Remove unsuported compiler. (see #256) --- .travis.yml | 42 ++---------------------------------------- 1 file changed, 2 insertions(+), 40 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1a71fd8c2..375e77651 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,9 @@ # ITNOA # Copyright (c) 2012-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com) -# request for Ubuntu 14.04 Trusty VM +# request for Ubuntu 16.04 Trusty VM sudo: true -dist: trusty +dist: xenial language: cpp cache: @@ -21,44 +21,6 @@ addons: matrix: include: - - name: "gcc default (4.8)" - compiler: gcc - env: - - CC=gcc - - CXX=g++ - - name: "gcc 4.9" - compiler: gcc - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - g++-4.9 - env: - - CC=gcc-4.9 - - CXX=g++-4.9 - name: "gcc 5" - compiler: gcc - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - g++-5 - env: - - CC=gcc-5 - - CXX=g++-5 - name: "gcc 6" - compiler: gcc - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - g++-6 - env: - - CC=gcc-6 - - CXX=g++-6 - name: "gcc 7" compiler: gcc addons: From b0e3ff0343021685c8e56468cc5701c32e99a50e Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Tue, 2 Apr 2019 19:46:22 +0430 Subject: [PATCH 011/232] Change vcpkg in g++7. (see #256) --- .travis.yml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 375e77651..f7b15fcda 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,6 +29,11 @@ matrix: - ubuntu-toolchain-r-test packages: - g++-7 + - cd third_party/vcpkg + - ./bootstrap-vcpkg.sh + - chmod +x vcpkg + - ./vcpkg install gtest + - cd ../.. env: - CC=gcc-7 - CXX=g++-7 @@ -55,9 +60,9 @@ before_script: - git clone https://github.com/Microsoft/vcpkg.git vcpkg - cd vcpkg - chmod +x bootstrap-vcpkg.sh - - ./bootstrap-vcpkg.sh - - chmod +x vcpkg - - ./vcpkg install gtest +# - ./bootstrap-vcpkg.sh +# - chmod +x vcpkg +# - ./vcpkg install gtest - cd ../.. - mkdir compile - cd compile From 162f016b2b74346099b4691eac36bec807d5c289 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Tue, 2 Apr 2019 19:50:48 +0430 Subject: [PATCH 012/232] Correct before_script. (see #256) --- .travis.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index f7b15fcda..ed2e48a4c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,11 +29,12 @@ matrix: - ubuntu-toolchain-r-test packages: - g++-7 - - cd third_party/vcpkg - - ./bootstrap-vcpkg.sh - - chmod +x vcpkg - - ./vcpkg install gtest - - cd ../.. + before_script: + - cd third_party/vcpkg + - ./bootstrap-vcpkg.sh + - chmod +x vcpkg + - ./vcpkg install gtest + - cd ../.. env: - CC=gcc-7 - CXX=g++-7 From e17a3a7d3c15bbe39fccf83ee2c11d069fefed3a Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Tue, 2 Apr 2019 21:09:43 +0430 Subject: [PATCH 013/232] Add install to gcc7. (see #256) --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index ed2e48a4c..e86b86823 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,6 +23,7 @@ matrix: include: - name: "gcc 7" compiler: gcc + install: addons: apt: sources: From 416a40c2e38bb57c50ef8e51d755adf033a7f3ba Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Tue, 2 Apr 2019 21:16:39 +0430 Subject: [PATCH 014/232] remove install to gcc7. (see #256) --- .travis.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index e86b86823..4834c892a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,7 @@ cache: addons: apt: + update: true packages: - cmake - git @@ -23,19 +24,18 @@ matrix: include: - name: "gcc 7" compiler: gcc - install: addons: apt: sources: - ubuntu-toolchain-r-test packages: - g++-7 - before_script: - - cd third_party/vcpkg - - ./bootstrap-vcpkg.sh - - chmod +x vcpkg - - ./vcpkg install gtest - - cd ../.. +# before_script: +# - cd third_party/vcpkg +# - ./bootstrap-vcpkg.sh +# - chmod +x vcpkg +# - ./vcpkg install gtest +# - cd ../.. env: - CC=gcc-7 - CXX=g++-7 @@ -62,9 +62,9 @@ before_script: - git clone https://github.com/Microsoft/vcpkg.git vcpkg - cd vcpkg - chmod +x bootstrap-vcpkg.sh -# - ./bootstrap-vcpkg.sh -# - chmod +x vcpkg -# - ./vcpkg install gtest + - ./bootstrap-vcpkg.sh + - chmod +x vcpkg + - ./vcpkg install gtest - cd ../.. - mkdir compile - cd compile From 285ebc09819d282f01cc7c74554f21f452e513f3 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Tue, 2 Apr 2019 21:28:24 +0430 Subject: [PATCH 015/232] Add build.sh (see #256) --- .travis.yml | 18 ++++++++++-------- build.sh | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 8 deletions(-) create mode 100644 build.sh diff --git a/.travis.yml b/.travis.yml index 4834c892a..9f686f1d5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -58,14 +58,16 @@ before_install: # scripts to run before build before_script: - - cd third_party - - git clone https://github.com/Microsoft/vcpkg.git vcpkg - - cd vcpkg - - chmod +x bootstrap-vcpkg.sh - - ./bootstrap-vcpkg.sh - - chmod +x vcpkg - - ./vcpkg install gtest - - cd ../.. + - g++ --version + - build.sh +# - cd third_party +# - git clone https://github.com/Microsoft/vcpkg.git vcpkg +# - cd vcpkg +# - chmod +x bootstrap-vcpkg.sh +# - ./bootstrap-vcpkg.sh +# - chmod +x vcpkg +# - ./vcpkg install gtest +# - cd ../.. - mkdir compile - cd compile - cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../third_party/vcpkg/scripts/buildsystems/vcpkg.cmake .. diff --git a/build.sh b/build.sh new file mode 100644 index 000000000..1b66400b2 --- /dev/null +++ b/build.sh @@ -0,0 +1,37 @@ +#!/bin/sh +# Copyright (c) 2012-2019 Sébastien Rombauts (sebastien.rombauts@gmail.com) +# +# Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt +# or copy at http://opensource.org/licenses/MIT) + +# exit on firts error +set -e + +echo "g++ version: " +g++ --version + +sudo apt-get install g++-7 -y + +echo "g++ version after install: " +g++ --version + +cd third_party +git clone https://github.com/Microsoft/vcpkg.git vcpkg +cd vcpkg +chmod +x bootstrap-vcpkg.sh +./bootstrap-vcpkg.sh +chmod +x vcpkg +./vcpkg install gtest +cd ../.. + +#mkdir -p build +#cd build +# +## Generate a Makefile for GCC (or Clang, depanding on CC/CXX envvar) +#cmake -DCMAKE_BUILD_TYPE=Debug -DSQLITECPP_USE_GCOV=OFF -DSQLITECPP_BUILD_EXAMPLES=ON -DSQLITECPP_BUILD_TESTS=ON .. +# +## Build (ie 'make') +#cmake --build . +# +## Build and run unit-tests (ie 'make test') +#ctest --output-on-failure \ No newline at end of file From 521a13b3bb8574f66afc73d192a91918dbc789cf Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Tue, 2 Apr 2019 21:36:24 +0430 Subject: [PATCH 016/232] Update travis.yml to use g++7 (see #256) --- .travis.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9f686f1d5..7a3ed3fd5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ # request for Ubuntu 16.04 Trusty VM sudo: true dist: xenial -language: cpp +#language: cpp cache: apt: true @@ -59,7 +59,9 @@ before_install: # scripts to run before build before_script: - g++ --version - - build.sh + - g++-7 --version + - chmod +x build.sh + - ./build.sh # - cd third_party # - git clone https://github.com/Microsoft/vcpkg.git vcpkg # - cd vcpkg From 6ce328caf96d64133520d242f9c292e115ef2e13 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Tue, 2 Apr 2019 21:47:19 +0430 Subject: [PATCH 017/232] Remove g++ in clang test (see #256) --- .travis.yml | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7a3ed3fd5..14eab486c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,12 +30,6 @@ matrix: - ubuntu-toolchain-r-test packages: - g++-7 -# before_script: -# - cd third_party/vcpkg -# - ./bootstrap-vcpkg.sh -# - chmod +x vcpkg -# - ./vcpkg install gtest -# - cd ../.. env: - CC=gcc-7 - CXX=g++-7 @@ -58,18 +52,15 @@ before_install: # scripts to run before build before_script: - - g++ --version - - g++-7 --version - chmod +x build.sh - - ./build.sh -# - cd third_party -# - git clone https://github.com/Microsoft/vcpkg.git vcpkg -# - cd vcpkg -# - chmod +x bootstrap-vcpkg.sh -# - ./bootstrap-vcpkg.sh -# - chmod +x vcpkg -# - ./vcpkg install gtest -# - cd ../.. + - cd third_party + - git clone https://github.com/Microsoft/vcpkg.git vcpkg + - cd vcpkg + - chmod +x bootstrap-vcpkg.sh + - ./bootstrap-vcpkg.sh + - chmod +x vcpkg + - ./vcpkg install gtest + - cd ../.. - mkdir compile - cd compile - cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../third_party/vcpkg/scripts/buildsystems/vcpkg.cmake .. From d953fddb130a4b399ade9f2e6414b0cba919f7b5 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Tue, 2 Apr 2019 21:55:12 +0430 Subject: [PATCH 018/232] Add osx image. (see #256) --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 14eab486c..d9e0b1180 100644 --- a/.travis.yml +++ b/.travis.yml @@ -41,6 +41,7 @@ matrix: - name: "osx" compiler: clang os: osx + osx_image: xcode10.1 env: - CC=clang - CXX=clang From 29e7b397caa0e62513b9b80e52064b2a46b8666a Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Tue, 2 Apr 2019 22:09:47 +0430 Subject: [PATCH 019/232] Add allow clang apple for vcpkg. (see #256) --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index d9e0b1180..59c188be8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,6 +45,7 @@ matrix: env: - CC=clang - CXX=clang + - VCPKG_ALLOW_APPLE_CLANG=1 before_install: From af08d84d3259aa82b98e2e478649152095debeaf Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Tue, 2 Apr 2019 22:18:20 +0430 Subject: [PATCH 020/232] Add SQLITE_ORM_OMITS_CODECVT flag to cmake in travis. (see #256) --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 59c188be8..486e51cb4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -65,7 +65,8 @@ before_script: - cd ../.. - mkdir compile - cd compile - - cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../third_party/vcpkg/scripts/buildsystems/vcpkg.cmake .. + - if [[ "$TRAVIS_JOB_NAME" == "clang default" ]]; then cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../third_party/vcpkg/scripts/buildsystems/vcpkg.cmake -DSQLITE_ORM_OMITS_CODECVT=1 .. ; else \ + cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../third_party/vcpkg/scripts/buildsystems/vcpkg.cmake .. ; fi # build examples, and run tests (ie make & make test) script: From 5d8b8076e9acabdb766e43e9811c2ab072ba0541 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Wed, 3 Apr 2019 00:07:45 +0430 Subject: [PATCH 021/232] Try to investigate problem about cmake does not found. (see #256) --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 486e51cb4..e3e107afd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -65,7 +65,7 @@ before_script: - cd ../.. - mkdir compile - cd compile - - if [[ "$TRAVIS_JOB_NAME" == "clang default" ]]; then cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../third_party/vcpkg/scripts/buildsystems/vcpkg.cmake -DSQLITE_ORM_OMITS_CODECVT=1 .. ; else \ + - if [ "$TRAVIS_JOB_NAME" = "clang default" ]; then cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../third_party/vcpkg/scripts/buildsystems/vcpkg.cmake -DSQLITE_ORM_OMITS_CODECVT=1 .. ; else \ cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../third_party/vcpkg/scripts/buildsystems/vcpkg.cmake .. ; fi # build examples, and run tests (ie make & make test) From b1944bfb115146744e0ad4ad36744edca7249453 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Wed, 3 Apr 2019 01:26:16 +0430 Subject: [PATCH 022/232] Try to investigate problem about cmake does not found. (see #256) --- .travis.yml | 2 +- build.sh | 27 ++++++++++++++++----------- tests/CMakeLists.txt | 7 +++++++ 3 files changed, 24 insertions(+), 12 deletions(-) mode change 100644 => 100755 build.sh diff --git a/.travis.yml b/.travis.yml index e3e107afd..4099d491c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -65,7 +65,7 @@ before_script: - cd ../.. - mkdir compile - cd compile - - if [ "$TRAVIS_JOB_NAME" = "clang default" ]; then cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../third_party/vcpkg/scripts/buildsystems/vcpkg.cmake -DSQLITE_ORM_OMITS_CODECVT=1 .. ; else \ + - if [ "$TRAVIS_JOB_NAME" = "clang default" ]; then cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../third_party/vcpkg/scripts/buildsystems/vcpkg.cmake -DSQLITE_ORM_OMITS_CODECVT=ON .. ; else \ cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../third_party/vcpkg/scripts/buildsystems/vcpkg.cmake .. ; fi # build examples, and run tests (ie make & make test) diff --git a/build.sh b/build.sh old mode 100644 new mode 100755 index 1b66400b2..48606914d --- a/build.sh +++ b/build.sh @@ -10,19 +10,24 @@ set -e echo "g++ version: " g++ --version -sudo apt-get install g++-7 -y +mkdir -p compile +cd compile + +TRAVIS_JOB_NAME="clang default" + +if [ "$TRAVIS_JOB_NAME" = "clang default" ]; then cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../third_party/vcpkg/scripts/buildsystems/vcpkg.cmake -DSQLITE_ORM_OMITS_CODECVT=ON .. ; else\ + cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../third_party/vcpkg/scripts/buildsystems/vcpkg.cmake .. ; fi + -echo "g++ version after install: " -g++ --version -cd third_party -git clone https://github.com/Microsoft/vcpkg.git vcpkg -cd vcpkg -chmod +x bootstrap-vcpkg.sh -./bootstrap-vcpkg.sh -chmod +x vcpkg -./vcpkg install gtest -cd ../.. +#cd third_party +#git clone https://github.com/Microsoft/vcpkg.git vcpkg +#cd vcpkg +#chmod +x bootstrap-vcpkg.sh +#./bootstrap-vcpkg.sh +#chmod +x vcpkg +#./vcpkg install gtest +#cd ../.. #mkdir -p build #cd build diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5e53ee5a1..45a153b3c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,5 +1,7 @@ cmake_minimum_required (VERSION 3.2) +option(SQLITE_ORM_OMITS_CODECVT "Omits codec testing" OFF) + option(SqliteOrm_SysSqlite "Use system version of sqlite library" OFF) if(SqliteOrm_SysSqlite) @@ -10,6 +12,11 @@ endif() add_executable(unit_tests tests.cpp) +if(SQLITE_ORM_OMITS_CODECVT) + message(STATUS "SQLITE_ORM_OMITS_CODECVT is enabled") + target_compile_definitions(unit_tests PRIVATE SQLITE_ORM_OMITS_CODECVT=1) +endif() + target_link_libraries(unit_tests PRIVATE sqlite_orm sqlite3) add_test(NAME "All_in_one_unit_test" From df8e120ed6a1adeafe86086f6f2b42e4845d5e4b Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Wed, 3 Apr 2019 01:36:08 +0430 Subject: [PATCH 023/232] Try to investigate problem about cmake does not found. (see #256) --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4099d491c..8dad8c103 100644 --- a/.travis.yml +++ b/.travis.yml @@ -65,7 +65,7 @@ before_script: - cd ../.. - mkdir compile - cd compile - - if [ "$TRAVIS_JOB_NAME" = "clang default" ]; then cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../third_party/vcpkg/scripts/buildsystems/vcpkg.cmake -DSQLITE_ORM_OMITS_CODECVT=ON .. ; else \ + - if [ "$TRAVIS_JOB_NAME" = "clang default" ]; then cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../third_party/vcpkg/scripts/buildsystems/vcpkg.cmake -DSQLITE_ORM_OMITS_CODECVT=ON .. ; else\ cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../third_party/vcpkg/scripts/buildsystems/vcpkg.cmake .. ; fi # build examples, and run tests (ie make & make test) From cae0e0945dd17957238f10f5ee429f83be48fc4b Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Wed, 3 Apr 2019 01:50:06 +0430 Subject: [PATCH 024/232] Try to investigate problem about cmake does not found. (see #256) --- .travis.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8dad8c103..8a50e0a01 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,11 +33,13 @@ matrix: env: - CC=gcc-7 - CXX=g++-7 + - SQLITE_ORM_OMITS_CODECVT=OFF - name: "clang default" compiler: clang env: - CC=clang - CXX=clang++ + - SQLITE_ORM_OMITS_CODECVT=ON - name: "osx" compiler: clang os: osx @@ -46,6 +48,7 @@ matrix: - CC=clang - CXX=clang - VCPKG_ALLOW_APPLE_CLANG=1 + - SQLITE_ORM_OMITS_CODECVT=ON before_install: @@ -65,8 +68,7 @@ before_script: - cd ../.. - mkdir compile - cd compile - - if [ "$TRAVIS_JOB_NAME" = "clang default" ]; then cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../third_party/vcpkg/scripts/buildsystems/vcpkg.cmake -DSQLITE_ORM_OMITS_CODECVT=ON .. ; else\ - cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../third_party/vcpkg/scripts/buildsystems/vcpkg.cmake .. ; fi + - cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../third_party/vcpkg/scripts/buildsystems/vcpkg.cmake -DSQLITE_ORM_OMITS_CODECVT="$SQLITE_ORM_OMITS_CODECVT" .. # build examples, and run tests (ie make & make test) script: From d1c071ee9a7e7c4480040b553420960b4118e591 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Wed, 3 Apr 2019 02:18:55 +0430 Subject: [PATCH 025/232] Add mac gcc test. (see #256) --- .travis.yml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8a50e0a01..95552bfbb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,7 +40,7 @@ matrix: - CC=clang - CXX=clang++ - SQLITE_ORM_OMITS_CODECVT=ON - - name: "osx" + - name: "osx clang" compiler: clang os: osx osx_image: xcode10.1 @@ -49,6 +49,18 @@ matrix: - CXX=clang - VCPKG_ALLOW_APPLE_CLANG=1 - SQLITE_ORM_OMITS_CODECVT=ON + - name: "osx gcc" + addons: + homeberaw: + packages: + - g++-7 + compiler: gcc + os: osx + osx_image: xcode10.1 + env: + - CC=gcc-7 + - CXX=g++-7 + - SQLITE_ORM_OMITS_CODECVT=OFF before_install: From a110983ee2f307b9013eaa1231aca7829b3c0458 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Wed, 3 Apr 2019 02:26:01 +0430 Subject: [PATCH 026/232] Add mac gcc test. (see #256) --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 95552bfbb..cd0450f08 100644 --- a/.travis.yml +++ b/.travis.yml @@ -53,13 +53,13 @@ matrix: addons: homeberaw: packages: - - g++-7 + - gcc6 compiler: gcc os: osx osx_image: xcode10.1 env: - - CC=gcc-7 - - CXX=g++-7 + - CC=gcc-6 + - CXX=g++-6 - SQLITE_ORM_OMITS_CODECVT=OFF From 742eb7942d7466f7f96cbe089bb401963e6d51d9 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Wed, 3 Apr 2019 02:29:18 +0430 Subject: [PATCH 027/232] Correct brew addons usage. (see #256) --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index cd0450f08..a5e7feb1a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,10 +15,11 @@ addons: packages: - cmake - git - homeberaw: + homebrew: packages: - cmake - git + update: true matrix: include: @@ -51,7 +52,7 @@ matrix: - SQLITE_ORM_OMITS_CODECVT=ON - name: "osx gcc" addons: - homeberaw: + homebrew: packages: - gcc6 compiler: gcc From 21ec3d1cabf907020461889bc5df0a8623de6e43 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Wed, 3 Apr 2019 02:52:43 +0430 Subject: [PATCH 028/232] Update gcc of mac to version 7. (see #256) --- .travis.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index a5e7feb1a..1b37ed8be 100644 --- a/.travis.yml +++ b/.travis.yml @@ -54,16 +54,15 @@ matrix: addons: homebrew: packages: - - gcc6 + - gcc7 compiler: gcc os: osx osx_image: xcode10.1 env: - - CC=gcc-6 - - CXX=g++-6 + - CC=gcc-7 + - CXX=g++-7 - SQLITE_ORM_OMITS_CODECVT=OFF - before_install: # coveralls test coverage: - if [[ "$CXX" == "g++" ]]; then pip install --user cpp-coveralls ; fi From 1e762a9e3deefc0741705b09d2079b75e68bd29e Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Wed, 3 Apr 2019 03:06:58 +0430 Subject: [PATCH 029/232] Update gcc of mac to version 7. (see #256) --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1b37ed8be..0805d7da3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -54,7 +54,7 @@ matrix: addons: homebrew: packages: - - gcc7 + - gcc@7 compiler: gcc os: osx osx_image: xcode10.1 From c11b7b5f87e1fc5847238d107aa01d0f487e4552 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Wed, 3 Apr 2019 03:18:19 +0430 Subject: [PATCH 030/232] Comment temporaly gtest installation. (see #256) --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0805d7da3..761ca3ab0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -76,7 +76,7 @@ before_script: - chmod +x bootstrap-vcpkg.sh - ./bootstrap-vcpkg.sh - chmod +x vcpkg - - ./vcpkg install gtest +# - ./vcpkg install gtest - cd ../.. - mkdir compile - cd compile From 41db456699b4398efc9a2997be46c4bafc5b0cb6 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Wed, 3 Apr 2019 14:59:52 +0430 Subject: [PATCH 031/232] Investigate compile error on gcc in mac os. (see #256) --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 761ca3ab0..c91721a66 100644 --- a/.travis.yml +++ b/.travis.yml @@ -54,13 +54,13 @@ matrix: addons: homebrew: packages: - - gcc@7 + - gcc6 compiler: gcc os: osx osx_image: xcode10.1 env: - - CC=gcc-7 - - CXX=g++-7 + - CC=gcc-6 + - CXX=g++-6 - SQLITE_ORM_OMITS_CODECVT=OFF before_install: @@ -84,7 +84,7 @@ before_script: # build examples, and run tests (ie make & make test) script: - - cmake --build . --config Debug + - cmake --build . --config Debug --trace --debug-output - ctest --verbose --output-on-failure -C Debug # generate and publish GCov coveralls results From c60d6887da90dc79c9906c3a327387cd48d0dc95 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Wed, 3 Apr 2019 15:07:55 +0430 Subject: [PATCH 032/232] Investigate compile error on gcc in mac os. (see #256) --- .travis.yml | 2 +- CMakeLists.txt | 1 + build.sh | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c91721a66..0a6f539bf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -84,7 +84,7 @@ before_script: # build examples, and run tests (ie make & make test) script: - - cmake --build . --config Debug --trace --debug-output + - cmake --build . --config Debug - ctest --verbose --output-on-failure -C Debug # generate and publish GCov coveralls results diff --git a/CMakeLists.txt b/CMakeLists.txt index 556ecf14d..b87954007 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,7 @@ cmake_minimum_required (VERSION 3.2) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_VERBOSE_MAKEFILE ON) # PACKAGE_VERSION is used by cpack scripts currently # Both sqlite_orm_VERSION and PACKAGE_VERSION should be the same for now diff --git a/build.sh b/build.sh index 48606914d..675bb5525 100755 --- a/build.sh +++ b/build.sh @@ -18,6 +18,7 @@ TRAVIS_JOB_NAME="clang default" if [ "$TRAVIS_JOB_NAME" = "clang default" ]; then cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../third_party/vcpkg/scripts/buildsystems/vcpkg.cmake -DSQLITE_ORM_OMITS_CODECVT=ON .. ; else\ cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../third_party/vcpkg/scripts/buildsystems/vcpkg.cmake .. ; fi +cmake --build . --config Debug #cd third_party From f6b61dfa9b90a316d4fcf76151e2f0f1bde4e90e Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Wed, 3 Apr 2019 15:33:48 +0430 Subject: [PATCH 033/232] Investigate compile error on gcc in mac os. (see #256) --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b87954007..6d7b1e946 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,6 @@ cmake_minimum_required (VERSION 3.2) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_VERBOSE_MAKEFILE ON) # PACKAGE_VERSION is used by cpack scripts currently # Both sqlite_orm_VERSION and PACKAGE_VERSION should be the same for now @@ -11,6 +10,8 @@ set(PACKAGE_VERSION ${sqlite_orm_VERSION}) project("sqlite_orm" VERSION ${PACKAGE_VERSION}) +set(CMAKE_VERBOSE_MAKEFILE ON) + message(STATUS "Configuring ${CMAKE_PROJECT_NAME} ${sqlite_orm_VERSION}") set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_CURRENT_SOURCE_DIR}/build/cmake") From 435cc11dcf2392bfcfd055191edec056ae4a40b9 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Wed, 3 Apr 2019 15:50:52 +0430 Subject: [PATCH 034/232] Investigate compile error on gcc in mac os. (see #256) --- include/sqlite_orm/sqlite_orm.h | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 06167e6b6..ccff598a3 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -5286,25 +5286,28 @@ namespace sqlite_orm { using getter_type = typename column_type::getter_type; using setter_type = typename column_type::setter_type; if(!res){ - static_if{}>([&res, &obj, &col, &c]{ - if(compare_any(col.member_pointer, c)){ - res = &(obj.*col.member_pointer); - } - })(); + static_if{}>([]{})(); +// static_if{}>([&res, &obj, &col, &c]{ +// if(compare_any(col.member_pointer, c)){ +// res = &(obj.*col.member_pointer); +// } +// })(); } if(!res){ - static_if{}>([&res, &obj, &col, &c]{ - if(compare_any(col.getter, c)){ - res = &((obj).*(col.getter))(); - } - })(); + static_if{}>([]{})(); +// static_if{}>([&res, &obj, &col, &c]{ +// if(compare_any(col.getter, c)){ +// res = &((obj).*(col.getter))(); +// } +// })(); } if(!res){ - static_if{}>([&res, &obj, &col, &c]{ - if(compare_any(col.setter, c)){ - res = &((obj).*(col.getter))(); - } - })(); + static_if{}>([]{})(); +// static_if{}>([&res, &obj, &col, &c]{ +// if(compare_any(col.setter, c)){ +// res = &((obj).*(col.getter))(); +// } +// })(); } }); return res; From 492cfdbe12907e79cc866b8470d0c26b5f90d63f Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Wed, 3 Apr 2019 17:17:12 +0430 Subject: [PATCH 035/232] Investigate compile error on gcc in mac os. (see #256) --- include/sqlite_orm/sqlite_orm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index ccff598a3..7b99995c4 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -5294,7 +5294,7 @@ namespace sqlite_orm { // })(); } if(!res){ - static_if{}>([]{})(); + static_if{}>([]{})(); // static_if{}>([&res, &obj, &col, &c]{ // if(compare_any(col.getter, c)){ // res = &((obj).*(col.getter))(); From a95e53c83aac3b511abb28d29522c118488e7cdf Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Wed, 3 Apr 2019 17:59:40 +0430 Subject: [PATCH 036/232] Investigate compile error on gcc in mac os. (see #256) --- include/sqlite_orm/sqlite_orm.h | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 7b99995c4..c6d75d7f2 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -5286,28 +5286,25 @@ namespace sqlite_orm { using getter_type = typename column_type::getter_type; using setter_type = typename column_type::setter_type; if(!res){ - static_if{}>([]{})(); -// static_if{}>([&res, &obj, &col, &c]{ -// if(compare_any(col.member_pointer, c)){ -// res = &(obj.*col.member_pointer); -// } -// })(); + static_if{}>([&res, &obj, &col, &c](int temp){ + if(compare_any(col.member_pointer, c)){ + res = &(obj.*col.member_pointer); + } + })(0); } if(!res){ - static_if{}>([]{})(); -// static_if{}>([&res, &obj, &col, &c]{ -// if(compare_any(col.getter, c)){ -// res = &((obj).*(col.getter))(); -// } -// })(); + static_if{}>([&res, &obj, &col, &c](int temp){ + if(compare_any(col.getter, c)){ + res = &((obj).*(col.getter))(); + } + })(0); } if(!res){ - static_if{}>([]{})(); -// static_if{}>([&res, &obj, &col, &c]{ -// if(compare_any(col.setter, c)){ -// res = &((obj).*(col.getter))(); -// } -// })(); + static_if{}>([&res, &obj, &col, &c](int temp){ + if(compare_any(col.setter, c)){ + res = &((obj).*(col.getter))(); + } + })(0); } }); return res; From e422eb2976f101419299ae6146473e15bacf135c Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Wed, 3 Apr 2019 18:32:28 +0430 Subject: [PATCH 037/232] Investigate compile error on gcc in mac os. (see #256) --- include/sqlite_orm/sqlite_orm.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index c6d75d7f2..dee6f73f8 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -5285,26 +5285,28 @@ namespace sqlite_orm { using member_pointer_t = typename column_type::member_pointer_t; using getter_type = typename column_type::getter_type; using setter_type = typename column_type::setter_type; + + // GCC has bug that reported in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64095 so static_if must have at lease one input if(!res){ - static_if{}>([&res, &obj, &col, &c](int temp){ + static_if{}>([&res, &obj, &col](const C& c){ if(compare_any(col.member_pointer, c)){ res = &(obj.*col.member_pointer); } - })(0); + })(c); } if(!res){ - static_if{}>([&res, &obj, &col, &c](int temp){ + static_if{}>([&res, &obj, &col, &c](const C& c){ if(compare_any(col.getter, c)){ res = &((obj).*(col.getter))(); } - })(0); + })(c); } if(!res){ - static_if{}>([&res, &obj, &col, &c](int temp){ + static_if{}>([&res, &obj, &col](const C& c){ if(compare_any(col.setter, c)){ res = &((obj).*(col.getter))(); } - })(0); + })(c); } }); return res; From 26de479601f3a2c5bd635f039d8bc7d999cbbfaa Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Wed, 3 Apr 2019 18:55:52 +0430 Subject: [PATCH 038/232] Investigate compile error on gcc in mac os. (see #256) --- build.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build.sh b/build.sh index 675bb5525..c1f77eb7b 100755 --- a/build.sh +++ b/build.sh @@ -21,6 +21,8 @@ if [ "$TRAVIS_JOB_NAME" = "clang default" ]; then cmake -DCMAKE_BUILD_TYPE=Debug cmake --build . --config Debug + + #cd third_party #git clone https://github.com/Microsoft/vcpkg.git vcpkg #cd vcpkg From ec886d31f2e75845594332fcee1e167c4fe02cf2 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Wed, 3 Apr 2019 19:07:57 +0430 Subject: [PATCH 039/232] Investigate compile error on gcc in mac os. (see #256) --- build.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/build.sh b/build.sh index c1f77eb7b..5e3cc79a0 100755 --- a/build.sh +++ b/build.sh @@ -20,9 +20,6 @@ if [ "$TRAVIS_JOB_NAME" = "clang default" ]; then cmake -DCMAKE_BUILD_TYPE=Debug cmake --build . --config Debug - - - #cd third_party #git clone https://github.com/Microsoft/vcpkg.git vcpkg #cd vcpkg From 71a40563bb11222159143303d7895798e541be0b Mon Sep 17 00:00:00 2001 From: soroshsabz Date: Wed, 3 Apr 2019 22:08:37 +0430 Subject: [PATCH 040/232] Create CONTRIBUTING.md --- CONTRIBUTING.md | 106 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..d9118e0f0 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,106 @@ +# How to Contribute # + +Thank you for your interest in contributing to the sqlite_orm project! + +## GitHub pull requests ## + +This is the preferred method of submitting changes. When you submit a pull request through github, +it activates the continuous integration (CI) build systems at Appveyor and Travis to build your changesxi +on a variety of Linux and Windows configurations and run all the test suites. Follow these requirements +for a successful pull request: + + 1. All significant changes require a [github issue](https://github.com/fnc12/sqlite_orm/issues). Trivial changes such as fixing a typo or a compiler warning do not. + + 1. All pull requests should contain a single commit per issue, or we will ask you to squash it. + 1. The pull request title must begin with the github issue identifier if it has an associated issue, for example: + + #9999 : an example pull request title + + 1. Commit messages must follow this pattern for code changes (deviations will not be merged): + + [summary of fix, one line if possible](fixes #issue number) + +Instructions: + + 1. Create a fork in your GitHub account of http://github.com/fnc12/sqlite_orm + 1. Clone the fork to your development system. + 1. Create a branch for your changes (best practice is following git flow pattern with issue number as branch name, e.g. feature/9999-some-feature or bugfix/9999-some-bug). + 1. Modify the source to include the improvement/bugfix, and: + + * Remember to provide *tests* for all submitted changes! + * Use test-driven development (TDD): add a test that will isolate the bug *before* applying the change that fixes it. + * Verify that you follow current code style on sqlite_orm. + * [*optional*] Verify that your change works on other platforms by adding a GitHub service hook to [Travis CI](http://docs.travis-ci.com/user/getting-started/#Step-one%3A-Sign-in) and [AppVeyor](http://www.appveyor.com/docs). You can use this technique to run the sqlite_orm CI jobs in your account to check your changes before they are made public. Every GitHub pull request into sqlite_orm will run the full CI build and test suite on your changes. + + 1. Squash your changes to a single commit. This maintains clean change history. + 1. Commit and push changes to your branch (please use issue name and description as commit title, e.g. "make it perfect. (fixes #9999)"). + 1. Use GitHub to create a pull request going from your branch to sqlite_orm:dev. Ensure that the github issue number is at the beginning of the title of your pull request. + 1. Wait for other contributors or committers to review your new addition, and for a CI build to complete. + 1. Wait for a owner or collaborators to commit your patch. + +## If you want to build the project locally ## + +See our detailed instructions on the [CMake README](/build/cmake/README.md). + +## If you want to review open issues... ## + + 1. Review the [GitHub Pull Request Backlog](https://github.com/fnc12/sqlite_orm/pulls). Code reviews are open to all. + +## If you discovered a defect... ## + + 1. Check to see if the issue is already in the [github issues](https://github.com/fnc12/sqlite_orm/issues). + 1. If not, create a issue describing the change you're proposing in the github issues page. + 1. Contribute your code changes using the GitHub pull request method: + +## Contributing via Patch ## + +To create a patch from changes in your local directory: + + git diff > ../sqlite_orm-NNNN.patch + +then wait for contributors or committers to review your changes, and then for a committer to apply your patch. This is not the preferred way to submit changes and incurs additional overhead for committers who must then create a pull request for you. + +## GitHub recipes for Pull Requests ## + +Sometimes commmitters may ask you to take actions in your pull requests. Here are some recipes that will help you accomplish those requests. These examples assume you are working on github issue 9999. You should also be familiar with the [upstream](https://help.github.com/articles/syncing-a-fork/) repository concept. + +### Squash your changes ### + +If you have not submitted a pull request yet, or if you have not yet rebased your existing pull request, you can squash all your commits down to a single commit. This makes life easier for the committers. If your pull request on GitHub has more than one commit, you should do this. + +1. Use the command ``git log`` to identify how many commits you made since you began. +2. Use the command ``git rebase -i HEAD~N`` where N is the number of commits. +3. Leave "pull" in the first line. +4. Change all other lines from "pull" to "fixup". +5. All your changes are now in a single commit. + +If you already have a pull request outstanding, you will need to do a "force push" to overwrite it since you changed your commit history: + + git push -u origin feature/9999-make-perfect --force + +A more detailed walkthrough of a squash can be found at [Git Ready](http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html). + +### Rebase your pull request ### + +If your pull request has a conflict with master, it needs to be rebased: + + git checkout feature/9999-make-perfect + git rebase upstream master + (resolve any conflicts, make sure it builds) + git push -u origin feature/9999-make-perfect --force + +### Fix a bad merge ### + +If your pull request contains commits that are not yours, then you should use the following technique to fix the bad merge in your branch: + + git checkout master + git pull upstream master + git checkout -b feature/9999-make-perfect-take-2 + git cherry-pick ... + (pick only your commits from your original pull request in ascending chronological order) + squash your changes to a single commit if there is more than one (see above) + git push -u origin feature/9999-make-perfect-take-2:feature/9999-make-perfect + +This procedure will apply only your commits in order to the current master, then you will squash them to a single commit, and then you force push your local feature/9999-make-perfect-take-2 into remote feature/9999-make-perfect which represents your pull request, replacing all the commits with the new one. + + From 4da12a749d6ae98faa1b7ebe84df26ee6dd3970e Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Wed, 3 Apr 2019 22:16:56 +0430 Subject: [PATCH 041/232] Investigate compile error on gcc in mac os. (see #256) --- include/sqlite_orm/sqlite_orm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index dee6f73f8..c22733525 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -5295,7 +5295,7 @@ namespace sqlite_orm { })(c); } if(!res){ - static_if{}>([&res, &obj, &col, &c](const C& c){ + static_if{}>([&res, &obj, &col](const C& c){ if(compare_any(col.getter, c)){ res = &((obj).*(col.getter))(); } From 740a4de16604815b1067c7c347703abb10d78960 Mon Sep 17 00:00:00 2001 From: soroshsabz Date: Thu, 4 Apr 2019 01:51:45 +0430 Subject: [PATCH 042/232] Update README.md Add vcpkg in installation --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 871ec4994..44a022a80 100644 --- a/README.md +++ b/README.md @@ -722,7 +722,9 @@ For more details please check the project [wiki](https://github.com/fnc12/sqlite # Installation -Just put `include/sqlite_orm/sqlite_orm.h` into you folder with headers. Also it is recommended to keep project libraries' sources in separate folders cause there is no normal dependency manager for C++ yet. +Use popular package manager like [vcpkg](https://github.com/Microsoft/vcpkg) and just install it with `vcpkg install sqlite_orm` command. + +Or just put `include/sqlite_orm/sqlite_orm.h` into you folder with headers. Also it is recommended to keep project libraries' sources in separate folders cause there is no dominant normal dependency manager for C++ yet. # Requirements From 22047ceac93377200d4405c27a59244291114795 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Thu, 4 Apr 2019 10:19:20 +0430 Subject: [PATCH 043/232] Correct build.sh. (see #256) --- build.sh | 45 +++++++++++++++------------------------------ 1 file changed, 15 insertions(+), 30 deletions(-) diff --git a/build.sh b/build.sh index 5e3cc79a0..0527b4d29 100755 --- a/build.sh +++ b/build.sh @@ -1,42 +1,27 @@ #!/bin/sh -# Copyright (c) 2012-2019 Sébastien Rombauts (sebastien.rombauts@gmail.com) -# -# Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt -# or copy at http://opensource.org/licenses/MIT) # exit on firts error set -e -echo "g++ version: " -g++ --version - +echo "Prepare third party libraries" +cd third_party +git clone https://github.com/Microsoft/vcpkg.git vcpkg +cd vcpkg +chmod +x bootstrap-vcpkg.sh +./bootstrap-vcpkg.sh +chmod +x vcpkg +./vcpkg install gtest +cd ../.. + +echo "Prepare for compile" mkdir -p compile cd compile -TRAVIS_JOB_NAME="clang default" - -if [ "$TRAVIS_JOB_NAME" = "clang default" ]; then cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../third_party/vcpkg/scripts/buildsystems/vcpkg.cmake -DSQLITE_ORM_OMITS_CODECVT=ON .. ; else\ - cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../third_party/vcpkg/scripts/buildsystems/vcpkg.cmake .. ; fi +cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../third_party/vcpkg/scripts/buildsystems/vcpkg.cmake .. +echo "Compiling..." cmake --build . --config Debug -#cd third_party -#git clone https://github.com/Microsoft/vcpkg.git vcpkg -#cd vcpkg -#chmod +x bootstrap-vcpkg.sh -#./bootstrap-vcpkg.sh -#chmod +x vcpkg -#./vcpkg install gtest -#cd ../.. +echo "Run testing..." +ctest -C Debug --output-on-failure -V -#mkdir -p build -#cd build -# -## Generate a Makefile for GCC (or Clang, depanding on CC/CXX envvar) -#cmake -DCMAKE_BUILD_TYPE=Debug -DSQLITECPP_USE_GCOV=OFF -DSQLITECPP_BUILD_EXAMPLES=ON -DSQLITECPP_BUILD_TESTS=ON .. -# -## Build (ie 'make') -#cmake --build . -# -## Build and run unit-tests (ie 'make test') -#ctest --output-on-failure \ No newline at end of file From 232096758af61601668833ce50c4a7be1e9899a0 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Thu, 4 Apr 2019 10:20:59 +0430 Subject: [PATCH 044/232] Remove unnessery installing dependency. (see #256) --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0a6f539bf..933734b23 100644 --- a/.travis.yml +++ b/.travis.yml @@ -76,7 +76,7 @@ before_script: - chmod +x bootstrap-vcpkg.sh - ./bootstrap-vcpkg.sh - chmod +x vcpkg -# - ./vcpkg install gtest + - ./vcpkg install gtest - cd ../.. - mkdir compile - cd compile @@ -89,4 +89,4 @@ script: # generate and publish GCov coveralls results after_success: - - if [[ "$CXX" == "g++" ]]; then coveralls --root .. -e examples -e googletest -e sqlite3 -e tests -E ".*feature_tests.*" -E ".*CompilerId.*" --gcov-options '\-lp' ; fi \ No newline at end of file + - if [[ "$CXX" == "g++" ]]; then coveralls --root .. -e examples -e googletest -e sqlite3 -e tests -E ".*feature_tests.*" -E ".*CompilerId.*" --gcov-options '\-lp' ; fi From 5447420d919a20c5e27bb5f1af09b57d380aba40 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Thu, 4 Apr 2019 10:23:08 +0430 Subject: [PATCH 045/232] Remove copyrights. (see #256) --- .travis.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 933734b23..dafa5ab35 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,8 @@ -# ITNOA -# Copyright (c) 2012-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com) - -# request for Ubuntu 16.04 Trusty VM +# Request for Ubuntu 16.04 Trusty VM sudo: true dist: xenial + +# This is comment to easer chagne CXX and CC flags #language: cpp cache: From 23849aa3fc8c007a0247e2771ec2501fd95f82f5 Mon Sep 17 00:00:00 2001 From: Matt Kline Date: Tue, 9 Apr 2019 15:39:01 -0700 Subject: [PATCH 046/232] Use unique_ptr in examples Previous commits somehow missed foreign_key and comments in select. --- examples/foreign_key.cpp | 20 ++++++++++---------- examples/select.cpp | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/examples/foreign_key.cpp b/examples/foreign_key.cpp index b90d9ae58..a5421a153 100644 --- a/examples/foreign_key.cpp +++ b/examples/foreign_key.cpp @@ -20,7 +20,7 @@ struct Artist { struct Track { int trackId; std::string trackName; - std::shared_ptr trackArtist; // must map to &Artist::artistId + std::unique_ptr trackArtist; // must map to &Artist::artistId }; int main(int argc, char **argv) { @@ -48,14 +48,14 @@ int main(int argc, char **argv) { storage.replace(Artist{ 1, "Dean Martin" }); storage.replace(Artist{ 2, "Frank Sinatra" }); - storage.replace(Track{ 11, "That's Amore", std::make_shared(1) }); - storage.replace(Track{ 12, "Christmas Blues", std::make_shared(1) }); - storage.replace(Track{ 13, "My Way", std::make_shared(2) }); + storage.replace(Track{ 11, "That's Amore", std::make_unique(1) }); + storage.replace(Track{ 12, "Christmas Blues", std::make_unique(1) }); + storage.replace(Track{ 13, "My Way", std::make_unique(2) }); try{ // This fails because value inserted into the trackartist column (3) // does not correspond to row in the artist table. - storage.replace(Track{ 14, "Mr. Bojangles", std::make_shared(3) }); + storage.replace(Track{ 14, "Mr. Bojangles", std::make_unique(3) }); assert(0); }catch(std::system_error e) { cout << e.what() << endl; @@ -84,7 +84,7 @@ int main(int argc, char **argv) { // Now that "Sammy Davis Jr." (artistid = 3) has been added to the database, // it is possible to INSERT new tracks using this artist without violating // the foreign key constraint: - storage.replace(Track{ 15, "Boogie Woogie", std::make_shared(3) }); + storage.replace(Track{ 15, "Boogie Woogie", std::make_unique(3) }); try{ // Attempting to delete the artist record for "Frank Sinatra" fails, since @@ -136,9 +136,9 @@ int main(int argc, char **argv) { storage.replace(Artist{ 1, "Dean Martin" }); storage.replace(Artist{ 2, "Frank Sinatra" }); - storage.replace(Track{ 11, "That's Amore", std::make_shared(1) }); - storage.replace(Track{ 12, "Christmas Blues", std::make_shared(1) }); - storage.replace(Track{ 13, "My Way", std::make_shared(2) }); + storage.replace(Track{ 11, "That's Amore", std::make_unique(1) }); + storage.replace(Track{ 12, "Christmas Blues", std::make_unique(1) }); + storage.replace(Track{ 13, "My Way", std::make_unique(2) }); // Update the artistid column of the artist record for "Dean Martin". // Normally, this would raise a constraint, as it would orphan the two @@ -187,7 +187,7 @@ int main(int argc, char **argv) { storage.replace(Artist{ 3, "Sammy Davis Jr." }); - storage.replace(Track{ 14, "Mr. Bojangles", std::make_shared(3) }); + storage.replace(Track{ 14, "Mr. Bojangles", std::make_unique(3) }); // Deleting the row from the parent table causes the child key // value of the dependent row to be set to integer value 0. However, this diff --git a/examples/select.cpp b/examples/select.cpp index 20bb342eb..917c69391 100644 --- a/examples/select.cpp +++ b/examples/select.cpp @@ -82,7 +82,7 @@ int main(int argc, char **argv) { auto allEmployeesTuples = storage.select(asterisk()); cout << "allEmployeesTuples count = " << allEmployeesTuples.size() << endl; - for(auto &row : allEmployeesTuples) { // row is std::tuple, std::shared_ptr> + for(auto &row : allEmployeesTuples) { // row is std::tuple, std::unique_ptr> cout << std::get<0>(row) << '\t' << std::get<1>(row) << '\t' << std::get<2>(row) << '\t'; if(auto &value = std::get<3>(row)){ cout << *value; From 01aa86e986a68cedfd082a44967c93579ebde31b Mon Sep 17 00:00:00 2001 From: Yevgeniy Zakharov Date: Thu, 11 Apr 2019 12:24:29 +0300 Subject: [PATCH 047/232] Update TODO.md --- TODO.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/TODO.md b/TODO.md index c2b81c7d7..cc57a0d47 100644 --- a/TODO.md +++ b/TODO.md @@ -12,13 +12,12 @@ * explicit FROM for subqueries in FROM argument * backup API https://www.sqlite.org/backup.html * busy handler https://sqlite.org/c3ref/busy_handler.html -* CAST https://sqlite.org/lang_expr.html#castexpr * CREATE VIEW and other view operations https://sqlite.org/lang_createview.html * triggers * query static check for correct order (e.g. `GROUP BY` after `WHERE`) -* column alias * `FULL OUTER JOIN` * `WINDOW` * `UPSERT` https://www.sqlite.org/lang_UPSERT.html +* `CHECK` constraint Please feel free to add any feature that isn't listed here and not implemented yet. From 27560d85687bce730b64a8fb689daf30f467c0b7 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Fri, 12 Apr 2019 20:06:06 +0430 Subject: [PATCH 048/232] Add -AllowAppleClang option to vcpkg. (see #256) --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index dafa5ab35..18bc50682 100644 --- a/.travis.yml +++ b/.travis.yml @@ -73,7 +73,8 @@ before_script: - git clone https://github.com/Microsoft/vcpkg.git vcpkg - cd vcpkg - chmod +x bootstrap-vcpkg.sh - - ./bootstrap-vcpkg.sh + - if [[ "$CXX" == "clang" && "$TRAVIS_OS_NAME" == "mac" ]]; then ./bootstrap-vcpkg.sh -allowAppleClang ; else\ + ./bootstrap-vcpkg.sh - chmod +x vcpkg - ./vcpkg install gtest - cd ../.. From 02df99e0c6096cd670362431307cff401fa01e2b Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Fri, 12 Apr 2019 20:08:20 +0430 Subject: [PATCH 049/232] Add -AllowAppleClang option to vcpkg. (see #256) --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 18bc50682..72bf2b529 100644 --- a/.travis.yml +++ b/.travis.yml @@ -73,8 +73,7 @@ before_script: - git clone https://github.com/Microsoft/vcpkg.git vcpkg - cd vcpkg - chmod +x bootstrap-vcpkg.sh - - if [[ "$CXX" == "clang" && "$TRAVIS_OS_NAME" == "mac" ]]; then ./bootstrap-vcpkg.sh -allowAppleClang ; else\ - ./bootstrap-vcpkg.sh + - if [[ "$CXX" == "clang" && "$TRAVIS_OS_NAME" == "mac" ]]; then ./bootstrap-vcpkg.sh -allowAppleClang ; else ./bootstrap-vcpkg.sh ; fi - chmod +x vcpkg - ./vcpkg install gtest - cd ../.. From 5c5a26b39bd11a24966d0ae836a6a363bb212d47 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Fri, 12 Apr 2019 20:15:33 +0430 Subject: [PATCH 050/232] Add -AllowAppleClang option to vcpkg. (see #256) --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 72bf2b529..a9d172a85 100644 --- a/.travis.yml +++ b/.travis.yml @@ -73,7 +73,7 @@ before_script: - git clone https://github.com/Microsoft/vcpkg.git vcpkg - cd vcpkg - chmod +x bootstrap-vcpkg.sh - - if [[ "$CXX" == "clang" && "$TRAVIS_OS_NAME" == "mac" ]]; then ./bootstrap-vcpkg.sh -allowAppleClang ; else ./bootstrap-vcpkg.sh ; fi + - if [[ "$CXX" == "clang" && "$TRAVIS_OS_NAME" == "mac" ]]; then ./bootstrap-vcpkg.sh --allowAppleClang ; else ./bootstrap-vcpkg.sh ; fi - chmod +x vcpkg - ./vcpkg install gtest - cd ../.. From 6e9db7dee65f89004b06f2fd097953b4aa55118f Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Fri, 12 Apr 2019 20:25:05 +0430 Subject: [PATCH 051/232] Add -AllowAppleClang option to vcpkg. (see #256) --- .travis.yml | 2 +- build.sh | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index a9d172a85..dce085ac3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -73,7 +73,7 @@ before_script: - git clone https://github.com/Microsoft/vcpkg.git vcpkg - cd vcpkg - chmod +x bootstrap-vcpkg.sh - - if [[ "$CXX" == "clang" && "$TRAVIS_OS_NAME" == "mac" ]]; then ./bootstrap-vcpkg.sh --allowAppleClang ; else ./bootstrap-vcpkg.sh ; fi + - if [[ "$CXX" == "clang" && "$TRAVIS_OS_NAME" == "osx" ]]; then ./bootstrap-vcpkg.sh --allowAppleClang ; else ./bootstrap-vcpkg.sh ; fi - chmod +x vcpkg - ./vcpkg install gtest - cd ../.. diff --git a/build.sh b/build.sh index 0527b4d29..8acae85b0 100755 --- a/build.sh +++ b/build.sh @@ -8,7 +8,9 @@ cd third_party git clone https://github.com/Microsoft/vcpkg.git vcpkg cd vcpkg chmod +x bootstrap-vcpkg.sh -./bootstrap-vcpkg.sh + +if [[ "$CXX" == "clang" && "$TRAVIS_OS_NAME" == "mac" ]]; then ./bootstrap-vcpkg.sh --allowAppleClang ; else ./bootstrap-vcpkg.sh ; fi + chmod +x vcpkg ./vcpkg install gtest cd ../.. From f7879aa7f38eccedb8772fe2c3517ce716080335 Mon Sep 17 00:00:00 2001 From: soroshsabz Date: Fri, 12 Apr 2019 20:48:29 +0430 Subject: [PATCH 052/232] Update README.md Add cmake instructions --- README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/README.md b/README.md index bdbefa937..70704b175 100644 --- a/README.md +++ b/README.md @@ -732,6 +732,26 @@ For more details please check the project [wiki](https://github.com/fnc12/sqlite Use popular package manager like [vcpkg](https://github.com/Microsoft/vcpkg) and just install it with `vcpkg install sqlite_orm` command. +Or you can use below instructions + +```bash +git clone https://github.com/fnc12/sqlite_orm.git sqlite_orm +cd sqlite_orm +mkdir compile +cd compile +cmake .. +cmake --build . +sudo make install +``` + +then you can just include `sqlite_orm.h` that install in system-wide header files location or if you use cmake build system you can just add below commands in CMakeLists.txt + +```cmake +find_package(sqlite_orm CONFIG REQUIRED) +target_link_libraries(main PRIVATE sqlite_orm::sqlite_orm) +target_include_directories(main PRIVATE ${SQLITE_ORM_INCLUDE_DIR}) +``` + Or just put `include/sqlite_orm/sqlite_orm.h` into you folder with headers. Also it is recommended to keep project libraries' sources in separate folders cause there is no dominant normal dependency manager for C++ yet. # Requirements From 6050e1776e1393dc15f4a0ff7210a00aff45bfe2 Mon Sep 17 00:00:00 2001 From: soroshsabz Date: Sat, 13 Apr 2019 00:36:29 +0430 Subject: [PATCH 053/232] Update README.md Improve grammer --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 70704b175..bf55e1985 100644 --- a/README.md +++ b/README.md @@ -744,7 +744,7 @@ cmake --build . sudo make install ``` -then you can just include `sqlite_orm.h` that install in system-wide header files location or if you use cmake build system you can just add below commands in CMakeLists.txt +then you can just include `sqlite_orm.h` that is installed in system-wide header files location or in case you use cmake build system you can just add below commands in CMakeLists.txt ```cmake find_package(sqlite_orm CONFIG REQUIRED) From 912551712a42392aec2d29f884ee3fe735609b5f Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Sat, 13 Apr 2019 00:39:07 +0430 Subject: [PATCH 054/232] Add -AllowAppleClang option to vcpkg. (see #256) --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index dce085ac3..923cc7b6f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -43,7 +43,7 @@ matrix: - name: "osx clang" compiler: clang os: osx - osx_image: xcode10.1 + osx_image: xcode10.2 env: - CC=clang - CXX=clang From bc7182a3447856d718109c0b7a60ae945c9a9c12 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Sat, 13 Apr 2019 00:53:37 +0430 Subject: [PATCH 055/232] Add -AllowAppleClang option to vcpkg. (see #256) --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 923cc7b6f..0b6333dff 100644 --- a/.travis.yml +++ b/.travis.yml @@ -68,6 +68,7 @@ before_install: # scripts to run before build before_script: + - if [[ "$CXX" == "clang" ]]; then clang --version ; fi - chmod +x build.sh - cd third_party - git clone https://github.com/Microsoft/vcpkg.git vcpkg From 97094bfbcafe734df5c8ff77e70a1eb3fc49ce4d Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Sat, 13 Apr 2019 01:17:34 +0430 Subject: [PATCH 056/232] Add -AllowAppleClang option to vcpkg. (see #256) --- .travis.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.travis.yml b/.travis.yml index 0b6333dff..19040ca8a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -44,7 +44,16 @@ matrix: compiler: clang os: osx osx_image: xcode10.2 + before_install: + - brew install --with-toolchain llvm + - brew info llvm + - export PATH="/usr/local/opt/llvm/bin:$PATH" + - echo 'export PATH="/usr/local/opt/llvm/bin:$PATH"' >> ~/.bash_profile + - xcode-select --install env: + - CPATH=/usr/local/opt/llvm/include + - LIBRARY_PATH=/usr/local/opt/llvm/lib + - LD_LIBRARY_PATH=/usr/local/opt/llvm/lib - CC=clang - CXX=clang - VCPKG_ALLOW_APPLE_CLANG=1 From 9833ab417ae4c2461d280d6a3a279b66b212b083 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Sat, 13 Apr 2019 01:19:37 +0430 Subject: [PATCH 057/232] Add -AllowAppleClang option to vcpkg. (see #256) --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 19040ca8a..4d30ee87a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -51,9 +51,9 @@ matrix: - echo 'export PATH="/usr/local/opt/llvm/bin:$PATH"' >> ~/.bash_profile - xcode-select --install env: - - CPATH=/usr/local/opt/llvm/include - - LIBRARY_PATH=/usr/local/opt/llvm/lib - - LD_LIBRARY_PATH=/usr/local/opt/llvm/lib + - CPATH="/usr/local/opt/llvm/include" + - LIBRARY_PATH="/usr/local/opt/llvm/lib" + - LD_LIBRARY_PATH="/usr/local/opt/llvm/lib" - CC=clang - CXX=clang - VCPKG_ALLOW_APPLE_CLANG=1 From d7dc8d5ab2eda4a20e2f5cde264fd4ee1a3ab176 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Sat, 13 Apr 2019 01:21:00 +0430 Subject: [PATCH 058/232] Add -AllowAppleClang option to vcpkg. (see #256) --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4d30ee87a..8303b2997 100644 --- a/.travis.yml +++ b/.travis.yml @@ -47,8 +47,8 @@ matrix: before_install: - brew install --with-toolchain llvm - brew info llvm - - export PATH="/usr/local/opt/llvm/bin:$PATH" - - echo 'export PATH="/usr/local/opt/llvm/bin:$PATH"' >> ~/.bash_profile +# - export PATH="/usr/local/opt/llvm/bin:$PATH" +# - echo 'export PATH="/usr/local/opt/llvm/bin:$PATH"' >> ~/.bash_profile - xcode-select --install env: - CPATH="/usr/local/opt/llvm/include" From ca8970da4db2308bef993935bc7309c98f7c2a24 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Sat, 13 Apr 2019 01:25:03 +0430 Subject: [PATCH 059/232] Add -AllowAppleClang option to vcpkg. (see #256) --- .travis.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8303b2997..8dfc8368b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,15 +45,15 @@ matrix: os: osx osx_image: xcode10.2 before_install: - - brew install --with-toolchain llvm - - brew info llvm +# - brew install --with-toolchain llvm + - brew info llvm # - export PATH="/usr/local/opt/llvm/bin:$PATH" # - echo 'export PATH="/usr/local/opt/llvm/bin:$PATH"' >> ~/.bash_profile - xcode-select --install env: - - CPATH="/usr/local/opt/llvm/include" - - LIBRARY_PATH="/usr/local/opt/llvm/lib" - - LD_LIBRARY_PATH="/usr/local/opt/llvm/lib" +# - CPATH="/usr/local/opt/llvm/include" +# - LIBRARY_PATH="/usr/local/opt/llvm/lib" +# - LD_LIBRARY_PATH="/usr/local/opt/llvm/lib" - CC=clang - CXX=clang - VCPKG_ALLOW_APPLE_CLANG=1 From d9e63c97b012766543cf119fe6d2d5e9a7049527 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Sat, 13 Apr 2019 01:32:05 +0430 Subject: [PATCH 060/232] Add -AllowAppleClang option to vcpkg. (see #256) --- .travis.yml | 13 ++++--------- prepare-osx-with-clang.sh | 11 +++++++++++ 2 files changed, 15 insertions(+), 9 deletions(-) create mode 100755 prepare-osx-with-clang.sh diff --git a/.travis.yml b/.travis.yml index 8dfc8368b..cfbbe4c65 100644 --- a/.travis.yml +++ b/.travis.yml @@ -44,16 +44,10 @@ matrix: compiler: clang os: osx osx_image: xcode10.2 - before_install: -# - brew install --with-toolchain llvm - - brew info llvm -# - export PATH="/usr/local/opt/llvm/bin:$PATH" -# - echo 'export PATH="/usr/local/opt/llvm/bin:$PATH"' >> ~/.bash_profile - - xcode-select --install env: -# - CPATH="/usr/local/opt/llvm/include" -# - LIBRARY_PATH="/usr/local/opt/llvm/lib" -# - LD_LIBRARY_PATH="/usr/local/opt/llvm/lib" + - CPATH="/usr/local/opt/llvm/include" + - LIBRARY_PATH="/usr/local/opt/llvm/lib" + - LD_LIBRARY_PATH="/usr/local/opt/llvm/lib" - CC=clang - CXX=clang - VCPKG_ALLOW_APPLE_CLANG=1 @@ -78,6 +72,7 @@ before_install: # scripts to run before build before_script: - if [[ "$CXX" == "clang" ]]; then clang --version ; fi + - if [[ "$CXX" == "clang" && "$TRAVIS_OS_NAME" == "osx" ]]; then chmod +x prepare-osx-with-clang.sh ; ./prepare-osx-with-clang.sh ; fi - chmod +x build.sh - cd third_party - git clone https://github.com/Microsoft/vcpkg.git vcpkg diff --git a/prepare-osx-with-clang.sh b/prepare-osx-with-clang.sh new file mode 100755 index 000000000..2d81b1461 --- /dev/null +++ b/prepare-osx-with-clang.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +# exit on firts error +set -e + +brew install --with-toolchain llvm +brew info llvm +export PATH="/usr/local/opt/llvm/bin:$PATH" +echo 'export PATH="/usr/local/opt/llvm/bin:$PATH"' >> ~/.bash_profile +xcode-select --install + From 144368d3624f8f2c244dc4dae8556065c13042b7 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Sat, 13 Apr 2019 01:33:20 +0430 Subject: [PATCH 061/232] Add -AllowAppleClang option to vcpkg. (see #256) --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index cfbbe4c65..a5d49e3c8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,9 +45,9 @@ matrix: os: osx osx_image: xcode10.2 env: - - CPATH="/usr/local/opt/llvm/include" - - LIBRARY_PATH="/usr/local/opt/llvm/lib" - - LD_LIBRARY_PATH="/usr/local/opt/llvm/lib" +# - CPATH="/usr/local/opt/llvm/include" +# - LIBRARY_PATH="/usr/local/opt/llvm/lib" +# - LD_LIBRARY_PATH="/usr/local/opt/llvm/lib" - CC=clang - CXX=clang - VCPKG_ALLOW_APPLE_CLANG=1 From 4ccb9c22f80238a218e5eea22476d4379f475cb6 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Sat, 13 Apr 2019 01:34:38 +0430 Subject: [PATCH 062/232] Add -AllowAppleClang option to vcpkg. (see #256) --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index a5d49e3c8..e2b1ad5ac 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,9 +45,9 @@ matrix: os: osx osx_image: xcode10.2 env: -# - CPATH="/usr/local/opt/llvm/include" -# - LIBRARY_PATH="/usr/local/opt/llvm/lib" -# - LD_LIBRARY_PATH="/usr/local/opt/llvm/lib" + - CPATH=/usr/local/opt/llvm/include + - LIBRARY_PATH=/usr/local/opt/llvm/lib + - LD_LIBRARY_PATH=/usr/local/opt/llvm/lib - CC=clang - CXX=clang - VCPKG_ALLOW_APPLE_CLANG=1 From b1887bed2d551f351665d41dcbc7a5c83d657426 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Sat, 13 Apr 2019 01:40:11 +0430 Subject: [PATCH 063/232] Add -AllowAppleClang option to vcpkg. (see #256) --- prepare-osx-with-clang.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prepare-osx-with-clang.sh b/prepare-osx-with-clang.sh index 2d81b1461..77e2e2662 100755 --- a/prepare-osx-with-clang.sh +++ b/prepare-osx-with-clang.sh @@ -3,7 +3,7 @@ # exit on firts error set -e -brew install --with-toolchain llvm +brew install llvm brew info llvm export PATH="/usr/local/opt/llvm/bin:$PATH" echo 'export PATH="/usr/local/opt/llvm/bin:$PATH"' >> ~/.bash_profile From 547f1e6285d20bb1453933d68dfad6490b75cc56 Mon Sep 17 00:00:00 2001 From: soroshsabz Date: Sat, 13 Apr 2019 01:44:45 +0430 Subject: [PATCH 064/232] Update CONTRIBUTING.md Resolve some problem in review --- CONTRIBUTING.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d9118e0f0..f2797931e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,8 +5,8 @@ Thank you for your interest in contributing to the sqlite_orm project! ## GitHub pull requests ## This is the preferred method of submitting changes. When you submit a pull request through github, -it activates the continuous integration (CI) build systems at Appveyor and Travis to build your changesxi -on a variety of Linux and Windows configurations and run all the test suites. Follow these requirements +it activates the continuous integration (CI) build systems at Appveyor and Travis to build your changes +on a variety of Linux, Windows and MacOS configurations and run all the test suites. Follow these requirements for a successful pull request: 1. All significant changes require a [github issue](https://github.com/fnc12/sqlite_orm/issues). Trivial changes such as fixing a typo or a compiler warning do not. @@ -82,10 +82,10 @@ A more detailed walkthrough of a squash can be found at [Git Ready](http://gitre ### Rebase your pull request ### -If your pull request has a conflict with master, it needs to be rebased: +If your pull request has a conflict with dev, it needs to be rebased: git checkout feature/9999-make-perfect - git rebase upstream master + git rebase upstream dev (resolve any conflicts, make sure it builds) git push -u origin feature/9999-make-perfect --force @@ -93,14 +93,14 @@ If your pull request has a conflict with master, it needs to be rebased: If your pull request contains commits that are not yours, then you should use the following technique to fix the bad merge in your branch: - git checkout master - git pull upstream master + git checkout dev + git pull upstream dev git checkout -b feature/9999-make-perfect-take-2 git cherry-pick ... (pick only your commits from your original pull request in ascending chronological order) squash your changes to a single commit if there is more than one (see above) git push -u origin feature/9999-make-perfect-take-2:feature/9999-make-perfect -This procedure will apply only your commits in order to the current master, then you will squash them to a single commit, and then you force push your local feature/9999-make-perfect-take-2 into remote feature/9999-make-perfect which represents your pull request, replacing all the commits with the new one. +This procedure will apply only your commits in order to the current dev, then you will squash them to a single commit, and then you force push your local feature/9999-make-perfect-take-2 into remote feature/9999-make-perfect which represents your pull request, replacing all the commits with the new one. From 6ee508feafc9d610f90e25f3ccf50eb80cd21f89 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Sat, 13 Apr 2019 01:59:32 +0430 Subject: [PATCH 065/232] Add -AllowAppleClang option to vcpkg. (see #256) --- .travis.yml | 2 ++ prepare-osx-with-clang.sh | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index e2b1ad5ac..8239b3995 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,6 +45,8 @@ matrix: os: osx osx_image: xcode10.2 env: + - CPPFLAGS="-I/usr/local/opt/llvm/include" + - LDFLAGS="-L/usr/local/opt/llvm/lib -Wl,-rpath,/usr/local/opt/llvm/lib" - CPATH=/usr/local/opt/llvm/include - LIBRARY_PATH=/usr/local/opt/llvm/lib - LD_LIBRARY_PATH=/usr/local/opt/llvm/lib diff --git a/prepare-osx-with-clang.sh b/prepare-osx-with-clang.sh index 77e2e2662..267cc3253 100755 --- a/prepare-osx-with-clang.sh +++ b/prepare-osx-with-clang.sh @@ -7,5 +7,3 @@ brew install llvm brew info llvm export PATH="/usr/local/opt/llvm/bin:$PATH" echo 'export PATH="/usr/local/opt/llvm/bin:$PATH"' >> ~/.bash_profile -xcode-select --install - From e82a1fbcdd1ca871e7e154f8d8a588faf4164ba5 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Sat, 13 Apr 2019 02:10:15 +0430 Subject: [PATCH 066/232] Add -AllowAppleClang option to vcpkg. (see #256) --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8239b3995..5afcabd74 100644 --- a/.travis.yml +++ b/.travis.yml @@ -50,8 +50,8 @@ matrix: - CPATH=/usr/local/opt/llvm/include - LIBRARY_PATH=/usr/local/opt/llvm/lib - LD_LIBRARY_PATH=/usr/local/opt/llvm/lib - - CC=clang - - CXX=clang + - CC=/usr/local/opt/llvm/bin/clang + - CXX=/usr/local/opt/llvm/bin/clang++ - VCPKG_ALLOW_APPLE_CLANG=1 - SQLITE_ORM_OMITS_CODECVT=ON - name: "osx gcc" From ac0597d877c7ffa205af05e0d585ededcd507d28 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Sat, 13 Apr 2019 02:39:00 +0430 Subject: [PATCH 067/232] Add -AllowAppleClang option to vcpkg. (see #256) --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 5afcabd74..e5648218f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -42,6 +42,10 @@ matrix: - SQLITE_ORM_OMITS_CODECVT=ON - name: "osx clang" compiler: clang + addons: + homebrew: + packages: + - clang os: osx osx_image: xcode10.2 env: From d5b9bd2dafb03bdbc8c25d96d9de8cd2bc3405e1 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Sat, 13 Apr 2019 02:47:29 +0430 Subject: [PATCH 068/232] Add -AllowAppleClang option to vcpkg. (see #256) --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index e5648218f..c397e9b3d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -42,10 +42,10 @@ matrix: - SQLITE_ORM_OMITS_CODECVT=ON - name: "osx clang" compiler: clang - addons: - homebrew: - packages: - - clang +# addons: +# homebrew: +# packages: +# - clang os: osx osx_image: xcode10.2 env: From f519e3552697ddcc0e0e42f1a41ca83a75cc7fad Mon Sep 17 00:00:00 2001 From: fnc12 Date: Fri, 19 Apr 2019 16:47:30 +0300 Subject: [PATCH 069/232] minor improvements --- dev/column.h | 25 ++- dev/conditions.h | 53 +++--- dev/constraints.h | 32 ++-- dev/index.h | 5 +- dev/select_constraints.h | 29 +-- dev/storage_impl.h | 161 ++++++++-------- dev/table.h | 21 +- include/sqlite_orm/sqlite_orm.h | 326 ++++++++++++++++++-------------- 8 files changed, 364 insertions(+), 288 deletions(-) diff --git a/dev/column.h b/dev/column.h index 6e1fcf1b4..6921a209e 100644 --- a/dev/column.h +++ b/dev/column.h @@ -14,6 +14,14 @@ namespace sqlite_orm { namespace internal { + struct column_base { + + /** + * Column name. Specified during construction in `make_column`. + */ + const std::string name; + }; + /** * This class stores single column info. column_t is a pair of [column_name:member_pointer] mapped to a storage * O is a mapped class, e.g. User @@ -21,7 +29,7 @@ namespace sqlite_orm { * Op... is a constraints pack, e.g. primary_key_t, autoincrement_t etc */ template - struct column_t { + struct column_t : column_base { using object_type = O; using field_type = T; using constraints_type = std::tuple; @@ -29,11 +37,6 @@ namespace sqlite_orm { using getter_type = G; using setter_type = S; - /** - * Column name. Specified during construction in `make_column`. - */ - const std::string name; - /** * Member pointer used to read/write member */ @@ -55,6 +58,10 @@ namespace sqlite_orm { */ constraints_type constraints; + column_t(std::string name, member_pointer_t member_pointer_, getter_type getter_, setter_type setter_, constraints_type constraints_): + column_base{std::move(name)}, member_pointer(member_pointer_), getter(getter_), setter(setter_), constraints(std::move(constraints_)) + {} + /** * Simplified interface for `NOT NULL` constraint */ @@ -109,6 +116,9 @@ namespace sqlite_orm { template struct is_column> : public std::true_type {}; + /** + * Getters aliases + */ template using getter_by_value_const = T (O::*)() const; @@ -127,6 +137,9 @@ namespace sqlite_orm { template using getter_by_const_ref = const T& (O::*)(); + /** + * Setters aliases + */ template using setter_by_value = void (O::*)(T); diff --git a/dev/conditions.h b/dev/conditions.h index bf550a0b9..66d243b65 100644 --- a/dev/conditions.h +++ b/dev/conditions.h @@ -63,21 +63,24 @@ namespace sqlite_orm { } }; + struct named_collate_base { + std::string name; + + operator std::string () const { + return "COLLATE " + this->name; + } + }; + /** * Collated something with custom collate function */ template - struct named_collate { + struct named_collate : named_collate_base { T expr; - std::string name; named_collate() = default; - named_collate(T expr_, std::string name_): expr(expr_), name(std::move(name_)) {} - - operator std::string () const { - return "COLLATE " + this->name; - } + named_collate(T expr_, std::string name_): named_collate_base{std::move(name_)}, expr(std::move(expr_)) {} }; /** @@ -328,32 +331,35 @@ namespace sqlite_orm { } }; + struct in_base { + bool negative = false; // used in not_in + + operator std::string () const { + if(!this->negative){ + return "IN"; + }else{ + return "NOT IN"; + } + } + }; + /** * IN operator object. */ template - struct in_t : public condition_t { + struct in_t : condition_t, in_base { using self = in_t; L l; // left expression A arg; // in arg - bool negative = false; // used in not_in in_t() = default; - in_t(L l_, A arg_, bool negative_): l(l_), arg(std::move(arg_)), negative(negative_) {} + in_t(L l_, A arg_, bool negative): in_base{negative}, l(l_), arg(std::move(arg_)) {} negated_condition_t operator!() const { return {*this}; } - - operator std::string () const { - if(!this->negative){ - return "IN"; - }else{ - return "NOT IN"; - } - } }; /** @@ -403,16 +409,19 @@ namespace sqlite_orm { } }; + struct order_by_base { + int asc_desc = 0; // 1: asc, -1: desc + std::string _collate_argument; + }; + /** * ORDER BY argument holder. */ template - struct order_by_t { + struct order_by_t : order_by_base { using self = order_by_t; O o; - int asc_desc = 0; // 1: asc, -1: desc - std::string _collate_argument; order_by_t(): o() {} @@ -615,7 +624,7 @@ namespace sqlite_orm { */ template struct using_t { - F O::*column; + F O::*column = nullptr; operator std::string() const { return "USING"; diff --git a/dev/constraints.h b/dev/constraints.h index f42ebab67..7f573c70b 100644 --- a/dev/constraints.h +++ b/dev/constraints.h @@ -20,24 +20,14 @@ namespace sqlite_orm { } }; - /** - * PRIMARY KEY constraint class. - * Cs is parameter pack which contains columns (member pointer and/or function pointers). Can be empty when used withen `make_column` function. - */ - template - struct primary_key_t { - std::tuple columns; + struct primary_key_base { enum class order_by { unspecified, ascending, descending, }; - order_by asc_option = order_by::unspecified; - primary_key_t(decltype(columns) c):columns(std::move(c)){} - - using field_type = void; // for column iteration. Better be deleted - using constraints_type = std::tuple<>; + order_by asc_option = order_by::unspecified; operator std::string() const { std::string res = "PRIMARY KEY"; @@ -53,6 +43,22 @@ namespace sqlite_orm { } return res; } + }; + + /** + * PRIMARY KEY constraint class. + * Cs is parameter pack which contains columns (member pointer and/or function pointers). Can be empty when used withen `make_column` function. + */ + template + struct primary_key_t : primary_key_base { + using order_by = primary_key_base::order_by; + + std::tuple columns; + + primary_key_t(decltype(columns) c):columns(std::move(c)){} + + using field_type = void; // for column iteration. Better be deleted + using constraints_type = std::tuple<>; primary_key_t asc() const { auto res = *this; @@ -298,7 +304,7 @@ namespace sqlite_orm { collate_t(internal::collate_argument argument_): argument(argument_) {} operator std::string() const { - std::string res = "COLLATE " + string_from_collate_argument(this->argument); + std::string res = "COLLATE " + this->string_from_collate_argument(this->argument); return res; } diff --git a/dev/index.h b/dev/index.h index cf6a5b0c0..54bd333ca 100644 --- a/dev/index.h +++ b/dev/index.h @@ -2,6 +2,7 @@ #include // std::tuple, std::make_tuple #include // std::string +#include // std::forward namespace sqlite_orm { @@ -23,11 +24,11 @@ namespace sqlite_orm { template internal::index_t make_index(const std::string &name, Cols ...cols) { - return {name, false, std::make_tuple(cols...)}; + return {name, false, std::make_tuple(std::forward(cols)...)}; } template internal::index_t make_unique_index(const std::string &name, Cols ...cols) { - return {name, true, std::make_tuple(cols...)}; + return {name, true, std::make_tuple(std::forward(cols)...)}; } } diff --git a/dev/select_constraints.h b/dev/select_constraints.h index cbf6c5ba5..7ee94856d 100644 --- a/dev/select_constraints.h +++ b/dev/select_constraints.h @@ -1,6 +1,8 @@ #pragma once #include // std::string +#include // std::declval +#include // std::true_type, std::false_type namespace sqlite_orm { @@ -165,21 +167,9 @@ namespace sqlite_orm { } }; - /** - * UNION object type. - */ - template - struct union_t : public compound_operator { - using super = compound_operator; - using left_type = typename super::left_type; - using right_type = typename super::right_type; - + struct union_base { bool all = false; - union_t(left_type l, right_type r, decltype(all) all_): super(std::move(l), std::move(r)), all(all_) {} - - union_t(left_type l, right_type r): union_t(std::move(l), std::move(r), false) {} - operator std::string() const { if(!this->all){ return "UNION"; @@ -189,6 +179,19 @@ namespace sqlite_orm { } }; + /** + * UNION object type. + */ + template + struct union_t : public compound_operator, union_base { + using left_type = typename compound_operator::left_type; + using right_type = typename compound_operator::right_type; + + union_t(left_type l, right_type r, decltype(all) all): compound_operator(std::move(l), std::move(r)), union_base{all} {} + + union_t(left_type l, right_type r): union_t(std::move(l), std::move(r), false) {} + }; + /** * EXCEPT object type. */ diff --git a/dev/storage_impl.h b/dev/storage_impl.h index f9624d287..5143219c0 100644 --- a/dev/storage_impl.h +++ b/dev/storage_impl.h @@ -26,6 +26,85 @@ namespace sqlite_orm { namespace internal { + struct storage_impl_base { + + static bool get_remove_add_columns(std::vector& columnsToAdd, + std::vector& storageTableInfo, + std::vector& dbTableInfo) + { + bool notEqual = false; + + // iterate through storage columns + for(size_t storageColumnInfoIndex = 0; storageColumnInfoIndex < storageTableInfo.size(); ++storageColumnInfoIndex) { + + // get storage's column info + auto &storageColumnInfo = storageTableInfo[storageColumnInfoIndex]; + auto &columnName = storageColumnInfo.name; + + // search for a column in db eith the same name + auto dbColumnInfoIt = std::find_if(dbTableInfo.begin(), + dbTableInfo.end(), + [&columnName](auto &ti){ + return ti.name == columnName; + }); + if(dbColumnInfoIt != dbTableInfo.end()){ + auto &dbColumnInfo = *dbColumnInfoIt; + auto dbColumnInfoType = to_sqlite_type(dbColumnInfo.type); + auto storageColumnInfoType = to_sqlite_type(storageColumnInfo.type); + if(dbColumnInfoType && storageColumnInfoType) { + auto columnsAreEqual = dbColumnInfo.name == storageColumnInfo.name && + *dbColumnInfoType == *storageColumnInfoType && + dbColumnInfo.notnull == storageColumnInfo.notnull && + (dbColumnInfo.dflt_value.length() > 0) == (storageColumnInfo.dflt_value.length() > 0) && + dbColumnInfo.pk == storageColumnInfo.pk; + if(!columnsAreEqual){ + notEqual = true; + break; + } + dbTableInfo.erase(dbColumnInfoIt); + storageTableInfo.erase(storageTableInfo.begin() + storageColumnInfoIndex); + --storageColumnInfoIndex; + }else{ + + // undefined type/types + notEqual = true; + break; + } + }else{ + columnsToAdd.push_back(&storageColumnInfo); + } + } + return notEqual; + } + + std::vector get_table_info(const std::string &tableName, sqlite3 *db) { + std::vector res; + auto query = "PRAGMA table_info('" + tableName + "')"; + auto rc = sqlite3_exec(db, + query.c_str(), + [](void *data, int argc, char **argv,char **) -> int { + auto &res = *(std::vector*)data; + if(argc){ + auto index = 0; + auto cid = std::atoi(argv[index++]); + std::string name = argv[index++]; + std::string type = argv[index++]; + bool notnull = !!std::atoi(argv[index++]); + std::string dflt_value = argv[index] ? argv[index] : ""; + index++; + auto pk = std::atoi(argv[index++]); + res.push_back(table_info{cid, name, type, notnull, dflt_value, pk}); + } + return 0; + }, &res, nullptr); + if(rc != SQLITE_OK) { + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); + } + return res; + } + + }; + /** * This is a generic implementation. Used as a tail in storage_impl inheritance chain */ @@ -206,32 +285,6 @@ namespace sqlite_orm { return ss.str(); } - std::vector get_table_info(const std::string &tableName, sqlite3 *db) { - std::vector res; - auto query = "PRAGMA table_info('" + tableName + "')"; - auto rc = sqlite3_exec(db, - query.c_str(), - [](void *data, int argc, char **argv,char **) -> int { - auto &res = *(std::vector*)data; - if(argc){ - auto index = 0; - auto cid = std::atoi(argv[index++]); - std::string name = argv[index++]; - std::string type = argv[index++]; - bool notnull = !!std::atoi(argv[index++]); - std::string dflt_value = argv[index] ? argv[index] : ""; - index++; - auto pk = std::atoi(argv[index++]); - res.push_back(table_info{cid, name, type, notnull, dflt_value, pk}); - } - return 0; - }, &res, nullptr); - if(rc != SQLITE_OK) { - throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); - } - return res; - } - void add_column(const table_info &ti, sqlite3 *db) { std::stringstream ss; ss << "ALTER TABLE " << this->table.name << " ADD COLUMN " << ti.name << " "; @@ -317,12 +370,12 @@ namespace sqlite_orm { auto storageTableInfo = this->table.get_table_info(); // now get current table info from db using `PRAGMA table_info` query.. - auto dbTableInfo = get_table_info(this->table.name, db); + auto dbTableInfo = this->get_table_info(this->table.name, db); // this vector will contain pointers to columns that gotta be added.. std::vector columnsToAdd; - if(get_remove_add_columns(columnsToAdd, storageTableInfo, dbTableInfo)) { + if(this->get_remove_add_columns(columnsToAdd, storageTableInfo, dbTableInfo)) { gottaCreateTable = true; } @@ -368,62 +421,12 @@ namespace sqlite_orm { return res; } - static bool get_remove_add_columns(std::vector& columnsToAdd, - std::vector& storageTableInfo, - std::vector& dbTableInfo) - { - bool notEqual = false; - - // iterate through storage columns - for(size_t storageColumnInfoIndex = 0; storageColumnInfoIndex < storageTableInfo.size(); ++storageColumnInfoIndex) { - - // get storage's column info - auto &storageColumnInfo = storageTableInfo[storageColumnInfoIndex]; - auto &columnName = storageColumnInfo.name; - - // search for a column in db eith the same name - auto dbColumnInfoIt = std::find_if(dbTableInfo.begin(), - dbTableInfo.end(), - [&columnName](auto &ti){ - return ti.name == columnName; - }); - if(dbColumnInfoIt != dbTableInfo.end()){ - auto &dbColumnInfo = *dbColumnInfoIt; - auto dbColumnInfoType = to_sqlite_type(dbColumnInfo.type); - auto storageColumnInfoType = to_sqlite_type(storageColumnInfo.type); - if(dbColumnInfoType && storageColumnInfoType) { - auto columnsAreEqual = dbColumnInfo.name == storageColumnInfo.name && - *dbColumnInfoType == *storageColumnInfoType && - dbColumnInfo.notnull == storageColumnInfo.notnull && - (dbColumnInfo.dflt_value.length() > 0) == (storageColumnInfo.dflt_value.length() > 0) && - dbColumnInfo.pk == storageColumnInfo.pk; - if(!columnsAreEqual){ - notEqual = true; - break; - } - dbTableInfo.erase(dbColumnInfoIt); - storageTableInfo.erase(storageTableInfo.begin() + storageColumnInfoIndex); - --storageColumnInfoIndex; - }else{ - - // undefined type/types - notEqual = true; - break; - } - }else{ - columnsToAdd.push_back(&storageColumnInfo); - } - } - return notEqual; - } - - private: using self = storage_impl; }; template<> - struct storage_impl<>{ + struct storage_impl<> : storage_impl_base { template std::string find_table_name() const { diff --git a/dev/table.h b/dev/table.h index 2b481d04e..e77446109 100644 --- a/dev/table.h +++ b/dev/table.h @@ -20,29 +20,32 @@ namespace sqlite_orm { namespace internal { + struct table_base { + + /** + * Table name. + */ + const std::string name; + + bool _without_rowid = false; + }; + /** * Table interface class. Implementation is hidden in `table_impl` class. */ template - struct table_t { + struct table_t : table_base { using impl_type = table_impl; using object_type = T; static constexpr const int columns_count = impl_type::columns_count; - /** - * Table name. - */ - const std::string name; - /** * Implementation that stores columns information. */ impl_type impl; - table_t(decltype(name) name_, decltype(impl) impl_): name(std::move(name_)), impl(std::move(impl_)) {} - - bool _without_rowid = false; + table_t(decltype(name) name_, decltype(impl) impl_): table_base{std::move(name_)}, impl(std::move(impl_)) {} table_t without_rowid() const { auto res = *this; diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index a1de47556..a88d1115a 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -420,24 +420,14 @@ namespace sqlite_orm { } }; - /** - * PRIMARY KEY constraint class. - * Cs is parameter pack which contains columns (member pointer and/or function pointers). Can be empty when used withen `make_column` function. - */ - template - struct primary_key_t { - std::tuple columns; + struct primary_key_base { enum class order_by { unspecified, ascending, descending, }; - order_by asc_option = order_by::unspecified; - - primary_key_t(decltype(columns) c):columns(std::move(c)){} - using field_type = void; // for column iteration. Better be deleted - using constraints_type = std::tuple<>; + order_by asc_option = order_by::unspecified; operator std::string() const { std::string res = "PRIMARY KEY"; @@ -453,6 +443,22 @@ namespace sqlite_orm { } return res; } + }; + + /** + * PRIMARY KEY constraint class. + * Cs is parameter pack which contains columns (member pointer and/or function pointers). Can be empty when used withen `make_column` function. + */ + template + struct primary_key_t : primary_key_base { + using order_by = primary_key_base::order_by; + + std::tuple columns; + + primary_key_t(decltype(columns) c):columns(std::move(c)){} + + using field_type = void; // for column iteration. Better be deleted + using constraints_type = std::tuple<>; primary_key_t asc() const { auto res = *this; @@ -698,7 +704,7 @@ namespace sqlite_orm { collate_t(internal::collate_argument argument_): argument(argument_) {} operator std::string() const { - std::string res = "COLLATE " + string_from_collate_argument(this->argument); + std::string res = "COLLATE " + this->string_from_collate_argument(this->argument); return res; } @@ -1115,6 +1121,14 @@ namespace sqlite_orm { namespace internal { + struct column_base { + + /** + * Column name. Specified during construction in `make_column`. + */ + const std::string name; + }; + /** * This class stores single column info. column_t is a pair of [column_name:member_pointer] mapped to a storage * O is a mapped class, e.g. User @@ -1122,7 +1136,7 @@ namespace sqlite_orm { * Op... is a constraints pack, e.g. primary_key_t, autoincrement_t etc */ template - struct column_t { + struct column_t : column_base { using object_type = O; using field_type = T; using constraints_type = std::tuple; @@ -1130,11 +1144,6 @@ namespace sqlite_orm { using getter_type = G; using setter_type = S; - /** - * Column name. Specified during construction in `make_column`. - */ - const std::string name; - /** * Member pointer used to read/write member */ @@ -1156,6 +1165,10 @@ namespace sqlite_orm { */ constraints_type constraints; + column_t(std::string name, member_pointer_t member_pointer_, getter_type getter_, setter_type setter_, constraints_type constraints_): + column_base{std::move(name)}, member_pointer(member_pointer_), getter(getter_), setter(setter_), constraints(std::move(constraints_)) + {} + /** * Simplified interface for `NOT NULL` constraint */ @@ -1210,6 +1223,9 @@ namespace sqlite_orm { template struct is_column> : public std::true_type {}; + /** + * Getters aliases + */ template using getter_by_value_const = T (O::*)() const; @@ -1228,6 +1244,9 @@ namespace sqlite_orm { template using getter_by_const_ref = const T& (O::*)(); + /** + * Setters aliases + */ template using setter_by_value = void (O::*)(T); @@ -1571,21 +1590,24 @@ namespace sqlite_orm { } }; + struct named_collate_base { + std::string name; + + operator std::string () const { + return "COLLATE " + this->name; + } + }; + /** * Collated something with custom collate function */ template - struct named_collate { + struct named_collate : named_collate_base { T expr; - std::string name; named_collate() = default; - named_collate(T expr_, std::string name_): expr(expr_), name(std::move(name_)) {} - - operator std::string () const { - return "COLLATE " + this->name; - } + named_collate(T expr_, std::string name_): named_collate_base{std::move(name_)}, expr(std::move(expr_)) {} }; /** @@ -1836,32 +1858,35 @@ namespace sqlite_orm { } }; + struct in_base { + bool negative = false; // used in not_in + + operator std::string () const { + if(!this->negative){ + return "IN"; + }else{ + return "NOT IN"; + } + } + }; + /** * IN operator object. */ template - struct in_t : public condition_t { + struct in_t : condition_t, in_base { using self = in_t; L l; // left expression A arg; // in arg - bool negative = false; // used in not_in in_t() = default; - in_t(L l_, A arg_, bool negative_): l(l_), arg(std::move(arg_)), negative(negative_) {} + in_t(L l_, A arg_, bool negative): in_base{negative}, l(l_), arg(std::move(arg_)) {} negated_condition_t operator!() const { return {*this}; } - - operator std::string () const { - if(!this->negative){ - return "IN"; - }else{ - return "NOT IN"; - } - } }; /** @@ -1911,16 +1936,19 @@ namespace sqlite_orm { } }; + struct order_by_base { + int asc_desc = 0; // 1: asc, -1: desc + std::string _collate_argument; + }; + /** * ORDER BY argument holder. */ template - struct order_by_t { + struct order_by_t : order_by_base { using self = order_by_t; O o; - int asc_desc = 0; // 1: asc, -1: desc - std::string _collate_argument; order_by_t(): o() {} @@ -2123,7 +2151,7 @@ namespace sqlite_orm { */ template struct using_t { - F O::*column; + F O::*column = nullptr; operator std::string() const { return "USING"; @@ -3442,6 +3470,8 @@ namespace sqlite_orm { #pragma once #include // std::string +#include // std::declval +#include // std::true_type, std::false_type namespace sqlite_orm { @@ -3606,21 +3636,9 @@ namespace sqlite_orm { } }; - /** - * UNION object type. - */ - template - struct union_t : public compound_operator { - using super = compound_operator; - using left_type = typename super::left_type; - using right_type = typename super::right_type; - + struct union_base { bool all = false; - union_t(left_type l, right_type r, decltype(all) all_): super(std::move(l), std::move(r)), all(all_) {} - - union_t(left_type l, right_type r): union_t(std::move(l), std::move(r), false) {} - operator std::string() const { if(!this->all){ return "UNION"; @@ -3630,6 +3648,19 @@ namespace sqlite_orm { } }; + /** + * UNION object type. + */ + template + struct union_t : public compound_operator, union_base { + using left_type = typename compound_operator::left_type; + using right_type = typename compound_operator::right_type; + + union_t(left_type l, right_type r, decltype(all) all): compound_operator(std::move(l), std::move(r)), union_base{all} {} + + union_t(left_type l, right_type r): union_t(std::move(l), std::move(r), false) {} + }; + /** * EXCEPT object type. */ @@ -4513,6 +4544,7 @@ namespace sqlite_orm { #include // std::tuple, std::make_tuple #include // std::string +#include // std::forward namespace sqlite_orm { @@ -4534,12 +4566,12 @@ namespace sqlite_orm { template internal::index_t make_index(const std::string &name, Cols ...cols) { - return {name, false, std::make_tuple(cols...)}; + return {name, false, std::make_tuple(std::forward(cols)...)}; } template internal::index_t make_unique_index(const std::string &name, Cols ...cols) { - return {name, true, std::make_tuple(cols...)}; + return {name, true, std::make_tuple(std::forward(cols)...)}; } } #pragma once @@ -5263,29 +5295,32 @@ namespace sqlite_orm { namespace internal { + struct table_base { + + /** + * Table name. + */ + const std::string name; + + bool _without_rowid = false; + }; + /** * Table interface class. Implementation is hidden in `table_impl` class. */ template - struct table_t { + struct table_t : table_base { using impl_type = table_impl; using object_type = T; static constexpr const int columns_count = impl_type::columns_count; - /** - * Table name. - */ - const std::string name; - /** * Implementation that stores columns information. */ impl_type impl; - table_t(decltype(name) name_, decltype(impl) impl_): name(std::move(name_)), impl(std::move(impl_)) {} - - bool _without_rowid = false; + table_t(decltype(name) name_, decltype(impl) impl_): table_base{std::move(name_)}, impl(std::move(impl_)) {} table_t without_rowid() const { auto res = *this; @@ -5601,6 +5636,85 @@ namespace sqlite_orm { namespace internal { + struct storage_impl_base { + + static bool get_remove_add_columns(std::vector& columnsToAdd, + std::vector& storageTableInfo, + std::vector& dbTableInfo) + { + bool notEqual = false; + + // iterate through storage columns + for(size_t storageColumnInfoIndex = 0; storageColumnInfoIndex < storageTableInfo.size(); ++storageColumnInfoIndex) { + + // get storage's column info + auto &storageColumnInfo = storageTableInfo[storageColumnInfoIndex]; + auto &columnName = storageColumnInfo.name; + + // search for a column in db eith the same name + auto dbColumnInfoIt = std::find_if(dbTableInfo.begin(), + dbTableInfo.end(), + [&columnName](auto &ti){ + return ti.name == columnName; + }); + if(dbColumnInfoIt != dbTableInfo.end()){ + auto &dbColumnInfo = *dbColumnInfoIt; + auto dbColumnInfoType = to_sqlite_type(dbColumnInfo.type); + auto storageColumnInfoType = to_sqlite_type(storageColumnInfo.type); + if(dbColumnInfoType && storageColumnInfoType) { + auto columnsAreEqual = dbColumnInfo.name == storageColumnInfo.name && + *dbColumnInfoType == *storageColumnInfoType && + dbColumnInfo.notnull == storageColumnInfo.notnull && + (dbColumnInfo.dflt_value.length() > 0) == (storageColumnInfo.dflt_value.length() > 0) && + dbColumnInfo.pk == storageColumnInfo.pk; + if(!columnsAreEqual){ + notEqual = true; + break; + } + dbTableInfo.erase(dbColumnInfoIt); + storageTableInfo.erase(storageTableInfo.begin() + storageColumnInfoIndex); + --storageColumnInfoIndex; + }else{ + + // undefined type/types + notEqual = true; + break; + } + }else{ + columnsToAdd.push_back(&storageColumnInfo); + } + } + return notEqual; + } + + std::vector get_table_info(const std::string &tableName, sqlite3 *db) { + std::vector res; + auto query = "PRAGMA table_info('" + tableName + "')"; + auto rc = sqlite3_exec(db, + query.c_str(), + [](void *data, int argc, char **argv,char **) -> int { + auto &res = *(std::vector*)data; + if(argc){ + auto index = 0; + auto cid = std::atoi(argv[index++]); + std::string name = argv[index++]; + std::string type = argv[index++]; + bool notnull = !!std::atoi(argv[index++]); + std::string dflt_value = argv[index] ? argv[index] : ""; + index++; + auto pk = std::atoi(argv[index++]); + res.push_back(table_info{cid, name, type, notnull, dflt_value, pk}); + } + return 0; + }, &res, nullptr); + if(rc != SQLITE_OK) { + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); + } + return res; + } + + }; + /** * This is a generic implementation. Used as a tail in storage_impl inheritance chain */ @@ -5781,32 +5895,6 @@ namespace sqlite_orm { return ss.str(); } - std::vector get_table_info(const std::string &tableName, sqlite3 *db) { - std::vector res; - auto query = "PRAGMA table_info('" + tableName + "')"; - auto rc = sqlite3_exec(db, - query.c_str(), - [](void *data, int argc, char **argv,char **) -> int { - auto &res = *(std::vector*)data; - if(argc){ - auto index = 0; - auto cid = std::atoi(argv[index++]); - std::string name = argv[index++]; - std::string type = argv[index++]; - bool notnull = !!std::atoi(argv[index++]); - std::string dflt_value = argv[index] ? argv[index] : ""; - index++; - auto pk = std::atoi(argv[index++]); - res.push_back(table_info{cid, name, type, notnull, dflt_value, pk}); - } - return 0; - }, &res, nullptr); - if(rc != SQLITE_OK) { - throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); - } - return res; - } - void add_column(const table_info &ti, sqlite3 *db) { std::stringstream ss; ss << "ALTER TABLE " << this->table.name << " ADD COLUMN " << ti.name << " "; @@ -5892,12 +5980,12 @@ namespace sqlite_orm { auto storageTableInfo = this->table.get_table_info(); // now get current table info from db using `PRAGMA table_info` query.. - auto dbTableInfo = get_table_info(this->table.name, db); + auto dbTableInfo = this->get_table_info(this->table.name, db); // this vector will contain pointers to columns that gotta be added.. std::vector columnsToAdd; - if(get_remove_add_columns(columnsToAdd, storageTableInfo, dbTableInfo)) { + if(this->get_remove_add_columns(columnsToAdd, storageTableInfo, dbTableInfo)) { gottaCreateTable = true; } @@ -5943,62 +6031,12 @@ namespace sqlite_orm { return res; } - static bool get_remove_add_columns(std::vector& columnsToAdd, - std::vector& storageTableInfo, - std::vector& dbTableInfo) - { - bool notEqual = false; - - // iterate through storage columns - for(size_t storageColumnInfoIndex = 0; storageColumnInfoIndex < storageTableInfo.size(); ++storageColumnInfoIndex) { - - // get storage's column info - auto &storageColumnInfo = storageTableInfo[storageColumnInfoIndex]; - auto &columnName = storageColumnInfo.name; - - // search for a column in db eith the same name - auto dbColumnInfoIt = std::find_if(dbTableInfo.begin(), - dbTableInfo.end(), - [&columnName](auto &ti){ - return ti.name == columnName; - }); - if(dbColumnInfoIt != dbTableInfo.end()){ - auto &dbColumnInfo = *dbColumnInfoIt; - auto dbColumnInfoType = to_sqlite_type(dbColumnInfo.type); - auto storageColumnInfoType = to_sqlite_type(storageColumnInfo.type); - if(dbColumnInfoType && storageColumnInfoType) { - auto columnsAreEqual = dbColumnInfo.name == storageColumnInfo.name && - *dbColumnInfoType == *storageColumnInfoType && - dbColumnInfo.notnull == storageColumnInfo.notnull && - (dbColumnInfo.dflt_value.length() > 0) == (storageColumnInfo.dflt_value.length() > 0) && - dbColumnInfo.pk == storageColumnInfo.pk; - if(!columnsAreEqual){ - notEqual = true; - break; - } - dbTableInfo.erase(dbColumnInfoIt); - storageTableInfo.erase(storageTableInfo.begin() + storageColumnInfoIndex); - --storageColumnInfoIndex; - }else{ - - // undefined type/types - notEqual = true; - break; - } - }else{ - columnsToAdd.push_back(&storageColumnInfo); - } - } - return notEqual; - } - - private: using self = storage_impl; }; template<> - struct storage_impl<>{ + struct storage_impl<> : storage_impl_base { template std::string find_table_name() const { From 40b356009c609a1cf63e994215a90d5abaedb3dd Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Fri, 19 Apr 2019 22:14:17 +0430 Subject: [PATCH 070/232] Add -AllowAppleClang option to vcpkg. (see #256) --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index c397e9b3d..14d071089 100644 --- a/.travis.yml +++ b/.travis.yml @@ -41,11 +41,11 @@ matrix: - CXX=clang++ - SQLITE_ORM_OMITS_CODECVT=ON - name: "osx clang" + addons: + homebrew: + packages: + - clang compiler: clang -# addons: -# homebrew: -# packages: -# - clang os: osx osx_image: xcode10.2 env: From a741afc5048d14f9ff50abed0400aca60c79c14a Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Fri, 19 Apr 2019 22:25:54 +0430 Subject: [PATCH 071/232] Add -AllowAppleClang option to vcpkg. (see #256) --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 14d071089..a8829263c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -77,14 +77,14 @@ before_install: # scripts to run before build before_script: - - if [[ "$CXX" == "clang" ]]; then clang --version ; fi - - if [[ "$CXX" == "clang" && "$TRAVIS_OS_NAME" == "osx" ]]; then chmod +x prepare-osx-with-clang.sh ; ./prepare-osx-with-clang.sh ; fi + - if [[ "$CXX" == *"clang"* ]]; then clang --version ; fi + - if [[ "$CXX" == *"clang"* && "$TRAVIS_OS_NAME" == "osx" ]]; then chmod +x prepare-osx-with-clang.sh ; ./prepare-osx-with-clang.sh ; fi - chmod +x build.sh - cd third_party - git clone https://github.com/Microsoft/vcpkg.git vcpkg - cd vcpkg - chmod +x bootstrap-vcpkg.sh - - if [[ "$CXX" == "clang" && "$TRAVIS_OS_NAME" == "osx" ]]; then ./bootstrap-vcpkg.sh --allowAppleClang ; else ./bootstrap-vcpkg.sh ; fi + - if [[ "$CXX" == *"clang"* && "$TRAVIS_OS_NAME" == "osx" ]]; then ./bootstrap-vcpkg.sh --allowAppleClang ; else ./bootstrap-vcpkg.sh ; fi - chmod +x vcpkg - ./vcpkg install gtest - cd ../.. From af2b9051949d468a1bbc1ddf0ae70c58c43362fc Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Fri, 19 Apr 2019 22:27:37 +0430 Subject: [PATCH 072/232] Add -AllowAppleClang option to vcpkg. (see #256) --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a8829263c..7a375735a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -44,7 +44,7 @@ matrix: addons: homebrew: packages: - - clang + - llvm compiler: clang os: osx osx_image: xcode10.2 From 8adfd53a6f84802e1144f0b7368bb4c0bbb4b998 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Fri, 19 Apr 2019 23:01:54 +0430 Subject: [PATCH 073/232] Add -AllowAppleClang option to vcpkg. (see #256) --- build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sh b/build.sh index 8acae85b0..5ca371f61 100755 --- a/build.sh +++ b/build.sh @@ -9,7 +9,7 @@ git clone https://github.com/Microsoft/vcpkg.git vcpkg cd vcpkg chmod +x bootstrap-vcpkg.sh -if [[ "$CXX" == "clang" && "$TRAVIS_OS_NAME" == "mac" ]]; then ./bootstrap-vcpkg.sh --allowAppleClang ; else ./bootstrap-vcpkg.sh ; fi +if [[ "$CXX" == *"clang"* && "$TRAVIS_OS_NAME" == "osx" ]]; then ./bootstrap-vcpkg.sh --allowAppleClang ; else ./bootstrap-vcpkg.sh ; fi chmod +x vcpkg ./vcpkg install gtest From 387c8bc1409fd52b1c73ffe2fd448667d743ac59 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Fri, 26 Apr 2019 09:43:01 +0300 Subject: [PATCH 074/232] refactored process conditions --- dev/storage.h | 197 ++-------------- dev/tuple_helper.h | 20 ++ dev/view.h | 186 +++++++++++++++ include/sqlite_orm/sqlite_orm.h | 394 ++++++++++++++++++-------------- tests/tests.cpp | 30 +++ 5 files changed, 481 insertions(+), 346 deletions(-) create mode 100644 dev/view.h diff --git a/dev/storage.h b/dev/storage.h index defbe6a76..08501b281 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -44,6 +44,7 @@ #include "journal_mode.h" #include "limit_accesor.h" #include "field_value_holder.h" +#include "view.h" namespace sqlite_orm { @@ -57,165 +58,6 @@ namespace sqlite_orm { using self = storage_t; using impl_type = storage_impl; - template - struct view_t { - using mapped_type = T; - - storage_t &storage; - std::shared_ptr connection; - - const std::string query; - - view_t(storage_t &stor, decltype(connection) conn, Args&& ...args): - storage(stor), - connection(std::move(conn)), - query([&args..., &stor]{ - std::string q; - stor.template generate_select_asterisk(&q, args...); - return q; - }()){} - - struct iterator_t { - protected: - // The double-indirection is so that copies of the iterator - // share the same sqlite3_stmt from a sqlite3_prepare_v2() - // call. When one finishes iterating it, the pointer - // inside the shared_ptr is nulled out in all copies. - std::shared_ptr stmt; - view_t &view; - // shared_ptr is used over unique_ptr here - // so that the iterator can be copyable. - std::shared_ptr current; - - void extract_value(std::unique_ptr &temp) { - temp = std::make_unique(); - auto &storage = this->view.storage; - auto &impl = storage.template get_impl(); - auto index = 0; - impl.table.for_each_column([&index, &temp, this] (auto &c) { - using field_type = typename std::decay::type::field_type; - auto value = row_extractor().extract(*this->stmt, index++); - if(c.member_pointer){ - auto member_pointer = c.member_pointer; - (*temp).*member_pointer = std::move(value); - }else{ - ((*temp).*(c.setter))(std::move(value)); - } - }); - } - - public: - using value_type = T; - using difference_type = std::ptrdiff_t; - using pointer = value_type *; - using reference = value_type &; - using iterator_category = std::input_iterator_tag; - - iterator_t(sqlite3_stmt * stmt_, view_t &view_): stmt(std::make_shared(stmt_)), view(view_) { - this->operator++(); - } - - iterator_t(const iterator_t &) = default; - - iterator_t(iterator_t&&) = default; - - iterator_t& operator=(iterator_t&&) = default; - - iterator_t& operator=(const iterator_t&) = default; - - ~iterator_t() { - if(this->stmt){ - statement_finalizer f{*this->stmt}; - } - } - - T& operator*() { - if(!this->stmt) { - throw std::system_error(std::make_error_code(orm_error_code::trying_to_dereference_null_iterator)); - } - if(!this->current){ - std::unique_ptr value; - this->extract_value(value); - this->current = std::move(value); - } - return *this->current; - } - - T* operator->() { - if(!this->stmt) { - throw std::system_error(std::make_error_code(orm_error_code::trying_to_dereference_null_iterator)); - } - if(!this->current){ - std::unique_ptr value; - this->extract_value(value); - this->current = std::move(value); - } - return &*this->current; - } - - void operator++() { - if(this->stmt && *this->stmt){ - auto ret = sqlite3_step(*this->stmt); - switch(ret){ - case SQLITE_ROW: - this->current = nullptr; - break; - case SQLITE_DONE:{ - statement_finalizer f{*this->stmt}; - *this->stmt = nullptr; - }break; - default:{ - throw std::system_error(std::error_code(sqlite3_errcode(this->view.connection->get_db()), get_sqlite_error_category())); - } - } - } - } - - void operator++(int) { - this->operator++(); - } - - bool operator==(const iterator_t &other) const { - if(this->stmt && other.stmt){ - return *this->stmt == *other.stmt; - }else{ - if(!this->stmt && !other.stmt){ - return true; - }else{ - return false; - } - } - } - - bool operator!=(const iterator_t &other) const { - return !(*this == other); - } - }; - - size_t size() { - return this->storage.template count(); - } - - bool empty() { - return !this->size(); - } - - iterator_t end() { - return {nullptr, *this}; - } - - iterator_t begin() { - sqlite3_stmt *stmt = nullptr; - auto db = this->connection->get_db(); - auto ret = sqlite3_prepare_v2(db, this->query.c_str(), -1, &stmt, nullptr); - if(ret == SQLITE_OK){ - return {stmt, *this}; - }else{ - throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); - } - } - }; - std::function on_open; transaction_guard_t transaction_guard() { @@ -261,6 +103,9 @@ namespace sqlite_orm { bool isOpenedForever = false; std::map collatingFunctions; + template + friend struct view_t; + /** * Check whether connection exists and returns it if yes or creates a new one * and returns it. @@ -1244,14 +1089,14 @@ namespace sqlite_orm { * Recursion end. */ template - void process_conditions(std::stringstream &, Args .../*args*/) { + void process_conditions(std::stringstream &, std::tuple .../*args*/) { //.. } template - void process_conditions(std::stringstream &ss, C c, Args&& ...args) { - this->process_single_condition(ss, c); - this->process_conditions(ss, std::forward(args)...); + void process_conditions(std::stringstream &ss, std::tuple args) { + this->process_single_condition(ss, tuple_helper::head(args)); + this->process_conditions(ss, tuple_helper::tail(args)); } void on_open_internal(sqlite3 *db) { @@ -1309,7 +1154,7 @@ namespace sqlite_orm { public: template - view_t iterate(Args&& ...args) { + view_t iterate(Args&& ...args) { this->assert_mapped_type(); auto connection = this->get_or_create_connection(); @@ -1346,7 +1191,7 @@ namespace sqlite_orm { auto &impl = this->get_impl(); std::stringstream ss; ss << "DELETE FROM '" << impl.table.name << "' "; - this->process_conditions(ss, std::forward(args)...); + this->process_conditions(ss, std::make_tuple(std::forward(args)...)); auto query = ss.str(); sqlite3_stmt *stmt; if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { @@ -1503,7 +1348,7 @@ namespace sqlite_orm { ss << ", "; } } - this->process_conditions(ss, wh...); + this->process_conditions(ss, std::make_tuple(std::forward(wh)...)); auto query = ss.str(); sqlite3_stmt *stmt; if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { @@ -1552,7 +1397,7 @@ namespace sqlite_orm { } } ss << "FROM '" << impl.table.name << "' "; - this->process_conditions(ss, std::forward(args)...); + this->process_conditions(ss, std::make_tuple(std::forward(args)...)); if(query){ *query = ss.str(); } @@ -1858,7 +1703,7 @@ namespace sqlite_orm { ss << ",\"" << *y << "\""; } ss << ") FROM '"<< impl.table.name << "' "; - this->process_conditions(ss, std::forward(args)...); + this->process_conditions(ss, std::make_tuple(std::forward(args)...)); auto query = ss.str(); auto rc = sqlite3_exec(connection->get_db(), query.c_str(), @@ -2113,7 +1958,7 @@ namespace sqlite_orm { if(!tableAliasString.empty()) { ss << "'" << tableAliasString << "' "; } - this->process_conditions(ss, args...); + this->process_conditions(ss, std::make_tuple(std::forward(args)...)); auto query = ss.str(); auto rc = sqlite3_exec(connection->get_db(), query.c_str(), @@ -2146,7 +1991,7 @@ namespace sqlite_orm { auto columnName = this->string_from_expression(m); if(columnName.length()){ ss << columnName << ") FROM '"<< impl.table.name << "' "; - this->process_conditions(ss, std::forward(args)...); + this->process_conditions(ss, std::make_tuple(std::forward(args)...)); auto query = ss.str(); auto rc = sqlite3_exec(connection->get_db(), query.c_str(), @@ -2183,7 +2028,7 @@ namespace sqlite_orm { auto columnName = this->string_from_expression(m); if(columnName.length()){ ss << columnName << ") FROM '"<< impl.table.name << "' "; - this->process_conditions(ss, std::forward(args)...); + this->process_conditions(ss, std::make_tuple(std::forward(args)...)); auto query = ss.str(); auto rc = sqlite3_exec(connection->get_db(), query.c_str(), @@ -2253,7 +2098,7 @@ namespace sqlite_orm { auto columnName = this->string_from_expression(m); if(columnName.length()){ ss << columnName << ") FROM '" << impl.table.name << "' "; - this->process_conditions(ss, std::forward(args)...); + this->process_conditions(ss, std::make_tuple(std::forward(args)...)); auto query = ss.str(); auto rc = sqlite3_exec(connection->get_db(), query.c_str(), @@ -2292,7 +2137,7 @@ namespace sqlite_orm { auto columnName = this->string_from_expression(m); if(columnName.length()){ ss << columnName << ") FROM '" << impl.table.name << "' "; - this->process_conditions(ss, std::forward(args)...); + this->process_conditions(ss, std::make_tuple(std::forward(args)...)); auto query = ss.str(); auto rc = sqlite3_exec(connection->get_db(), query.c_str(), @@ -2331,7 +2176,7 @@ namespace sqlite_orm { auto columnName = this->string_from_expression(m); if(columnName.length()){ ss << columnName << ") FROM '"<< impl.table.name << "' "; - this->process_conditions(ss, std::forward(args)...); + this->process_conditions(ss, std::make_tuple(std::forward(args)...)); auto query = ss.str(); auto rc = sqlite3_exec(connection->get_db(), query.c_str(), @@ -2361,7 +2206,7 @@ namespace sqlite_orm { this->assert_mapped_type(); auto connection = this->get_or_create_connection(); - double res; + double res = 0; std::stringstream ss; ss << "SELECT " << static_cast(sqlite_orm::total(0)) << "("; auto columnName = this->string_from_expression(m); @@ -2379,7 +2224,7 @@ namespace sqlite_orm { ss << " "; } } - this->process_conditions(ss, std::forward(args)...); + this->process_conditions(ss, std::make_tuple(std::forward(args)...)); auto query = ss.str(); auto rc = sqlite3_exec(connection->get_db(), query.c_str(), diff --git a/dev/tuple_helper.h b/dev/tuple_helper.h index a4a947935..e0b3e4dee 100644 --- a/dev/tuple_helper.h +++ b/dev/tuple_helper.h @@ -67,5 +67,25 @@ namespace sqlite_orm { void tuple_for_each(const std::tuple& t, F&& f){ tuple_for_each_impl(std::forward(f), t, std::index_sequence_for{}); } + + // got it from here https://stackoverflow.com/questions/10626856/how-to-split-a-tuple + + template + auto head(std::tuple t) + { + return std::get<0>(t); + } + + template + auto tail_impl(std::index_sequence , std::tuple t) + { + return std::make_tuple(std::get(t)...); + } + + template + auto tail(std::tuple t) + { + return tail_impl(std::make_index_sequence() , t); + } } } diff --git a/dev/view.h b/dev/view.h new file mode 100644 index 000000000..3fe55fa57 --- /dev/null +++ b/dev/view.h @@ -0,0 +1,186 @@ +#pragma once + +#include // std::shared_ptr, std::make_shared, std::unique_ptr, std::make_unique +#include // std::string +#include // std::forward, std::move +#include +#include // std::decay +#include // std::ptrdiff_t +#include // std::make_error_code +#include // std::system_error + +#include "database_connection.h" +#include "row_extractor.h" +#include "statement_finalizer.h" +#include "error_code.h" + +namespace sqlite_orm { + + namespace internal { + + template + struct view_t { + using mapped_type = T; + using storage_type = S; + + storage_type &storage; + std::shared_ptr connection; + + const std::string query; + + view_t(storage_type &stor, decltype(connection) conn, Args&& ...args): + storage(stor), + connection(std::move(conn)), + query([&args..., &stor]{ + std::string q; + stor.template generate_select_asterisk(&q, std::forward(args)...); + return q; + }()){} + + struct iterator_t { + protected: + /** + * The double-indirection is so that copies of the iterator + * share the same sqlite3_stmt from a sqlite3_prepare_v2() + * call. When one finishes iterating it, the pointer + * inside the shared_ptr is nulled out in all copies. + */ + std::shared_ptr stmt; + view_t &view; + + /** + * shared_ptr is used over unique_ptr here + * so that the iterator can be copyable. + */ + std::shared_ptr current; + + void extract_value(std::unique_ptr &temp) { + temp = std::make_unique(); + auto &storage = this->view.storage; + auto &impl = storage.template get_impl(); + auto index = 0; + impl.table.for_each_column([&index, &temp, this] (auto &c) { + using field_type = typename std::decay::type::field_type; + auto value = row_extractor().extract(*this->stmt, index++); + if(c.member_pointer){ + auto member_pointer = c.member_pointer; + (*temp).*member_pointer = std::move(value); + }else{ + ((*temp).*(c.setter))(std::move(value)); + } + }); + } + + public: + using value_type = T; + using difference_type = std::ptrdiff_t; + using pointer = value_type *; + using reference = value_type &; + using iterator_category = std::input_iterator_tag; + + iterator_t(sqlite3_stmt *stmt_, view_t &view_): stmt(std::make_shared(stmt_)), view(view_) { + this->operator++(); + } + + iterator_t(const iterator_t &) = default; + + iterator_t(iterator_t&&) = default; + + iterator_t& operator=(iterator_t&&) = default; + + iterator_t& operator=(const iterator_t&) = default; + + ~iterator_t() { + if(this->stmt){ + statement_finalizer f{*this->stmt}; + } + } + + T& operator*() { + if(!this->stmt) { + throw std::system_error(std::make_error_code(orm_error_code::trying_to_dereference_null_iterator)); + } + if(!this->current){ + std::unique_ptr value; + this->extract_value(value); + this->current = std::move(value); + } + return *this->current; + } + + T* operator->() { + if(!this->stmt) { + throw std::system_error(std::make_error_code(orm_error_code::trying_to_dereference_null_iterator)); + } + if(!this->current){ + std::unique_ptr value; + this->extract_value(value); + this->current = std::move(value); + } + return &*this->current; + } + + void operator++() { + if(this->stmt && *this->stmt){ + auto ret = sqlite3_step(*this->stmt); + switch(ret){ + case SQLITE_ROW: + this->current = nullptr; + break; + case SQLITE_DONE:{ + statement_finalizer f{*this->stmt}; + *this->stmt = nullptr; + }break; + default:{ + throw std::system_error(std::error_code(sqlite3_errcode(this->view.connection->get_db()), get_sqlite_error_category())); + } + } + } + } + + void operator++(int) { + this->operator++(); + } + + bool operator==(const iterator_t &other) const { + if(this->stmt && other.stmt){ + return *this->stmt == *other.stmt; + }else{ + if(!this->stmt && !other.stmt){ + return true; + }else{ + return false; + } + } + } + + bool operator!=(const iterator_t &other) const { + return !(*this == other); + } + }; + + size_t size() { + return this->storage.template count(); + } + + bool empty() { + return !this->size(); + } + + iterator_t end() { + return {nullptr, *this}; + } + + iterator_t begin() { + sqlite3_stmt *stmt = nullptr; + auto db = this->connection->get_db(); + auto ret = sqlite3_prepare_v2(db, this->query.c_str(), -1, &stmt, nullptr); + if(ret == SQLITE_OK){ + return {stmt, *this}; + }else{ + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); + } + } + }; + } +} diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index b398f7a12..9bd6d7851 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -256,6 +256,26 @@ namespace sqlite_orm { void tuple_for_each(const std::tuple& t, F&& f){ tuple_for_each_impl(std::forward(f), t, std::index_sequence_for{}); } + + // got it from here https://stackoverflow.com/questions/10626856/how-to-split-a-tuple + + template + auto head(std::tuple t) + { + return std::get<0>(t); + } + + template + auto tail_impl(std::index_sequence , std::tuple t) + { + return std::make_tuple(std::get(t)...); + } + + template + auto tail(std::tuple t) + { + return tail_impl(std::make_index_sequence() , t); + } } } #pragma once @@ -5340,28 +5360,26 @@ namespace sqlite_orm { using member_pointer_t = typename column_type::member_pointer_t; using getter_type = typename column_type::getter_type; using setter_type = typename column_type::setter_type; - - // GCC has bug that reported in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64095 so static_if must have at lease one input if(!res){ - static_if{}>([&res, &obj, &col](const C& c){ + static_if{}>([&res, &obj, &col, &c]{ if(compare_any(col.member_pointer, c)){ res = &(obj.*col.member_pointer); } - })(c); + })(); } if(!res){ - static_if{}>([&res, &obj, &col](const C& c){ + static_if{}>([&res, &obj, &col, &c]{ if(compare_any(col.getter, c)){ res = &((obj).*(col.getter))(); } - })(c); + })(); } if(!res){ - static_if{}>([&res, &obj, &col](const C& c){ + static_if{}>([&res, &obj, &col, &c]{ if(compare_any(col.setter, c)){ res = &((obj).*(col.getter))(); } - })(c); + })(); } }); return res; @@ -6564,178 +6582,211 @@ namespace sqlite_orm { // #include "field_value_holder.h" +// #include "view.h" + + +#include // std::shared_ptr, std::make_shared, std::unique_ptr, std::make_unique +#include // std::string +#include // std::forward, std::move +#include +#include // std::decay +#include // std::ptrdiff_t +#include // std::make_error_code +#include // std::system_error + +// #include "database_connection.h" + +// #include "row_extractor.h" + +// #include "statement_finalizer.h" + +// #include "error_code.h" + namespace sqlite_orm { namespace internal { - /** - * Storage class itself. Create an instanse to use it as an interfacto to sqlite db by calling `make_storage` function. - */ - template - struct storage_t { - using self = storage_t; - using impl_type = storage_impl; + template + struct view_t { + using mapped_type = T; + using storage_type = S; - template - struct view_t { - using mapped_type = T; + storage_type &storage; + std::shared_ptr connection; + + const std::string query; + + view_t(storage_type &stor, decltype(connection) conn, Args&& ...args): + storage(stor), + connection(std::move(conn)), + query([&args..., &stor]{ + std::string q; + stor.template generate_select_asterisk(&q, std::forward(args)...); + return q; + }()){} + + struct iterator_t { + protected: + /** + * The double-indirection is so that copies of the iterator + * share the same sqlite3_stmt from a sqlite3_prepare_v2() + * call. When one finishes iterating it, the pointer + * inside the shared_ptr is nulled out in all copies. + */ + std::shared_ptr stmt; + view_t &view; - storage_t &storage; - std::shared_ptr connection; + /** + * shared_ptr is used over unique_ptr here + * so that the iterator can be copyable. + */ + std::shared_ptr current; - const std::string query; + void extract_value(std::unique_ptr &temp) { + temp = std::make_unique(); + auto &storage = this->view.storage; + auto &impl = storage.template get_impl(); + auto index = 0; + impl.table.for_each_column([&index, &temp, this] (auto &c) { + using field_type = typename std::decay::type::field_type; + auto value = row_extractor().extract(*this->stmt, index++); + if(c.member_pointer){ + auto member_pointer = c.member_pointer; + (*temp).*member_pointer = std::move(value); + }else{ + ((*temp).*(c.setter))(std::move(value)); + } + }); + } - view_t(storage_t &stor, decltype(connection) conn, Args&& ...args): - storage(stor), - connection(std::move(conn)), - query([&args..., &stor]{ - std::string q; - stor.template generate_select_asterisk(&q, args...); - return q; - }()){} + public: + using value_type = T; + using difference_type = std::ptrdiff_t; + using pointer = value_type *; + using reference = value_type &; + using iterator_category = std::input_iterator_tag; - struct iterator_t { - protected: - // The double-indirection is so that copies of the iterator - // share the same sqlite3_stmt from a sqlite3_prepare_v2() - // call. When one finishes iterating it, the pointer - // inside the shared_ptr is nulled out in all copies. - std::shared_ptr stmt; - view_t &view; - // shared_ptr is used over unique_ptr here - // so that the iterator can be copyable. - std::shared_ptr current; - - void extract_value(std::unique_ptr &temp) { - temp = std::make_unique(); - auto &storage = this->view.storage; - auto &impl = storage.template get_impl(); - auto index = 0; - impl.table.for_each_column([&index, &temp, this] (auto &c) { - using field_type = typename std::decay::type::field_type; - auto value = row_extractor().extract(*this->stmt, index++); - if(c.member_pointer){ - auto member_pointer = c.member_pointer; - (*temp).*member_pointer = std::move(value); - }else{ - ((*temp).*(c.setter))(std::move(value)); - } - }); - } - - public: - using value_type = T; - using difference_type = std::ptrdiff_t; - using pointer = value_type *; - using reference = value_type &; - using iterator_category = std::input_iterator_tag; - - iterator_t(sqlite3_stmt * stmt_, view_t &view_): stmt(std::make_shared(stmt_)), view(view_) { - this->operator++(); - } - - iterator_t(const iterator_t &) = default; - - iterator_t(iterator_t&&) = default; - - iterator_t& operator=(iterator_t&&) = default; - - iterator_t& operator=(const iterator_t&) = default; - - ~iterator_t() { - if(this->stmt){ - statement_finalizer f{*this->stmt}; - } + iterator_t(sqlite3_stmt *stmt_, view_t &view_): stmt(std::make_shared(stmt_)), view(view_) { + this->operator++(); + } + + iterator_t(const iterator_t &) = default; + + iterator_t(iterator_t&&) = default; + + iterator_t& operator=(iterator_t&&) = default; + + iterator_t& operator=(const iterator_t&) = default; + + ~iterator_t() { + if(this->stmt){ + statement_finalizer f{*this->stmt}; } - - T& operator*() { - if(!this->stmt) { - throw std::system_error(std::make_error_code(orm_error_code::trying_to_dereference_null_iterator)); - } - if(!this->current){ - std::unique_ptr value; - this->extract_value(value); - this->current = std::move(value); - } - return *this->current; + } + + T& operator*() { + if(!this->stmt) { + throw std::system_error(std::make_error_code(orm_error_code::trying_to_dereference_null_iterator)); } - - T* operator->() { - if(!this->stmt) { - throw std::system_error(std::make_error_code(orm_error_code::trying_to_dereference_null_iterator)); - } - if(!this->current){ - std::unique_ptr value; - this->extract_value(value); - this->current = std::move(value); - } - return &*this->current; + if(!this->current){ + std::unique_ptr value; + this->extract_value(value); + this->current = std::move(value); } - - void operator++() { - if(this->stmt && *this->stmt){ - auto ret = sqlite3_step(*this->stmt); - switch(ret){ - case SQLITE_ROW: - this->current = nullptr; - break; - case SQLITE_DONE:{ - statement_finalizer f{*this->stmt}; - *this->stmt = nullptr; - }break; - default:{ - throw std::system_error(std::error_code(sqlite3_errcode(this->view.connection->get_db()), get_sqlite_error_category())); - } - } - } + return *this->current; + } + + T* operator->() { + if(!this->stmt) { + throw std::system_error(std::make_error_code(orm_error_code::trying_to_dereference_null_iterator)); } - - void operator++(int) { - this->operator++(); + if(!this->current){ + std::unique_ptr value; + this->extract_value(value); + this->current = std::move(value); } - - bool operator==(const iterator_t &other) const { - if(this->stmt && other.stmt){ - return *this->stmt == *other.stmt; - }else{ - if(!this->stmt && !other.stmt){ - return true; - }else{ - return false; + return &*this->current; + } + + void operator++() { + if(this->stmt && *this->stmt){ + auto ret = sqlite3_step(*this->stmt); + switch(ret){ + case SQLITE_ROW: + this->current = nullptr; + break; + case SQLITE_DONE:{ + statement_finalizer f{*this->stmt}; + *this->stmt = nullptr; + }break; + default:{ + throw std::system_error(std::error_code(sqlite3_errcode(this->view.connection->get_db()), get_sqlite_error_category())); } } } - - bool operator!=(const iterator_t &other) const { - return !(*this == other); - } - }; - - size_t size() { - return this->storage.template count(); - } - - bool empty() { - return !this->size(); } - iterator_t end() { - return {nullptr, *this}; + void operator++(int) { + this->operator++(); } - iterator_t begin() { - sqlite3_stmt *stmt = nullptr; - auto db = this->connection->get_db(); - auto ret = sqlite3_prepare_v2(db, this->query.c_str(), -1, &stmt, nullptr); - if(ret == SQLITE_OK){ - return {stmt, *this}; + bool operator==(const iterator_t &other) const { + if(this->stmt && other.stmt){ + return *this->stmt == *other.stmt; }else{ - throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); + if(!this->stmt && !other.stmt){ + return true; + }else{ + return false; + } } } + + bool operator!=(const iterator_t &other) const { + return !(*this == other); + } }; + size_t size() { + return this->storage.template count(); + } + + bool empty() { + return !this->size(); + } + + iterator_t end() { + return {nullptr, *this}; + } + + iterator_t begin() { + sqlite3_stmt *stmt = nullptr; + auto db = this->connection->get_db(); + auto ret = sqlite3_prepare_v2(db, this->query.c_str(), -1, &stmt, nullptr); + if(ret == SQLITE_OK){ + return {stmt, *this}; + }else{ + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); + } + } + }; + } +} + + +namespace sqlite_orm { + + namespace internal { + + /** + * Storage class itself. Create an instanse to use it as an interfacto to sqlite db by calling `make_storage` function. + */ + template + struct storage_t { + using self = storage_t; + using impl_type = storage_impl; + std::function on_open; transaction_guard_t transaction_guard() { @@ -6781,6 +6832,9 @@ namespace sqlite_orm { bool isOpenedForever = false; std::map collatingFunctions; + template + friend struct view_t; + /** * Check whether connection exists and returns it if yes or creates a new one * and returns it. @@ -7764,14 +7818,14 @@ namespace sqlite_orm { * Recursion end. */ template - void process_conditions(std::stringstream &, Args .../*args*/) { + void process_conditions(std::stringstream &, std::tuple .../*args*/) { //.. } template - void process_conditions(std::stringstream &ss, C c, Args&& ...args) { - this->process_single_condition(ss, c); - this->process_conditions(ss, std::forward(args)...); + void process_conditions(std::stringstream &ss, std::tuple args) { + this->process_single_condition(ss, tuple_helper::head(args)); + this->process_conditions(ss, tuple_helper::tail(args)); } void on_open_internal(sqlite3 *db) { @@ -7829,7 +7883,7 @@ namespace sqlite_orm { public: template - view_t iterate(Args&& ...args) { + view_t iterate(Args&& ...args) { this->assert_mapped_type(); auto connection = this->get_or_create_connection(); @@ -7866,7 +7920,7 @@ namespace sqlite_orm { auto &impl = this->get_impl(); std::stringstream ss; ss << "DELETE FROM '" << impl.table.name << "' "; - this->process_conditions(ss, std::forward(args)...); + this->process_conditions(ss, std::make_tuple(std::forward(args)...)); auto query = ss.str(); sqlite3_stmt *stmt; if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { @@ -8023,7 +8077,7 @@ namespace sqlite_orm { ss << ", "; } } - this->process_conditions(ss, wh...); + this->process_conditions(ss, std::make_tuple(std::forward(wh)...)); auto query = ss.str(); sqlite3_stmt *stmt; if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { @@ -8072,7 +8126,7 @@ namespace sqlite_orm { } } ss << "FROM '" << impl.table.name << "' "; - this->process_conditions(ss, std::forward(args)...); + this->process_conditions(ss, std::make_tuple(std::forward(args)...)); if(query){ *query = ss.str(); } @@ -8378,7 +8432,7 @@ namespace sqlite_orm { ss << ",\"" << *y << "\""; } ss << ") FROM '"<< impl.table.name << "' "; - this->process_conditions(ss, std::forward(args)...); + this->process_conditions(ss, std::make_tuple(std::forward(args)...)); auto query = ss.str(); auto rc = sqlite3_exec(connection->get_db(), query.c_str(), @@ -8633,7 +8687,7 @@ namespace sqlite_orm { if(!tableAliasString.empty()) { ss << "'" << tableAliasString << "' "; } - this->process_conditions(ss, args...); + this->process_conditions(ss, std::make_tuple(std::forward(args)...)); auto query = ss.str(); auto rc = sqlite3_exec(connection->get_db(), query.c_str(), @@ -8666,7 +8720,7 @@ namespace sqlite_orm { auto columnName = this->string_from_expression(m); if(columnName.length()){ ss << columnName << ") FROM '"<< impl.table.name << "' "; - this->process_conditions(ss, std::forward(args)...); + this->process_conditions(ss, std::make_tuple(std::forward(args)...)); auto query = ss.str(); auto rc = sqlite3_exec(connection->get_db(), query.c_str(), @@ -8703,7 +8757,7 @@ namespace sqlite_orm { auto columnName = this->string_from_expression(m); if(columnName.length()){ ss << columnName << ") FROM '"<< impl.table.name << "' "; - this->process_conditions(ss, std::forward(args)...); + this->process_conditions(ss, std::make_tuple(std::forward(args)...)); auto query = ss.str(); auto rc = sqlite3_exec(connection->get_db(), query.c_str(), @@ -8773,7 +8827,7 @@ namespace sqlite_orm { auto columnName = this->string_from_expression(m); if(columnName.length()){ ss << columnName << ") FROM '" << impl.table.name << "' "; - this->process_conditions(ss, std::forward(args)...); + this->process_conditions(ss, std::make_tuple(std::forward(args)...)); auto query = ss.str(); auto rc = sqlite3_exec(connection->get_db(), query.c_str(), @@ -8812,7 +8866,7 @@ namespace sqlite_orm { auto columnName = this->string_from_expression(m); if(columnName.length()){ ss << columnName << ") FROM '" << impl.table.name << "' "; - this->process_conditions(ss, std::forward(args)...); + this->process_conditions(ss, std::make_tuple(std::forward(args)...)); auto query = ss.str(); auto rc = sqlite3_exec(connection->get_db(), query.c_str(), @@ -8851,7 +8905,7 @@ namespace sqlite_orm { auto columnName = this->string_from_expression(m); if(columnName.length()){ ss << columnName << ") FROM '"<< impl.table.name << "' "; - this->process_conditions(ss, std::forward(args)...); + this->process_conditions(ss, std::make_tuple(std::forward(args)...)); auto query = ss.str(); auto rc = sqlite3_exec(connection->get_db(), query.c_str(), @@ -8881,7 +8935,7 @@ namespace sqlite_orm { this->assert_mapped_type(); auto connection = this->get_or_create_connection(); - double res; + double res = 0; std::stringstream ss; ss << "SELECT " << static_cast(sqlite_orm::total(0)) << "("; auto columnName = this->string_from_expression(m); @@ -8899,7 +8953,7 @@ namespace sqlite_orm { ss << " "; } } - this->process_conditions(ss, std::forward(args)...); + this->process_conditions(ss, std::make_tuple(std::forward(args)...)); auto query = ss.str(); auto rc = sqlite3_exec(connection->get_db(), query.c_str(), diff --git a/tests/tests.cpp b/tests/tests.cpp index 008c0fa9b..15a68efcd 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -12,6 +12,34 @@ using namespace sqlite_orm; using std::cout; using std::endl; +void testIterateBlob() { + /*struct Test { + int64_t id; + std::vector key; + }; + + auto db = make_storage("", + make_table("Test", + make_column("key", &Test::key), + make_column("id", &Test::id, autoincrement(), primary_key()))); + db.sync_schema(true); + + std::vector key; + key.resize(255); + for (int i = 0; i < 255; i++){ + key[i] = i; + } + + Test v; + v.key = key; + + db.insert(v); + + for (auto& w : db.iterate(where(c(&Test::key) == key))) { + cout << w.id << endl; + }*/ +} + void testCast() { cout << __func__ << endl; @@ -2432,4 +2460,6 @@ int main(int argc, char **argv) { testCast(); testWhere(); + + testIterateBlob(); } From 86b9bc41aeeecf68fc369b0f785cb61bfeb84f51 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Fri, 26 Apr 2019 10:13:44 +0300 Subject: [PATCH 075/232] fixed GCC compilation --- dev/table.h | 12 ++++++------ include/sqlite_orm/sqlite_orm.h | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/dev/table.h b/dev/table.h index e77446109..1f3f54e12 100644 --- a/dev/table.h +++ b/dev/table.h @@ -66,25 +66,25 @@ namespace sqlite_orm { using getter_type = typename column_type::getter_type; using setter_type = typename column_type::setter_type; if(!res){ - static_if{}>([&res, &obj, &col, &c]{ + static_if{}>([&res, &obj, &col](const C &c){ if(compare_any(col.member_pointer, c)){ res = &(obj.*col.member_pointer); } - })(); + })(c); } if(!res){ - static_if{}>([&res, &obj, &col, &c]{ + static_if{}>([&res, &obj, &col](const C &c){ if(compare_any(col.getter, c)){ res = &((obj).*(col.getter))(); } - })(); + })(c); } if(!res){ - static_if{}>([&res, &obj, &col, &c]{ + static_if{}>([&res, &obj, &col](const C &c){ if(compare_any(col.setter, c)){ res = &((obj).*(col.getter))(); } - })(); + })(c); } }); return res; diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 9bd6d7851..285b80e45 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -5361,25 +5361,25 @@ namespace sqlite_orm { using getter_type = typename column_type::getter_type; using setter_type = typename column_type::setter_type; if(!res){ - static_if{}>([&res, &obj, &col, &c]{ + static_if{}>([&res, &obj, &col](const C &c){ if(compare_any(col.member_pointer, c)){ res = &(obj.*col.member_pointer); } - })(); + })(c); } if(!res){ - static_if{}>([&res, &obj, &col, &c]{ + static_if{}>([&res, &obj, &col](const C &c){ if(compare_any(col.getter, c)){ res = &((obj).*(col.getter))(); } - })(); + })(c); } if(!res){ - static_if{}>([&res, &obj, &col, &c]{ + static_if{}>([&res, &obj, &col](const C &c){ if(compare_any(col.setter, c)){ res = &((obj).*(col.getter))(); } - })(); + })(c); } }); return res; From 9fcbca040babee8bd462752807940eca6d10f6af Mon Sep 17 00:00:00 2001 From: Matt Kline Date: Fri, 26 Apr 2019 10:47:17 -0700 Subject: [PATCH 076/232] Apply e422eb2 to dev/table.h Unless it's done there, any run of the amalgamation script will remove this fix from sqlite_orm.h --- dev/table.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/dev/table.h b/dev/table.h index e77446109..0423d6208 100644 --- a/dev/table.h +++ b/dev/table.h @@ -65,26 +65,28 @@ namespace sqlite_orm { using member_pointer_t = typename column_type::member_pointer_t; using getter_type = typename column_type::getter_type; using setter_type = typename column_type::setter_type; + // Make static_if have at least one input as a workaround for GCC bug: + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64095 if(!res){ - static_if{}>([&res, &obj, &col, &c]{ + static_if{}>([&res, &obj, &col](const C& c){ if(compare_any(col.member_pointer, c)){ res = &(obj.*col.member_pointer); } - })(); + })(c); } if(!res){ - static_if{}>([&res, &obj, &col, &c]{ + static_if{}>([&res, &obj, &col](const C& c){ if(compare_any(col.getter, c)){ res = &((obj).*(col.getter))(); } - })(); + })(c); } if(!res){ - static_if{}>([&res, &obj, &col, &c]{ + static_if{}>([&res, &obj, &col](const C& c){ if(compare_any(col.setter, c)){ res = &((obj).*(col.getter))(); } - })(); + })(c); } }); return res; From 23a4d4e1cbc5ca7be040807c206bcdaf0b25b035 Mon Sep 17 00:00:00 2001 From: Matt Kline Date: Wed, 24 Apr 2019 15:21:12 -0700 Subject: [PATCH 077/232] Various fixes for GCC 8.3 and Clang 8 warnings The project I'm using sqlite_orm for is built with fairly stringent warnings (-Wall -Wextra -Wpointer-arith -Wconversion -Wsign-conversion -Wno-maybe-uninitialized -Werror). This resolves warnings that came out of that set, mostly related to: - Sign conversion errors, especially regarding size_t <-> int. To preserve the existing API, all count() functions continue to return int, but this requires casts whenever you compare those to STL .size() calls. - Unused args - Catching exceptions by value - Unreachable locations - I'm currently calling assert(false) to convince the compiler that we don't reach the end of some functions (and exit without returning a value). Let me know if something else is preferred - e.g. an UNREACHABLE macro that resolves to __builtin_unreachable() in GCC and Clang. --- dev/constraints.h | 2 ++ dev/row_extractor.h | 10 +++--- dev/select_constraints.h | 2 +- dev/static_magic.h | 4 +-- dev/storage.h | 28 ++++++++-------- dev/storage_impl.h | 2 +- dev/sync_schema_result.h | 1 + examples/blob.cpp | 2 +- examples/collate.cpp | 2 +- examples/composite_key.cpp | 2 +- examples/core_functions.cpp | 2 +- examples/cross_join.cpp | 2 +- examples/custom_aliases.cpp | 2 +- examples/distinct.cpp | 2 +- examples/enum_binding.cpp | 3 ++ examples/exists.cpp | 26 +++++++-------- examples/foreign_key.cpp | 12 +++---- examples/group_by.cpp | 2 +- examples/in_memory.cpp | 2 +- examples/index.cpp | 4 +-- examples/insert.cpp | 2 +- examples/iteration.cpp | 4 +-- examples/key_value.cpp | 2 +- examples/left_and_inner_join.cpp | 2 +- examples/multi_table_select.cpp | 2 +- examples/nullable_enum_binding.cpp | 4 ++- examples/private_class_members.cpp | 2 +- examples/select.cpp | 2 +- examples/subentities.cpp | 6 ++-- examples/subquery.cpp | 2 +- examples/synchronous.cpp | 2 +- examples/unique.cpp | 4 +-- examples/update.cpp | 2 +- include/sqlite_orm/sqlite_orm.h | 53 ++++++++++++++++-------------- tests/tests.cpp | 48 +++++++++++++-------------- 35 files changed, 130 insertions(+), 119 deletions(-) diff --git a/dev/constraints.h b/dev/constraints.h index 7f573c70b..42e5a7cfd 100644 --- a/dev/constraints.h +++ b/dev/constraints.h @@ -1,5 +1,6 @@ #pragma once +#include #include // std::string #include // std::tuple, std::make_tuple #include // std::stringstream @@ -314,6 +315,7 @@ namespace sqlite_orm { case decltype(argument)::nocase: return "NOCASE"; case decltype(argument)::rtrim: return "RTRIM"; } + assert(false); } }; diff --git a/dev/row_extractor.h b/dev/row_extractor.h index 0b0ffe984..89e5b4dc5 100644 --- a/dev/row_extractor.h +++ b/dev/row_extractor.h @@ -147,7 +147,7 @@ namespace sqlite_orm { std::vector extract(const char *row_value) { if(row_value){ auto len = ::strlen(row_value); - return this->go(row_value, static_cast(len)); + return this->go(row_value, len); }else{ return {}; } @@ -161,7 +161,7 @@ namespace sqlite_orm { protected: - std::vector go(const char *bytes, int len) { + std::vector go(const char *bytes, size_t len) { if(len){ std::vector res; res.reserve(len); @@ -209,7 +209,7 @@ namespace sqlite_orm { std::vector extract(const char *row_value) { if(row_value){ auto len = ::strlen(row_value); - return this->go(row_value, static_cast(len)); + return this->go(row_value, len); }else{ return {}; } @@ -217,13 +217,13 @@ namespace sqlite_orm { std::vector extract(sqlite3_stmt *stmt, int columnIndex) { auto bytes = static_cast(sqlite3_column_blob(stmt, columnIndex)); - auto len = sqlite3_column_bytes(stmt, columnIndex); + auto len = static_cast(sqlite3_column_bytes(stmt, columnIndex)); return this->go(bytes, len); } protected: - std::vector go(const char *bytes, int len) { + std::vector go(const char *bytes, size_t len) { if(len){ std::vector res; res.reserve(len); diff --git a/dev/select_constraints.h b/dev/select_constraints.h index 7ee94856d..aec4583d2 100644 --- a/dev/select_constraints.h +++ b/dev/select_constraints.h @@ -228,7 +228,7 @@ namespace sqlite_orm { * Generic way to get DISTINCT value from any type. */ template - bool get_distinct(const T &t) { + bool get_distinct(const T &) { return false; } diff --git a/dev/static_magic.h b/dev/static_magic.h index 620ed8853..d02c7be3e 100644 --- a/dev/static_magic.h +++ b/dev/static_magic.h @@ -8,10 +8,10 @@ namespace sqlite_orm { namespace static_magic { template - auto static_if(std::true_type, T t, F f) { return t; } + auto static_if(std::true_type, T t, F) { return t; } template - auto static_if(std::false_type, T t, F f) { return f; } + auto static_if(std::false_type, T, F f) { return f; } template auto static_if(T t, F f) { return static_if(std::integral_constant{}, t, f); } diff --git a/dev/storage.h b/dev/storage.h index defbe6a76..263e8333f 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -318,7 +318,7 @@ namespace sqlite_orm { std::stringstream ss; std::vector columnNames; using columns_type_t = typename std::decay::type::columns_type; - constexpr const int columnsCount = std::tuple_size::value; + constexpr const size_t columnsCount = std::tuple_size::value; columnNames.reserve(columnsCount); tuple_helper::iterator()(fk.columns, [&columnNames, this](auto &v){ columnNames.push_back(this->impl.column_name(v)); @@ -334,7 +334,7 @@ namespace sqlite_orm { ss << ") REFERENCES "; std::vector referencesNames; using references_type_t = typename std::decay::type::references_type; - constexpr const int referencesCount = std::tuple_size::value; + constexpr const size_t referencesCount = std::tuple_size::value; referencesNames.reserve(referencesCount); { using first_reference_t = typename std::tuple_element<0, references_type_t>::type; @@ -438,7 +438,7 @@ namespace sqlite_orm { std::string escape(std::string text) { for(size_t i = 0; i < text.length(); ) { if(text[i] == '\''){ - text.insert(text.begin() + i, '\''); + text.insert(text.begin() + static_cast(i), '\''); i += 2; } else @@ -471,12 +471,12 @@ namespace sqlite_orm { } template - std::string string_from_expression(const alias_holder &holder, bool noTableName = false, bool /*escape*/ = false) { + std::string string_from_expression(const alias_holder &, bool /*noTableName*/ = false, bool /*escape*/ = false) { return T::get(); } template - std::string string_from_expression(const as_t &als, bool noTableName = false, bool /*escape*/ = false) { + std::string string_from_expression(const as_t &als, bool /*noTableName*/ = false, bool /*escape*/ = false) { auto tableAliasString = alias_extractor::get(); return this->string_from_expression(als.expression) + " AS " + tableAliasString; } @@ -667,7 +667,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const aggregate_functions::count_asterisk_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const aggregate_functions::count_asterisk_t &, bool /*noTableName*/ = false, bool /*escape*/ = false) { return this->string_from_expression(aggregate_functions::count_asterisk_without_type{}); } @@ -829,9 +829,9 @@ namespace sqlite_orm { args.emplace_back(std::move(expression)); }); ss << static_cast(f) << "("; - auto lim = int(args.size()); + const auto lim = static_cast(args.size()); for(auto i = 0; i < lim; ++i) { - ss << args[i]; + ss << args[static_cast(i)]; if(i < lim - 1) { ss << ", "; }else{ @@ -868,7 +868,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const column_pointer &c, bool noTableName = false, bool escape = false) { + std::string string_from_expression(const column_pointer &c, bool noTableName = false, bool /*escape*/ = false) { std::stringstream ss; if(!noTableName){ ss << "'" << this->impl.template find_table_name() << "'."; @@ -889,7 +889,7 @@ namespace sqlite_orm { } template - std::vector get_column_names(const internal::asterisk_t &ast) { + std::vector get_column_names(const internal::asterisk_t &) { std::vector res; res.push_back("*"); return res; @@ -898,7 +898,7 @@ namespace sqlite_orm { template std::vector get_column_names(const internal::columns_t &cols) { std::vector columnNames; - columnNames.reserve(cols.count()); + columnNames.reserve(static_cast(cols.count())); cols.for_each([&columnNames, this](auto &m) { auto columnName = this->string_from_expression(m); if(columnName.length()){ @@ -1783,7 +1783,7 @@ namespace sqlite_orm { } template - std::set> parse_table_name(const column_pointer &c) { + std::set> parse_table_name(const column_pointer &) { std::set> res; res.insert({this->impl.template find_table_name(), ""}); return res; @@ -1795,7 +1795,7 @@ namespace sqlite_orm { } template - std::set> parse_table_name(const aggregate_functions::count_asterisk_t &c) { + std::set> parse_table_name(const aggregate_functions::count_asterisk_t &) { auto tableName = this->impl.template find_table_name(); if(!tableName.empty()){ return {std::make_pair(std::move(tableName), "")}; @@ -1809,7 +1809,7 @@ namespace sqlite_orm { } template - std::set> parse_table_name(const asterisk_t &ast) { + std::set> parse_table_name(const asterisk_t &) { auto tableName = this->impl.template find_table_name(); return {std::make_pair(std::move(tableName), "")}; } diff --git a/dev/storage_impl.h b/dev/storage_impl.h index 5143219c0..77a644844 100644 --- a/dev/storage_impl.h +++ b/dev/storage_impl.h @@ -62,7 +62,7 @@ namespace sqlite_orm { break; } dbTableInfo.erase(dbColumnInfoIt); - storageTableInfo.erase(storageTableInfo.begin() + storageColumnInfoIndex); + storageTableInfo.erase(storageTableInfo.begin() + static_cast(storageColumnInfoIndex)); --storageColumnInfoIndex; }else{ diff --git a/dev/sync_schema_result.h b/dev/sync_schema_result.h index 459ffdfe8..7e206011f 100644 --- a/dev/sync_schema_result.h +++ b/dev/sync_schema_result.h @@ -51,5 +51,6 @@ namespace sqlite_orm { case sync_schema_result::new_columns_added_and_old_columns_removed: return os << "old excess columns removed and new columns added"; case sync_schema_result::dropped_and_recreated: return os << "old table dropped and recreated"; } + return os; } } diff --git a/examples/blob.cpp b/examples/blob.cpp index d4c84422d..47554369c 100644 --- a/examples/blob.cpp +++ b/examples/blob.cpp @@ -14,7 +14,7 @@ struct User { std::vector hash; // binary format }; -int main(int argc, char **argv) { +int main(int, char **) { using namespace sqlite_orm; auto storage = make_storage("blob.sqlite", make_table("users", diff --git a/examples/collate.cpp b/examples/collate.cpp index 12d1df6ec..87078ec13 100644 --- a/examples/collate.cpp +++ b/examples/collate.cpp @@ -19,7 +19,7 @@ struct Foo { int baz; }; -int main(int argc, char** argv) { +int main(int, char**) { using namespace sqlite_orm; auto storage = make_storage("collate.sqlite", diff --git a/examples/composite_key.cpp b/examples/composite_key.cpp index 07c7ede9d..9560d5d16 100644 --- a/examples/composite_key.cpp +++ b/examples/composite_key.cpp @@ -52,7 +52,7 @@ int main() { try{ // 2 and 'Drake' values will be ignored cause they are primary keys storage.insert(User{ 2, "Drake", "Singer" }); - }catch(std::system_error e){ + }catch(const std::system_error& e){ cout << "exception = " << e.what() << endl; } storage.replace(User{ 2, "The Weeknd", "Singer" }); diff --git a/examples/core_functions.cpp b/examples/core_functions.cpp index d47d0b964..2f2f56988 100644 --- a/examples/core_functions.cpp +++ b/examples/core_functions.cpp @@ -13,7 +13,7 @@ struct MarvelHero { short points; }; -int main(int argc, char **argv) { +int main(int, char **argv) { cout << "path = " << argv[0] << endl; using namespace sqlite_orm; diff --git a/examples/cross_join.cpp b/examples/cross_join.cpp index aac22dd63..c9f5f3c63 100644 --- a/examples/cross_join.cpp +++ b/examples/cross_join.cpp @@ -30,7 +30,7 @@ static auto initStorage(const std::string &path) { make_column("suit", &Suit::suit))); } -int main(int argc, char **argv) { +int main(int, char **) { using namespace DataModel; using Storage = decltype(initStorage("")); diff --git a/examples/custom_aliases.cpp b/examples/custom_aliases.cpp index beaa6888c..f0fa8ab64 100644 --- a/examples/custom_aliases.cpp +++ b/examples/custom_aliases.cpp @@ -41,7 +41,7 @@ struct CompanyNameAlias : alias_tag { } }; -int main(int argc, char* argv[]) { +int main(int, char** argv) { cout << argv[0] << endl; auto storage = make_storage("custom_aliases.sqlite", diff --git a/examples/distinct.cpp b/examples/distinct.cpp index 6d1af04db..527aa94df 100644 --- a/examples/distinct.cpp +++ b/examples/distinct.cpp @@ -28,7 +28,7 @@ auto initStorage(const std::string &path) { } using Storage = decltype(initStorage("")); -int main(int argc, char **argv) { +int main(int, char **) { Storage storage = initStorage("distinct.sqlite"); diff --git a/examples/enum_binding.cpp b/examples/enum_binding.cpp index 72e84a3a5..ab6d18b49 100644 --- a/examples/enum_binding.cpp +++ b/examples/enum_binding.cpp @@ -1,5 +1,7 @@ #include + +#include #include #include @@ -30,6 +32,7 @@ std::string GenderToString(Gender gender) { case Gender::Female:return "female"; case Gender::Male:return "male"; } + assert(false); // unreachable } /** diff --git a/examples/exists.cpp b/examples/exists.cpp index d063caf42..58069e6f3 100644 --- a/examples/exists.cpp +++ b/examples/exists.cpp @@ -41,7 +41,7 @@ struct Order { std::string agentCode; }; -int main(int argc, char **argv) { +int main(int, char **) { using namespace sqlite_orm; auto storage = make_storage("exists.sqlite", @@ -77,18 +77,18 @@ int main(int argc, char **argv) { storage.remove_all(); storage.remove_all(); - storage.replace(Agent{"A007", "Ramasundar", "Bangalore", 0.15, "077-25814763"}); - storage.replace(Agent{"A003", "Alex", "London", 0.13, "075-12458969"}); - storage.replace(Agent{"A008", "Alford", "New York", 0.12, "044-25874365"}); - storage.replace(Agent{"A011", "Ravi Kumar", "Bangalore", 0.15, "077-45625874"}); - storage.replace(Agent{"A010", "Santakumar", "Chennai", 0.14, "007-22388644"}); - storage.replace(Agent{"A012", "Lucida", "San Jose", 0.12, "044-52981425"}); - storage.replace(Agent{"A005", "Anderson", "Brisban", 0.13, "045-21447739"}); - storage.replace(Agent{"A001", "Subbarao", "Bangalore", 0.14, "077-12346674"}); - storage.replace(Agent{"A002", "Mukesh", "Mumbai", 0.11, "029-12358964"}); - storage.replace(Agent{"A006", "McDen", "London", 0.15, "078-22255588"}); - storage.replace(Agent{"A004", "Ivan", "Torento", 0.15, "008-22544166"}); - storage.replace(Agent{"A009", "Benjamin", "Hampshair", 0.11, "008-22536178"}); + storage.replace(Agent{"A007", "Ramasundar", "Bangalore", 0.15, "077-25814763", ""}); + storage.replace(Agent{"A003", "Alex", "London", 0.13, "075-12458969", ""}); + storage.replace(Agent{"A008", "Alford", "New York", 0.12, "044-25874365", ""}); + storage.replace(Agent{"A011", "Ravi Kumar", "Bangalore", 0.15, "077-45625874", ""}); + storage.replace(Agent{"A010", "Santakumar", "Chennai", 0.14, "007-22388644", ""}); + storage.replace(Agent{"A012", "Lucida", "San Jose", 0.12, "044-52981425", ""}); + storage.replace(Agent{"A005", "Anderson", "Brisban", 0.13, "045-21447739", ""}); + storage.replace(Agent{"A001", "Subbarao", "Bangalore", 0.14, "077-12346674", ""}); + storage.replace(Agent{"A002", "Mukesh", "Mumbai", 0.11, "029-12358964", ""}); + storage.replace(Agent{"A006", "McDen", "London", 0.15, "078-22255588", ""}); + storage.replace(Agent{"A004", "Ivan", "Torento", 0.15, "008-22544166", ""}); + storage.replace(Agent{"A009", "Benjamin", "Hampshair", 0.11, "008-22536178", ""}); storage.replace(Customer{"C00013", "Holmes", "London", "London", "UK", 2, 6000.00, 5000.00, 7000.00, 4000.00, "BBBBBBB", "A003"}); storage.replace(Customer{"C00001", "Micheal", "New York", "New York", "USA", 2, 3000.00, 5000.00, 2000.00, 6000.00, "CCCCCCC", "A008"}); diff --git a/examples/foreign_key.cpp b/examples/foreign_key.cpp index a5421a153..a3ef8d9d3 100644 --- a/examples/foreign_key.cpp +++ b/examples/foreign_key.cpp @@ -23,7 +23,7 @@ struct Track { std::unique_ptr trackArtist; // must map to &Artist::artistId }; -int main(int argc, char **argv) { +int main(int, char **argv) { cout << "path = " << argv[0] << endl; using namespace sqlite_orm; @@ -57,7 +57,7 @@ int main(int argc, char **argv) { // does not correspond to row in the artist table. storage.replace(Track{ 14, "Mr. Bojangles", std::make_unique(3) }); assert(0); - }catch(std::system_error e) { + }catch(const std::system_error& e) { cout << e.what() << endl; } @@ -71,7 +71,7 @@ int main(int argc, char **argv) { try{ storage.update_all(set(assign(&Track::trackArtist, 3)), where(is_equal(&Track::trackName, "Mr. Bojangles"))); assert(0); - }catch(std::system_error e) { + }catch(const std::system_error& e) { cout << e.what() << endl; } @@ -91,7 +91,7 @@ int main(int argc, char **argv) { // the track table contains a row that refer to it. storage.remove_all(where(is_equal(&Artist::artistName, "Frank Sinatra"))); assert(0); - }catch(std::system_error e) { + }catch(const std::system_error& e) { cout << e.what() << endl; } @@ -105,7 +105,7 @@ int main(int argc, char **argv) { // exists records in the track table that refer to it. storage.update_all(set(assign(&Artist::artistId, 4)), where(is_equal(&Artist::artistName, "Dean Martin"))); assert(0); - }catch(std::system_error e) { + }catch(const std::system_error& e) { cout << e.what() << endl; } @@ -197,7 +197,7 @@ int main(int argc, char **argv) { try{ storage.remove_all(where(c(&Artist::artistName) == "Sammy Davis Jr.")); assert(0); - }catch(std::system_error e) { + }catch(const std::system_error& e) { cout << e.what() << endl; } diff --git a/examples/group_by.cpp b/examples/group_by.cpp index 26a7e21d0..9831917cc 100644 --- a/examples/group_by.cpp +++ b/examples/group_by.cpp @@ -17,7 +17,7 @@ struct Employee { double salary; }; -int main(int argc, char **argv) { +int main(int, char **) { using namespace sqlite_orm; auto storage = make_storage("group_by.sqlite", diff --git a/examples/in_memory.cpp b/examples/in_memory.cpp index ee41ef635..22737b333 100644 --- a/examples/in_memory.cpp +++ b/examples/in_memory.cpp @@ -15,7 +15,7 @@ struct RapArtist { std::string name; }; -int main(int argc, char **argv) { +int main(int, char **) { auto storage = make_storage(":memory:", make_table("rap_artists", diff --git a/examples/index.cpp b/examples/index.cpp index 8c9c2a23a..fb5c03a39 100644 --- a/examples/index.cpp +++ b/examples/index.cpp @@ -25,7 +25,7 @@ auto storage = make_storage("index.sqlite", make_column("last_name", &Contract::lastName), make_column("email", &Contract::email))); -int main(int argc, char **argv) { +int main(int, char **) { storage.sync_schema(); storage.remove_all(); @@ -41,7 +41,7 @@ int main(int argc, char **argv) { "Doe", "john.doe@sqlitetutorial.net", }); - }catch(std::system_error e){ + }catch(const std::system_error& e){ cout << e.what() << endl; } std::vector moreContracts = { diff --git a/examples/insert.cpp b/examples/insert.cpp index d06809063..b5dd89f4c 100644 --- a/examples/insert.cpp +++ b/examples/insert.cpp @@ -23,7 +23,7 @@ struct DetailedEmployee : public Employee { std::string birthDate; }; -int main(int argc, char **argv) { +int main(int, char **) { using namespace sqlite_orm; auto storage = make_storage("insert.sqlite", diff --git a/examples/iteration.cpp b/examples/iteration.cpp index c3bcadcee..11253169b 100644 --- a/examples/iteration.cpp +++ b/examples/iteration.cpp @@ -12,7 +12,7 @@ struct MarvelHero { std::string abilities; }; -int main(int argc, char **argv) { +int main(int, char **) { using namespace sqlite_orm; auto storage = make_storage("iteration.sqlite", make_table("marvel", @@ -57,7 +57,7 @@ int main(int argc, char **argv) { } std::vector heroesByAlgorithm; - heroesByAlgorithm.reserve(storage.count()); + heroesByAlgorithm.reserve(static_cast(storage.count())); { auto view = storage.iterate(); std::copy(view.begin(), diff --git a/examples/key_value.cpp b/examples/key_value.cpp index 821701d24..090286175 100644 --- a/examples/key_value.cpp +++ b/examples/key_value.cpp @@ -56,7 +56,7 @@ int storedKeysCount() { return getStorage().count(); } -int main(int argc, char **argv) { +int main(int, char **argv) { cout << argv[0] << endl; // to know executable path in case if you need to access sqlite directly from sqlite client diff --git a/examples/left_and_inner_join.cpp b/examples/left_and_inner_join.cpp index 7cf3a272b..2a7fd64fe 100644 --- a/examples/left_and_inner_join.cpp +++ b/examples/left_and_inner_join.cpp @@ -57,7 +57,7 @@ inline auto initStorage(const std::string &path){ make_column("UnitPrice", &Track::unitPrice))); } -int main(int argc, char **argv) { +int main(int, char **) { auto storage = initStorage("chinook.db"); diff --git a/examples/multi_table_select.cpp b/examples/multi_table_select.cpp index bbea3c51d..62f6500d4 100644 --- a/examples/multi_table_select.cpp +++ b/examples/multi_table_select.cpp @@ -23,7 +23,7 @@ struct ReqDetail { double itemCost; }; -int main(int argc, char **argv) { +int main(int, char **) { using namespace sqlite_orm; auto storage = make_storage("multi_table_select.sqlite", diff --git a/examples/nullable_enum_binding.cpp b/examples/nullable_enum_binding.cpp index 490f72dc2..95e183646 100644 --- a/examples/nullable_enum_binding.cpp +++ b/examples/nullable_enum_binding.cpp @@ -1,4 +1,5 @@ +#include #include #include #include @@ -25,6 +26,7 @@ std::unique_ptr GenderToString(Gender gender) { case Gender::Male:return std::make_unique("male"); case Gender::None:return {}; } + assert(false); } std::unique_ptr GenderFromString(const std::string &s) { @@ -104,7 +106,7 @@ namespace sqlite_orm { }; } -int main(int argc, char **argv) { +int main(int, char **) { using namespace sqlite_orm; auto storage = make_storage("nullable_enum.sqlite", make_table("users", diff --git a/examples/private_class_members.cpp b/examples/private_class_members.cpp index 0b29fdae3..6780cd5d0 100644 --- a/examples/private_class_members.cpp +++ b/examples/private_class_members.cpp @@ -43,7 +43,7 @@ class Player { } }; -int main(int argc, char **argv) { +int main(int, char **) { using namespace sqlite_orm; auto storage = make_storage("private.sqlite", make_table("players", diff --git a/examples/select.cpp b/examples/select.cpp index 917c69391..600f6a976 100644 --- a/examples/select.cpp +++ b/examples/select.cpp @@ -19,7 +19,7 @@ using namespace sqlite_orm; using std::cout; using std::endl; -int main(int argc, char **argv) { +int main(int, char **) { auto storage = make_storage("select.sqlite", make_table("COMPANY", make_column("ID", &Employee::id, primary_key()), diff --git a/examples/subentities.cpp b/examples/subentities.cpp index 6703f6b55..3309b5559 100644 --- a/examples/subentities.cpp +++ b/examples/subentities.cpp @@ -79,20 +79,20 @@ Student getStudent(int studentId) { return res; // must be moved automatically by compiler } -int main(int argc, char **argv) { +int main(int, char **) { decltype(Student::id) mikeId; decltype(Student::id) annaId; { storage.sync_schema(); // create tables if they don't exist - Student mike{ -1, "Mike", 123 }; // create student named `Mike` without marks and without id + Student mike{ -1, "Mike", 123, {} }; // create student named `Mike` without marks and without id mike.marks = { 3, 4, 5 }; mike.id = addStudent(mike); mikeId = mike.id; // also let's create another students with marks.. - Student anna{ -1, "Anna", 555 }; + Student anna{ -1, "Anna", 555, {} }; anna.marks.push_back(6); anna.marks.push_back(7); anna.id = addStudent(anna); diff --git a/examples/subquery.cpp b/examples/subquery.cpp index d0e991c7a..37769123e 100644 --- a/examples/subquery.cpp +++ b/examples/subquery.cpp @@ -38,7 +38,7 @@ struct JobHistory { decltype(Employee::departmentId) departmentId; }; -int main(int argc, char **argv) { +int main(int, char **) { using namespace sqlite_orm; auto storage = make_storage("subquery.sqlite", make_table("employees", diff --git a/examples/synchronous.cpp b/examples/synchronous.cpp index 7676850ff..6c86026ef 100644 --- a/examples/synchronous.cpp +++ b/examples/synchronous.cpp @@ -13,7 +13,7 @@ struct Query uint16_t type; }; -int main(int argc, char** argv) { +int main(int, char**) { using namespace sqlite_orm; diff --git a/examples/unique.cpp b/examples/unique.cpp index 82ce29f41..205bad79d 100644 --- a/examples/unique.cpp +++ b/examples/unique.cpp @@ -14,7 +14,7 @@ struct Entry { std::unique_ptr nullableColumn; }; -int main(int argc, char **argv) { +int main(int, char **) { using namespace sqlite_orm; auto storage = make_storage("unique.sqlite", make_table("unique_test", @@ -34,7 +34,7 @@ int main(int argc, char **argv) { auto id2 = storage.insert(Entry{ 0, sameString, std::make_unique("I got you") }); cout << "inserted " << storage.dump(storage.get(id2)) << endl; - } catch (std::system_error e) { + } catch (const std::system_error& e) { cerr << e.what() << endl; } diff --git a/examples/update.cpp b/examples/update.cpp index 3f26ea049..6bd36404f 100644 --- a/examples/update.cpp +++ b/examples/update.cpp @@ -32,7 +32,7 @@ using Storage = decltype(initStorage("")); static std::unique_ptr stor; -int main(int argc, char **argv) { +int main(int, char **) { stor = std::make_unique(initStorage("update.sqlite")); stor->sync_schema(); stor->remove_all(); diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index b398f7a12..9f333dcf6 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -268,10 +268,10 @@ namespace sqlite_orm { namespace static_magic { template - auto static_if(std::true_type, T t, F f) { return t; } + auto static_if(std::true_type, T t, F) { return t; } template - auto static_if(std::false_type, T t, F f) { return f; } + auto static_if(std::false_type, T, F f) { return f; } template auto static_if(T t, F f) { return static_if(std::integral_constant{}, t, f); } @@ -400,6 +400,7 @@ namespace sqlite_orm { } #pragma once +#include #include // std::string #include // std::tuple, std::make_tuple #include // std::stringstream @@ -714,6 +715,7 @@ namespace sqlite_orm { case decltype(argument)::nocase: return "NOCASE"; case decltype(argument)::rtrim: return "RTRIM"; } + assert(false); } }; @@ -3697,7 +3699,7 @@ namespace sqlite_orm { * Generic way to get DISTINCT value from any type. */ template - bool get_distinct(const T &t) { + bool get_distinct(const T &) { return false; } @@ -4326,7 +4328,7 @@ namespace sqlite_orm { std::vector extract(const char *row_value) { if(row_value){ auto len = ::strlen(row_value); - return this->go(row_value, static_cast(len)); + return this->go(row_value, len); }else{ return {}; } @@ -4340,7 +4342,7 @@ namespace sqlite_orm { protected: - std::vector go(const char *bytes, int len) { + std::vector go(const char *bytes, size_t len) { if(len){ std::vector res; res.reserve(len); @@ -4388,7 +4390,7 @@ namespace sqlite_orm { std::vector extract(const char *row_value) { if(row_value){ auto len = ::strlen(row_value); - return this->go(row_value, static_cast(len)); + return this->go(row_value, len); }else{ return {}; } @@ -4396,13 +4398,13 @@ namespace sqlite_orm { std::vector extract(sqlite3_stmt *stmt, int columnIndex) { auto bytes = static_cast(sqlite3_column_blob(stmt, columnIndex)); - auto len = sqlite3_column_bytes(stmt, columnIndex); + auto len = static_cast(sqlite3_column_bytes(stmt, columnIndex)); return this->go(bytes, len); } protected: - std::vector go(const char *bytes, int len) { + std::vector go(const char *bytes, size_t len) { if(len){ std::vector res; res.reserve(len); @@ -4538,6 +4540,7 @@ namespace sqlite_orm { case sync_schema_result::new_columns_added_and_old_columns_removed: return os << "old excess columns removed and new columns added"; case sync_schema_result::dropped_and_recreated: return os << "old table dropped and recreated"; } + return os; } } #pragma once @@ -5340,8 +5343,8 @@ namespace sqlite_orm { using member_pointer_t = typename column_type::member_pointer_t; using getter_type = typename column_type::getter_type; using setter_type = typename column_type::setter_type; - - // GCC has bug that reported in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64095 so static_if must have at lease one input + // Make static_if have at least one input as a workaround for GCC bug: + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64095 if(!res){ static_if{}>([&res, &obj, &col](const C& c){ if(compare_any(col.member_pointer, c)){ @@ -5674,7 +5677,7 @@ namespace sqlite_orm { break; } dbTableInfo.erase(dbColumnInfoIt); - storageTableInfo.erase(storageTableInfo.begin() + storageColumnInfoIndex); + storageTableInfo.erase(storageTableInfo.begin() + static_cast(storageColumnInfoIndex)); --storageColumnInfoIndex; }else{ @@ -6838,7 +6841,7 @@ namespace sqlite_orm { std::stringstream ss; std::vector columnNames; using columns_type_t = typename std::decay::type::columns_type; - constexpr const int columnsCount = std::tuple_size::value; + constexpr const size_t columnsCount = std::tuple_size::value; columnNames.reserve(columnsCount); tuple_helper::iterator()(fk.columns, [&columnNames, this](auto &v){ columnNames.push_back(this->impl.column_name(v)); @@ -6854,7 +6857,7 @@ namespace sqlite_orm { ss << ") REFERENCES "; std::vector referencesNames; using references_type_t = typename std::decay::type::references_type; - constexpr const int referencesCount = std::tuple_size::value; + constexpr const size_t referencesCount = std::tuple_size::value; referencesNames.reserve(referencesCount); { using first_reference_t = typename std::tuple_element<0, references_type_t>::type; @@ -6958,7 +6961,7 @@ namespace sqlite_orm { std::string escape(std::string text) { for(size_t i = 0; i < text.length(); ) { if(text[i] == '\''){ - text.insert(text.begin() + i, '\''); + text.insert(text.begin() + static_cast(i), '\''); i += 2; } else @@ -6991,12 +6994,12 @@ namespace sqlite_orm { } template - std::string string_from_expression(const alias_holder &holder, bool noTableName = false, bool /*escape*/ = false) { + std::string string_from_expression(const alias_holder &, bool /*noTableName*/ = false, bool /*escape*/ = false) { return T::get(); } template - std::string string_from_expression(const as_t &als, bool noTableName = false, bool /*escape*/ = false) { + std::string string_from_expression(const as_t &als, bool /*noTableName*/ = false, bool /*escape*/ = false) { auto tableAliasString = alias_extractor::get(); return this->string_from_expression(als.expression) + " AS " + tableAliasString; } @@ -7187,7 +7190,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const aggregate_functions::count_asterisk_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const aggregate_functions::count_asterisk_t &, bool /*noTableName*/ = false, bool /*escape*/ = false) { return this->string_from_expression(aggregate_functions::count_asterisk_without_type{}); } @@ -7349,9 +7352,9 @@ namespace sqlite_orm { args.emplace_back(std::move(expression)); }); ss << static_cast(f) << "("; - auto lim = int(args.size()); + const auto lim = static_cast(args.size()); for(auto i = 0; i < lim; ++i) { - ss << args[i]; + ss << args[static_cast(i)]; if(i < lim - 1) { ss << ", "; }else{ @@ -7388,7 +7391,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const column_pointer &c, bool noTableName = false, bool escape = false) { + std::string string_from_expression(const column_pointer &c, bool noTableName = false, bool /*escape*/ = false) { std::stringstream ss; if(!noTableName){ ss << "'" << this->impl.template find_table_name() << "'."; @@ -7409,7 +7412,7 @@ namespace sqlite_orm { } template - std::vector get_column_names(const internal::asterisk_t &ast) { + std::vector get_column_names(const internal::asterisk_t &) { std::vector res; res.push_back("*"); return res; @@ -7418,7 +7421,7 @@ namespace sqlite_orm { template std::vector get_column_names(const internal::columns_t &cols) { std::vector columnNames; - columnNames.reserve(cols.count()); + columnNames.reserve(static_cast(cols.count())); cols.for_each([&columnNames, this](auto &m) { auto columnName = this->string_from_expression(m); if(columnName.length()){ @@ -8303,7 +8306,7 @@ namespace sqlite_orm { } template - std::set> parse_table_name(const column_pointer &c) { + std::set> parse_table_name(const column_pointer &) { std::set> res; res.insert({this->impl.template find_table_name(), ""}); return res; @@ -8315,7 +8318,7 @@ namespace sqlite_orm { } template - std::set> parse_table_name(const aggregate_functions::count_asterisk_t &c) { + std::set> parse_table_name(const aggregate_functions::count_asterisk_t &) { auto tableName = this->impl.template find_table_name(); if(!tableName.empty()){ return {std::make_pair(std::move(tableName), "")}; @@ -8329,7 +8332,7 @@ namespace sqlite_orm { } template - std::set> parse_table_name(const asterisk_t &ast) { + std::set> parse_table_name(const asterisk_t &) { auto tableName = this->impl.template find_table_name(); return {std::make_pair(std::move(tableName), "")}; } diff --git a/tests/tests.cpp b/tests/tests.cpp index 008c0fa9b..495dad3e6 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -28,7 +28,7 @@ void testCast() { make_column("score_str", &Student::scoreString))); storage.sync_schema(); - storage.replace(Student{1, 10.1, "14.5"}); + storage.replace(Student{1, 10.1f, "14.5"}); { auto rows = storage.select(columns(cast(&Student::scoreFloat), cast(&Student::scoreString))); @@ -656,7 +656,7 @@ void testExplicitInsert() { try { storage.insert(user4, columns(&User::name)); throw std::runtime_error("Must not fire"); - } catch (std::system_error e) { + } catch (const std::system_error&) { // cout << e.what() << endl; } } @@ -705,14 +705,14 @@ void testExplicitInsert() { try { storage.insert(visit3, columns(&Visit::id)); throw std::runtime_error("Must not fire"); - } catch (std::system_error e) { + } catch (const std::system_error&) { // cout << e.what() << endl; } try { storage.insert(visit3, columns(&Visit::setId)); throw std::runtime_error("Must not fire"); - } catch (std::system_error e) { + } catch (const std::system_error&) { // cout << e.what() << endl; } } @@ -741,7 +741,7 @@ void testCustomCollate() { storage.create_collation("ototo", [](int, const void *lhs, int, const void *rhs){ return strcmp((const char*)lhs, (const char*)rhs); }); - storage.create_collation("alwaysequal", [](int, const void *lhs, int, const void *rhs){ + storage.create_collation("alwaysequal", [](int, const void *, int, const void *){ return 0; }); auto rows = storage.select(&Item::name, where(is_equal(&Item::name, "Mercury").collate("ototo"))); @@ -754,12 +754,12 @@ void testCustomCollate() { storage.create_collation("ototo", {}); try { rows = storage.select(&Item::name, where(is_equal(&Item::name, "Mercury").collate("ototo"))); - } catch (std::system_error e) { + } catch (const std::system_error& e) { cout << e.what() << endl; } try { rows = storage.select(&Item::name, where(is_equal(&Item::name, "Mercury").collate("ototo2"))); - } catch (std::system_error e) { + } catch (const std::system_error& e) { cout << e.what() << endl; } rows = storage.select(&Item::name, where(is_equal(&Item::name, "Mercury").collate("alwaysequal")), @@ -767,7 +767,7 @@ void testCustomCollate() { rows = storage.select(&Item::name, where(is_equal(&Item::name, "Mercury").collate("alwaysequal")), order_by(&Item::name).collate("alwaysequal")); - assert(rows.size() == storage.count()); + assert(rows.size() == static_cast(storage.count())); } void testVacuum() { @@ -870,7 +870,7 @@ void testOperators() { c(&Object::nameLen) / c(&Object::number), c(&Object::nameLen) / 2)); - for(auto i = 0; i < rows.size(); ++i) { + for(size_t i = 0; i < rows.size(); ++i) { auto &row = rows[i]; auto &name = names[i]; assert(std::get<0>(row) == name + suffix); @@ -912,14 +912,14 @@ void testOperators() { &Object::nameLen % c(&Object::number), c(&Object::nameLen) % c(&Object::number), c(&Object::nameLen) % 5)); - for(auto i = 0; i < rows2.size(); ++i) { + for(size_t i = 0; i < rows2.size(); ++i) { auto &row = rows2[i]; auto &name = names[i]; - assert(std::get<0>(row) == name.length() % number); + assert(std::get<0>(row) == static_cast(name.length()) % number); assert(std::get<1>(row) == std::get<0>(row)); assert(std::get<2>(row) == std::get<1>(row)); assert(std::get<3>(row) == std::get<2>(row)); - assert(std::get<4>(row) == name.length() % 5); + assert(std::get<4>(row) == static_cast(name.length()) % 5); } } @@ -1314,7 +1314,7 @@ void testSyncSchema() { } // assert count first cause we will be asserting row by row next.. - assert(storage.count() == usersToInsert.size()); + assert(static_cast(storage.count()) == usersToInsert.size()); // now we create new storage with partial schema.. auto newStorage = make_storage(filename, @@ -1338,7 +1338,7 @@ void testSyncSchema() { assert(usersFromDb.size() == usersToInsert.size()); - for(auto i = 0; i < usersFromDb.size(); ++i) { + for(size_t i = 0; i < usersFromDb.size(); ++i) { auto &userFromDb = usersFromDb[i]; auto &oldUser = usersToInsert[i]; assert(userFromDb.id == oldUser.id); @@ -1654,7 +1654,7 @@ void testInsert() { auto countBefore = storage.count(); storage.insert_range(initList.begin(), initList.end()); - assert(storage.count() == countBefore + initList.size()); + assert(storage.count() == countBefore + static_cast(initList.size())); // test empty container @@ -1897,13 +1897,13 @@ void testBlob() { }; using byte = char; - auto generateData = [](int size) -> byte* { + auto generateData = [](size_t size) -> byte* { auto data = (byte*)::malloc(size * sizeof(byte)); - for (int i = 0; i < size; ++i) { + for (int i = 0; i < static_cast(size); ++i) { if ((i+1) % 10 == 0) { data[i] = 0; } else { - data[i] = (rand() % 100) + 1; + data[i] = static_cast((rand() % 100) + 1); } } return data; @@ -1915,7 +1915,7 @@ void testBlob() { storage.sync_schema(); storage.remove_all(); - auto size = 100; + size_t size = 100; auto data = generateData(size); // write data @@ -1988,7 +1988,7 @@ void testDefaultValue() { make_column("Age", &User::age), make_column("Email", &User::email, default_value("example@email.com")))); storage2.sync_schema(); - storage2.insert(User{0, "Tom", 15}); + storage2.insert(User{0, "Tom", 15, ""}); } // after #18 @@ -2109,7 +2109,7 @@ void testSynchronous() { try{ storage.pragma.synchronous(newValue); throw std::runtime_error("Must not fire"); - }catch(std::system_error) { + }catch(const std::system_error&) { // Safety level may not be changed inside a transaction assert(storage.pragma.synchronous() == value); } @@ -2285,11 +2285,11 @@ void testRowId() { _rowid_(), &SimpleTable::letter, &SimpleTable::desc)); - for(auto i = 0; i < rows.size(); ++i) { + for(size_t i = 0; i < rows.size(); ++i) { auto &row = rows[i]; assert(std::get<0>(row) == std::get<1>(row)); assert(std::get<1>(row) == std::get<2>(row)); - assert(std::get<2>(row) == i + 1); + assert(std::get<2>(row) == static_cast(i + 1)); assert(std::get<2>(row) == std::get<3>(row)); assert(std::get<3>(row) == std::get<4>(row)); assert(std::get<4>(row) == std::get<5>(row)); @@ -2343,7 +2343,7 @@ void testWhere() { assert(users5.size() == 0); } -int main(int argc, char **argv) { +int main(int, char **) { cout << "version = " << make_storage("").libversion() << endl; From 841678c651dc96d434750dabd2141368141284ee Mon Sep 17 00:00:00 2001 From: Matt Kline Date: Fri, 26 Apr 2019 11:01:05 -0700 Subject: [PATCH 078/232] throw instead of asserting on invalid enum outside test.cpp These could be built with NDEBUG, etc. Keeping assert(false) for unreachable spots in tests.cpp, since that must be built with assertions. --- dev/constraints.h | 2 +- examples/enum_binding.cpp | 2 +- examples/nullable_enum_binding.cpp | 2 +- include/sqlite_orm/sqlite_orm.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dev/constraints.h b/dev/constraints.h index 42e5a7cfd..ef375ff3e 100644 --- a/dev/constraints.h +++ b/dev/constraints.h @@ -315,7 +315,7 @@ namespace sqlite_orm { case decltype(argument)::nocase: return "NOCASE"; case decltype(argument)::rtrim: return "RTRIM"; } - assert(false); + throw std::domain_error("Invalid collate_argument enum"); } }; diff --git a/examples/enum_binding.cpp b/examples/enum_binding.cpp index ab6d18b49..5040eb4f4 100644 --- a/examples/enum_binding.cpp +++ b/examples/enum_binding.cpp @@ -32,7 +32,7 @@ std::string GenderToString(Gender gender) { case Gender::Female:return "female"; case Gender::Male:return "male"; } - assert(false); // unreachable + throw std::domain_error("Invalid Gender enum"); } /** diff --git a/examples/nullable_enum_binding.cpp b/examples/nullable_enum_binding.cpp index 95e183646..7c07085d9 100644 --- a/examples/nullable_enum_binding.cpp +++ b/examples/nullable_enum_binding.cpp @@ -26,7 +26,7 @@ std::unique_ptr GenderToString(Gender gender) { case Gender::Male:return std::make_unique("male"); case Gender::None:return {}; } - assert(false); + throw std::domain_error("Invalid Gender enum"); } std::unique_ptr GenderFromString(const std::string &s) { diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 9f333dcf6..0c0ab9a98 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -715,7 +715,7 @@ namespace sqlite_orm { case decltype(argument)::nocase: return "NOCASE"; case decltype(argument)::rtrim: return "RTRIM"; } - assert(false); + throw std::domain_error("Invalid collate_argument enum"); } }; From d85b38e8b90705fecd7233fa7613a89fc0a0d805 Mon Sep 17 00:00:00 2001 From: Matt Kline Date: Fri, 26 Apr 2019 16:36:05 -0700 Subject: [PATCH 079/232] examples, dev/constraints.h: Remove #include It's no longer needed, given the previous commit that throws instead. --- dev/constraints.h | 1 - examples/enum_binding.cpp | 1 - examples/nullable_enum_binding.cpp | 1 - include/sqlite_orm/sqlite_orm.h | 1 - 4 files changed, 4 deletions(-) diff --git a/dev/constraints.h b/dev/constraints.h index ef375ff3e..10715d7f6 100644 --- a/dev/constraints.h +++ b/dev/constraints.h @@ -1,6 +1,5 @@ #pragma once -#include #include // std::string #include // std::tuple, std::make_tuple #include // std::stringstream diff --git a/examples/enum_binding.cpp b/examples/enum_binding.cpp index 5040eb4f4..ad094da23 100644 --- a/examples/enum_binding.cpp +++ b/examples/enum_binding.cpp @@ -1,7 +1,6 @@ #include -#include #include #include diff --git a/examples/nullable_enum_binding.cpp b/examples/nullable_enum_binding.cpp index 7c07085d9..7467ccdb1 100644 --- a/examples/nullable_enum_binding.cpp +++ b/examples/nullable_enum_binding.cpp @@ -1,5 +1,4 @@ -#include #include #include #include diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 0c0ab9a98..d3e26e732 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -400,7 +400,6 @@ namespace sqlite_orm { } #pragma once -#include #include // std::string #include // std::tuple, std::make_tuple #include // std::stringstream From ac5574621ab340c69a135318371937fdd035965a Mon Sep 17 00:00:00 2001 From: fnc12 Date: Tue, 30 Apr 2019 09:55:21 +0300 Subject: [PATCH 080/232] added is_bindable --- dev/statement_binder.h | 66 ++++++++++----------------- dev/storage.h | 2 +- dev/view.h | 12 ++--- include/sqlite_orm/sqlite_orm.h | 80 +++++++++++++-------------------- tests/static_tests.cpp | 22 +++++++++ 5 files changed, 81 insertions(+), 101 deletions(-) diff --git a/dev/statement_binder.h b/dev/statement_binder.h index df2066f89..c924e0cd4 100644 --- a/dev/statement_binder.h +++ b/dev/statement_binder.h @@ -1,13 +1,14 @@ #pragma once #include -#include // std::enable_if_t, std::is_arithmetic, std::is_same +#include // std::enable_if_t, std::is_arithmetic, std::is_same, std::true_type, std::false_type #include // std::string, std::wstring #ifndef SQLITE_ORM_OMITS_CODECVT #include // std::wstring_convert, std::codecvt_utf8_utf16 #endif // SQLITE_ORM_OMITS_CODECVT #include // std::vector #include // std::nullptr_t +#include // std::declval #include "is_std_ptr.h" @@ -17,19 +18,13 @@ namespace sqlite_orm { * Helper class used for binding fields to sqlite3 statements. */ template - struct statement_binder { - int bind(sqlite3_stmt *stmt, int index, const V &value); - }; + struct statement_binder; /** * Specialization for arithmetic types. */ template - struct statement_binder< - V, - std::enable_if_t::value> - > - { + struct statement_binder::value>> { int bind(sqlite3_stmt *stmt, int index, const V &value) { return bind(stmt, index, value, tag()); } @@ -55,15 +50,7 @@ namespace sqlite_orm { * Specialization for std::string and C-string. */ template - struct statement_binder< - V, - std::enable_if_t< - std::is_same::value - || - std::is_same::value - > - > - { + struct statement_binder::value || std::is_same::value>> { int bind(sqlite3_stmt *stmt, int index, const V &value) { return sqlite3_bind_text(stmt, index, string_data(value), -1, SQLITE_TRANSIENT); } @@ -77,20 +64,13 @@ namespace sqlite_orm { return s; } }; + #ifndef SQLITE_ORM_OMITS_CODECVT /** * Specialization for std::wstring and C-wstring. */ template - struct statement_binder< - V, - std::enable_if_t< - std::is_same::value - || - std::is_same::value - > - > - { + struct statement_binder::value || std::is_same::value>> { int bind(sqlite3_stmt *stmt, int index, const V &value) { std::wstring_convert> converter; std::string utf8Str = converter.to_bytes(value); @@ -98,26 +78,19 @@ namespace sqlite_orm { } }; #endif // SQLITE_ORM_OMITS_CODECVT + /** * Specialization for std::nullptr_t. */ template - struct statement_binder< - V, - std::enable_if_t::value> - > - { + struct statement_binder::value>> { int bind(sqlite3_stmt *stmt, int index, const V &) { return sqlite3_bind_null(stmt, index); } }; template - struct statement_binder< - V, - std::enable_if_t::value> - > - { + struct statement_binder::value>> { using value_type = typename V::element_type; int bind(sqlite3_stmt *stmt, int index, const V &value) { @@ -133,11 +106,7 @@ namespace sqlite_orm { * Specialization for optional type (std::vector). */ template - struct statement_binder< - V, - std::enable_if_t>::value> - > - { + struct statement_binder>::value>> { int bind(sqlite3_stmt *stmt, int index, const V &value) { if (value.size()) { return sqlite3_bind_blob(stmt, index, (const void *)&value.front(), int(value.size()), SQLITE_TRANSIENT); @@ -146,4 +115,17 @@ namespace sqlite_orm { } } }; + + namespace internal { + + // got it from here https://stackoverflow.com/questions/44229676/how-to-decide-if-a-template-specialization-exist + + template + std::true_type is_bindable_impl(T *); + + std::false_type is_bindable_impl(...); + + template + using is_bindable = decltype(is_bindable_impl(std::declval*>())); + } } diff --git a/dev/storage.h b/dev/storage.h index 08501b281..65b656413 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -2247,7 +2247,7 @@ namespace sqlite_orm { /** * Select a single column into std::vector or multiple columns into std::vector>. * For a single column use `auto rows = storage.select(&User::id, where(...)); - * For multicolumns user `auto rows = storage.select(columns(&User::id, &User::name), where(...)); + * For multicolumns use `auto rows = storage.select(columns(&User::id, &User::name), where(...)); */ template< class T, diff --git a/dev/view.h b/dev/view.h index 3fe55fa57..cdb237b5f 100644 --- a/dev/view.h +++ b/dev/view.h @@ -8,6 +8,7 @@ #include // std::ptrdiff_t #include // std::make_error_code #include // std::system_error +#include // std::tuple, std::make_tuple #include "database_connection.h" #include "row_extractor.h" @@ -25,17 +26,12 @@ namespace sqlite_orm { storage_type &storage; std::shared_ptr connection; + std::tuple args; - const std::string query; - - view_t(storage_type &stor, decltype(connection) conn, Args&& ...args): + view_t(storage_type &stor, decltype(connection) conn, Args&& ...args_): storage(stor), connection(std::move(conn)), - query([&args..., &stor]{ - std::string q; - stor.template generate_select_asterisk(&q, std::forward(args)...); - return q; - }()){} + args(std::make_tuple(std::forward>(args_)...)){} struct iterator_t { protected: diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 285b80e45..d11d4d888 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -3988,13 +3988,14 @@ namespace sqlite_orm { #pragma once #include -#include // std::enable_if_t, std::is_arithmetic, std::is_same +#include // std::enable_if_t, std::is_arithmetic, std::is_same, std::true_type, std::false_type #include // std::string, std::wstring #ifndef SQLITE_ORM_OMITS_CODECVT #include // std::wstring_convert, std::codecvt_utf8_utf16 #endif // SQLITE_ORM_OMITS_CODECVT #include // std::vector #include // std::nullptr_t +#include // std::declval // #include "is_std_ptr.h" @@ -4005,19 +4006,15 @@ namespace sqlite_orm { * Helper class used for binding fields to sqlite3 statements. */ template - struct statement_binder { + struct statement_binder/* { int bind(sqlite3_stmt *stmt, int index, const V &value); - }; + }*/; /** * Specialization for arithmetic types. */ template - struct statement_binder< - V, - std::enable_if_t::value> - > - { + struct statement_binder::value>> { int bind(sqlite3_stmt *stmt, int index, const V &value) { return bind(stmt, index, value, tag()); } @@ -4043,15 +4040,7 @@ namespace sqlite_orm { * Specialization for std::string and C-string. */ template - struct statement_binder< - V, - std::enable_if_t< - std::is_same::value - || - std::is_same::value - > - > - { + struct statement_binder::value || std::is_same::value>> { int bind(sqlite3_stmt *stmt, int index, const V &value) { return sqlite3_bind_text(stmt, index, string_data(value), -1, SQLITE_TRANSIENT); } @@ -4065,20 +4054,13 @@ namespace sqlite_orm { return s; } }; + #ifndef SQLITE_ORM_OMITS_CODECVT /** * Specialization for std::wstring and C-wstring. */ template - struct statement_binder< - V, - std::enable_if_t< - std::is_same::value - || - std::is_same::value - > - > - { + struct statement_binder::value || std::is_same::value>> { int bind(sqlite3_stmt *stmt, int index, const V &value) { std::wstring_convert> converter; std::string utf8Str = converter.to_bytes(value); @@ -4086,26 +4068,19 @@ namespace sqlite_orm { } }; #endif // SQLITE_ORM_OMITS_CODECVT + /** * Specialization for std::nullptr_t. */ template - struct statement_binder< - V, - std::enable_if_t::value> - > - { + struct statement_binder::value>> { int bind(sqlite3_stmt *stmt, int index, const V &) { return sqlite3_bind_null(stmt, index); } }; template - struct statement_binder< - V, - std::enable_if_t::value> - > - { + struct statement_binder::value>> { using value_type = typename V::element_type; int bind(sqlite3_stmt *stmt, int index, const V &value) { @@ -4121,11 +4096,7 @@ namespace sqlite_orm { * Specialization for optional type (std::vector). */ template - struct statement_binder< - V, - std::enable_if_t>::value> - > - { + struct statement_binder>::value>> { int bind(sqlite3_stmt *stmt, int index, const V &value) { if (value.size()) { return sqlite3_bind_blob(stmt, index, (const void *)&value.front(), int(value.size()), SQLITE_TRANSIENT); @@ -4134,6 +4105,19 @@ namespace sqlite_orm { } } }; + + namespace internal { + + // got it from here https://stackoverflow.com/questions/44229676/how-to-decide-if-a-template-specialization-exist + + template + std::true_type is_bindable_impl(T *); + + std::false_type is_bindable_impl(...); + + template + using is_bindable = decltype(is_bindable_impl(std::declval*>())); + } } #pragma once @@ -6593,6 +6577,7 @@ namespace sqlite_orm { #include // std::ptrdiff_t #include // std::make_error_code #include // std::system_error +#include // std::tuple, std::make_tuple // #include "database_connection.h" @@ -6614,17 +6599,12 @@ namespace sqlite_orm { storage_type &storage; std::shared_ptr connection; + std::tuple args; - const std::string query; - - view_t(storage_type &stor, decltype(connection) conn, Args&& ...args): + view_t(storage_type &stor, decltype(connection) conn, Args&& ...args_): storage(stor), connection(std::move(conn)), - query([&args..., &stor]{ - std::string q; - stor.template generate_select_asterisk(&q, std::forward(args)...); - return q; - }()){} + args(std::make_tuple(std::forward>(args_)...)){} struct iterator_t { protected: @@ -8976,7 +8956,7 @@ namespace sqlite_orm { /** * Select a single column into std::vector or multiple columns into std::vector>. * For a single column use `auto rows = storage.select(&User::id, where(...)); - * For multicolumns user `auto rows = storage.select(columns(&User::id, &User::name), where(...)); + * For multicolumns use `auto rows = storage.select(columns(&User::id, &User::name), where(...)); */ template< class T, diff --git a/tests/static_tests.cpp b/tests/static_tests.cpp index 67bbfadf2..7b21cdc47 100644 --- a/tests/static_tests.cpp +++ b/tests/static_tests.cpp @@ -285,6 +285,28 @@ int main() { static_assert(std::is_same, decltype(mul(2, 3))>::type, double>::value, "Incorrect mul result"); static_assert(std::is_same, decltype(sqlite_orm::div(2, 3))>::type, double>::value, "Incorrect div result"); } + { + static_assert(internal::is_bindable::value, "bool must be bindable"); + static_assert(internal::is_bindable::value, "int must be bindable"); + static_assert(internal::is_bindable::value, "string must be bindable"); + static_assert(internal::is_bindable::value, "null must be bindable"); + static_assert(internal::is_bindable>::value, "unique_ptr must be bindable"); + static_assert(internal::is_bindable>::value, "shared_ptr must be bindable"); + + static_assert(!internal::is_bindable::value, "void cannot be bindable"); + auto isEqual = is_equal(&User::id, 5); + static_assert(!internal::is_bindable::value, "is_equal cannot be bindable"); + auto notEqual = is_not_equal(&User::id, 10); + static_assert(!internal::is_bindable::value, "is_not_equal cannot be bindable"); + auto lesserThan = lesser_than(&User::id, 10); + static_assert(!internal::is_bindable::value, "lesser_than cannot be bindable"); + auto lesserOrEqual = lesser_or_equal(&User::id, 5); + static_assert(!internal::is_bindable::value, "lesser_or_equal cannot be bindable"); + auto greaterThan = greater_than(&User::id, 5); + static_assert(!internal::is_bindable::value, "greater_than cannot be bindable"); + auto greaterOrEqual = greater_or_equal(&User::id, 5); + static_assert(!internal::is_bindable::value, "greater_or_equal cannot be bindable"); + } return 0; } From 252b2bd00d0e7bef528323f0209b098a73eb8900 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Tue, 30 Apr 2019 13:15:44 +0300 Subject: [PATCH 081/232] added more static tests --- tests/static_tests.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/static_tests.cpp b/tests/static_tests.cpp index 7b21cdc47..9aa8bdf12 100644 --- a/tests/static_tests.cpp +++ b/tests/static_tests.cpp @@ -288,6 +288,9 @@ int main() { { static_assert(internal::is_bindable::value, "bool must be bindable"); static_assert(internal::is_bindable::value, "int must be bindable"); + static_assert(internal::is_bindable::value, "long must be bindable"); + static_assert(internal::is_bindable::value, "float must be bindable"); + static_assert(internal::is_bindable::value, "double must be bindable"); static_assert(internal::is_bindable::value, "string must be bindable"); static_assert(internal::is_bindable::value, "null must be bindable"); static_assert(internal::is_bindable>::value, "unique_ptr must be bindable"); From 1a144ab8db95ecc54d4b547ceac26f3dfb973647 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Tue, 30 Apr 2019 19:21:03 +0300 Subject: [PATCH 082/232] fixed iterate compilation --- dev/storage.h | 21 ++++++++++----------- dev/view.h | 4 +++- include/sqlite_orm/sqlite_orm.h | 25 +++++++++++++------------ tests/tests.cpp | 8 ++++++-- 4 files changed, 32 insertions(+), 26 deletions(-) diff --git a/dev/storage.h b/dev/storage.h index 057dc46cd..c8b9b1cfc 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -1085,20 +1085,19 @@ namespace sqlite_orm { ss << this->process_where(hav.t) << " "; } + template + void process_conditions(std::stringstream &ss, std::tuple args) { + this->process_single_condition(ss, tuple_helper::head(args)); + this->process_conditions(ss, tuple_helper::tail(args)); + } + /** * Recursion end. */ - template - void process_conditions(std::stringstream &, std::tuple .../*args*/) { + void process_conditions(std::stringstream &, std::tuple<> /*args*/) { //.. } - template - void process_conditions(std::stringstream &ss, std::tuple args) { - this->process_single_condition(ss, tuple_helper::head(args)); - this->process_conditions(ss, tuple_helper::tail(args)); - } - void on_open_internal(sqlite3 *db) { #if SQLITE_VERSION_NUMBER >= 3006019 @@ -1378,7 +1377,7 @@ namespace sqlite_orm { * @return impl for O */ template - auto& generate_select_asterisk(std::string *query, Args&& ...args) { + auto& generate_select_asterisk(std::string *query, std::tuple args) { std::stringstream ss; ss << "SELECT "; auto &impl = this->get_impl(); @@ -1397,7 +1396,7 @@ namespace sqlite_orm { } } ss << "FROM '" << impl.table.name << "' "; - this->process_conditions(ss, std::make_tuple(std::forward(args)...)); + this->process_conditions(ss, move(args)); if(query){ *query = ss.str(); } @@ -1737,7 +1736,7 @@ namespace sqlite_orm { auto connection = this->get_or_create_connection(); C res; std::string query; - auto &impl = this->generate_select_asterisk(&query, std::forward(args)...); + auto &impl = this->generate_select_asterisk(&query, std::make_tuple(std::forward(args)...)); sqlite3_stmt *stmt; if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; diff --git a/dev/view.h b/dev/view.h index cdb237b5f..d4d550e6c 100644 --- a/dev/view.h +++ b/dev/view.h @@ -170,7 +170,9 @@ namespace sqlite_orm { iterator_t begin() { sqlite3_stmt *stmt = nullptr; auto db = this->connection->get_db(); - auto ret = sqlite3_prepare_v2(db, this->query.c_str(), -1, &stmt, nullptr); + std::string query; + this->storage.template generate_select_asterisk(&query, this->args); + auto ret = sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr); if(ret == SQLITE_OK){ return {stmt, *this}; }else{ diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 3af17ee2b..206870a10 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -6745,7 +6745,9 @@ namespace sqlite_orm { iterator_t begin() { sqlite3_stmt *stmt = nullptr; auto db = this->connection->get_db(); - auto ret = sqlite3_prepare_v2(db, this->query.c_str(), -1, &stmt, nullptr); + std::string query; + this->storage.template generate_select_asterisk(&query, this->args); + auto ret = sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr); if(ret == SQLITE_OK){ return {stmt, *this}; }else{ @@ -7796,20 +7798,19 @@ namespace sqlite_orm { ss << this->process_where(hav.t) << " "; } + template + void process_conditions(std::stringstream &ss, std::tuple args) { + this->process_single_condition(ss, tuple_helper::head(args)); + this->process_conditions(ss, tuple_helper::tail(args)); + } + /** * Recursion end. */ - template - void process_conditions(std::stringstream &, std::tuple .../*args*/) { + void process_conditions(std::stringstream &, std::tuple<> /*args*/) { //.. } - template - void process_conditions(std::stringstream &ss, std::tuple args) { - this->process_single_condition(ss, tuple_helper::head(args)); - this->process_conditions(ss, tuple_helper::tail(args)); - } - void on_open_internal(sqlite3 *db) { #if SQLITE_VERSION_NUMBER >= 3006019 @@ -8089,7 +8090,7 @@ namespace sqlite_orm { * @return impl for O */ template - auto& generate_select_asterisk(std::string *query, Args&& ...args) { + auto& generate_select_asterisk(std::string *query, std::tuple args) { std::stringstream ss; ss << "SELECT "; auto &impl = this->get_impl(); @@ -8108,7 +8109,7 @@ namespace sqlite_orm { } } ss << "FROM '" << impl.table.name << "' "; - this->process_conditions(ss, std::make_tuple(std::forward(args)...)); + this->process_conditions(ss, move(args)); if(query){ *query = ss.str(); } @@ -8448,7 +8449,7 @@ namespace sqlite_orm { auto connection = this->get_or_create_connection(); C res; std::string query; - auto &impl = this->generate_select_asterisk(&query, std::forward(args)...); + auto &impl = this->generate_select_asterisk(&query, std::make_tuple(std::forward(args)...)); sqlite3_stmt *stmt; if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; diff --git a/tests/tests.cpp b/tests/tests.cpp index 5729591d6..d4da70a49 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -13,7 +13,7 @@ using std::cout; using std::endl; void testIterateBlob() { - /*struct Test { + struct Test { int64_t id; std::vector key; }; @@ -35,7 +35,11 @@ void testIterateBlob() { db.insert(v); - for (auto& w : db.iterate(where(c(&Test::key) == key))) { + for(auto &obj : db.iterate()){ + cout << db.dump(obj) << endl; + } // test that view_t and iterator_t compile + + /*for (auto& w : db.iterate(where(c(&Test::key) == key))) { cout << w.id << endl; }*/ } From adef7c8c1d079073cead3e4e6f205627dd596045 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Tue, 30 Apr 2019 21:21:30 +0300 Subject: [PATCH 083/232] fixed core functions compilation --- dev/view.h | 2 +- include/sqlite_orm/sqlite_orm.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/view.h b/dev/view.h index d4d550e6c..478321b79 100644 --- a/dev/view.h +++ b/dev/view.h @@ -31,7 +31,7 @@ namespace sqlite_orm { view_t(storage_type &stor, decltype(connection) conn, Args&& ...args_): storage(stor), connection(std::move(conn)), - args(std::make_tuple(std::forward>(args_)...)){} + args(std::make_tuple(std::forward(args_)...)){} struct iterator_t { protected: diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 206870a10..3586b0c75 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -6606,7 +6606,7 @@ namespace sqlite_orm { view_t(storage_type &stor, decltype(connection) conn, Args&& ...args_): storage(stor), connection(std::move(conn)), - args(std::make_tuple(std::forward>(args_)...)){} + args(std::make_tuple(std::forward(args_)...)){} struct iterator_t { protected: From c4d6404b041a8a79a4b0e80b599f8389a12fe77e Mon Sep 17 00:00:00 2001 From: fnc12 Date: Tue, 30 Apr 2019 22:14:44 +0300 Subject: [PATCH 084/232] moved iterator outside of view --- dev/iterator.h | 146 ++++++++++++++++ dev/storage.h | 3 + dev/view.h | 133 +-------------- include/sqlite_orm/sqlite_orm.h | 284 ++++++++++++++++++-------------- 4 files changed, 311 insertions(+), 255 deletions(-) create mode 100644 dev/iterator.h diff --git a/dev/iterator.h b/dev/iterator.h new file mode 100644 index 000000000..59b51fe8f --- /dev/null +++ b/dev/iterator.h @@ -0,0 +1,146 @@ +#pragma once + +#include // std::shared_ptr, std::unique_ptr, std::make_shared +#include +#include // std::decay +#include // std::move +#include // std::ptrdiff_t +#include // std::input_iterator_tag +#include // std::system_error +#include // std::make_error_code + +#include "row_extractor.h" +#include "statement_finalizer.h" +#include "error_code.h" + +namespace sqlite_orm { + + namespace internal { + + template + struct iterator_t { + using view_type = V; + using value_type = typename view_type::mapped_type; + + protected: + + /** + * The double-indirection is so that copies of the iterator + * share the same sqlite3_stmt from a sqlite3_prepare_v2() + * call. When one finishes iterating it, the pointer + * inside the shared_ptr is nulled out in all copies. + */ + std::shared_ptr stmt; + view_type &view; + + /** + * shared_ptr is used over unique_ptr here + * so that the iterator can be copyable. + */ + std::shared_ptr current; + + void extract_value(std::unique_ptr &temp) { + temp = std::make_unique(); + auto &storage = this->view.storage; + auto &impl = storage.template get_impl(); + auto index = 0; + impl.table.for_each_column([&index, &temp, this] (auto &c) { + using field_type = typename std::decay::type::field_type; + auto value = row_extractor().extract(*this->stmt, index++); + if(c.member_pointer){ + auto member_pointer = c.member_pointer; + (*temp).*member_pointer = std::move(value); + }else{ + ((*temp).*(c.setter))(std::move(value)); + } + }); + } + + public: + using difference_type = std::ptrdiff_t; + using pointer = value_type *; + using reference = value_type &; + using iterator_category = std::input_iterator_tag; + + iterator_t(sqlite3_stmt *stmt_, view_type &view_): stmt(std::make_shared(stmt_)), view(view_) { + this->operator++(); + } + + iterator_t(const iterator_t &) = default; + + iterator_t(iterator_t&&) = default; + + iterator_t& operator=(iterator_t &&) = default; + + iterator_t& operator=(const iterator_t &) = default; + + ~iterator_t() { + if(this->stmt){ + statement_finalizer f{*this->stmt}; + } + } + + value_type &operator*() { + if(!this->stmt) { + throw std::system_error(std::make_error_code(orm_error_code::trying_to_dereference_null_iterator)); + } + if(!this->current){ + std::unique_ptr value; + this->extract_value(value); + this->current = move(value); + } + return *this->current; + } + + value_type *operator->() { + if(!this->stmt) { + throw std::system_error(std::make_error_code(orm_error_code::trying_to_dereference_null_iterator)); + } + if(!this->current){ + std::unique_ptr value; + this->extract_value(value); + this->current = move(value); + } + return &*this->current; + } + + void operator++() { + if(this->stmt && *this->stmt){ + auto ret = sqlite3_step(*this->stmt); + switch(ret){ + case SQLITE_ROW: + this->current = nullptr; + break; + case SQLITE_DONE:{ + statement_finalizer f{*this->stmt}; + *this->stmt = nullptr; + }break; + default:{ + throw std::system_error(std::error_code(sqlite3_errcode(this->view.connection->get_db()), get_sqlite_error_category())); + } + } + } + } + + void operator++(int) { + this->operator++(); + } + + bool operator==(const iterator_t &other) const { + if(this->stmt && other.stmt){ + return *this->stmt == *other.stmt; + }else{ + if(!this->stmt && !other.stmt){ + return true; + }else{ + return false; + } + } + } + + bool operator!=(const iterator_t &other) const { + return !(*this == other); + } + }; + } +} diff --git a/dev/storage.h b/dev/storage.h index c8b9b1cfc..906f830e5 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -106,6 +106,9 @@ namespace sqlite_orm { template friend struct view_t; + template + friend struct iterator_t; + /** * Check whether connection exists and returns it if yes or creates a new one * and returns it. diff --git a/dev/view.h b/dev/view.h index 478321b79..4b54b1342 100644 --- a/dev/view.h +++ b/dev/view.h @@ -1,12 +1,9 @@ #pragma once -#include // std::shared_ptr, std::make_shared, std::unique_ptr, std::make_unique +#include // std::shared_ptr #include // std::string #include // std::forward, std::move #include -#include // std::decay -#include // std::ptrdiff_t -#include // std::make_error_code #include // std::system_error #include // std::tuple, std::make_tuple @@ -14,6 +11,7 @@ #include "row_extractor.h" #include "statement_finalizer.h" #include "error_code.h" +#include "iterator.h" namespace sqlite_orm { @@ -23,6 +21,7 @@ namespace sqlite_orm { struct view_t { using mapped_type = T; using storage_type = S; + using self = view_t; storage_type &storage; std::shared_ptr connection; @@ -33,128 +32,6 @@ namespace sqlite_orm { connection(std::move(conn)), args(std::make_tuple(std::forward(args_)...)){} - struct iterator_t { - protected: - /** - * The double-indirection is so that copies of the iterator - * share the same sqlite3_stmt from a sqlite3_prepare_v2() - * call. When one finishes iterating it, the pointer - * inside the shared_ptr is nulled out in all copies. - */ - std::shared_ptr stmt; - view_t &view; - - /** - * shared_ptr is used over unique_ptr here - * so that the iterator can be copyable. - */ - std::shared_ptr current; - - void extract_value(std::unique_ptr &temp) { - temp = std::make_unique(); - auto &storage = this->view.storage; - auto &impl = storage.template get_impl(); - auto index = 0; - impl.table.for_each_column([&index, &temp, this] (auto &c) { - using field_type = typename std::decay::type::field_type; - auto value = row_extractor().extract(*this->stmt, index++); - if(c.member_pointer){ - auto member_pointer = c.member_pointer; - (*temp).*member_pointer = std::move(value); - }else{ - ((*temp).*(c.setter))(std::move(value)); - } - }); - } - - public: - using value_type = T; - using difference_type = std::ptrdiff_t; - using pointer = value_type *; - using reference = value_type &; - using iterator_category = std::input_iterator_tag; - - iterator_t(sqlite3_stmt *stmt_, view_t &view_): stmt(std::make_shared(stmt_)), view(view_) { - this->operator++(); - } - - iterator_t(const iterator_t &) = default; - - iterator_t(iterator_t&&) = default; - - iterator_t& operator=(iterator_t&&) = default; - - iterator_t& operator=(const iterator_t&) = default; - - ~iterator_t() { - if(this->stmt){ - statement_finalizer f{*this->stmt}; - } - } - - T& operator*() { - if(!this->stmt) { - throw std::system_error(std::make_error_code(orm_error_code::trying_to_dereference_null_iterator)); - } - if(!this->current){ - std::unique_ptr value; - this->extract_value(value); - this->current = std::move(value); - } - return *this->current; - } - - T* operator->() { - if(!this->stmt) { - throw std::system_error(std::make_error_code(orm_error_code::trying_to_dereference_null_iterator)); - } - if(!this->current){ - std::unique_ptr value; - this->extract_value(value); - this->current = std::move(value); - } - return &*this->current; - } - - void operator++() { - if(this->stmt && *this->stmt){ - auto ret = sqlite3_step(*this->stmt); - switch(ret){ - case SQLITE_ROW: - this->current = nullptr; - break; - case SQLITE_DONE:{ - statement_finalizer f{*this->stmt}; - *this->stmt = nullptr; - }break; - default:{ - throw std::system_error(std::error_code(sqlite3_errcode(this->view.connection->get_db()), get_sqlite_error_category())); - } - } - } - } - - void operator++(int) { - this->operator++(); - } - - bool operator==(const iterator_t &other) const { - if(this->stmt && other.stmt){ - return *this->stmt == *other.stmt; - }else{ - if(!this->stmt && !other.stmt){ - return true; - }else{ - return false; - } - } - } - - bool operator!=(const iterator_t &other) const { - return !(*this == other); - } - }; - size_t size() { return this->storage.template count(); } @@ -163,11 +40,11 @@ namespace sqlite_orm { return !this->size(); } - iterator_t end() { + iterator_t end() { return {nullptr, *this}; } - iterator_t begin() { + iterator_t begin() { sqlite3_stmt *stmt = nullptr; auto db = this->connection->get_db(); std::string query; diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 3586b0c75..6627a8898 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -6571,13 +6571,10 @@ namespace sqlite_orm { // #include "view.h" -#include // std::shared_ptr, std::make_shared, std::unique_ptr, std::make_unique +#include // std::shared_ptr #include // std::string #include // std::forward, std::move #include -#include // std::decay -#include // std::ptrdiff_t -#include // std::make_error_code #include // std::system_error #include // std::tuple, std::make_tuple @@ -6589,146 +6586,176 @@ namespace sqlite_orm { // #include "error_code.h" +// #include "iterator.h" + + +#include // std::shared_ptr, std::unique_ptr, std::make_shared +#include +#include // std::decay +#include // std::move +#include // std::ptrdiff_t +#include // std::input_iterator_tag +#include // std::system_error +#include // std::make_error_code + +// #include "row_extractor.h" + +// #include "statement_finalizer.h" + +// #include "error_code.h" + namespace sqlite_orm { namespace internal { - template - struct view_t { - using mapped_type = T; - using storage_type = S; + template + struct iterator_t { + using view_type = V; + using value_type = typename view_type::mapped_type; - storage_type &storage; - std::shared_ptr connection; - std::tuple args; + protected: - view_t(storage_type &stor, decltype(connection) conn, Args&& ...args_): - storage(stor), - connection(std::move(conn)), - args(std::make_tuple(std::forward(args_)...)){} + /** + * The double-indirection is so that copies of the iterator + * share the same sqlite3_stmt from a sqlite3_prepare_v2() + * call. When one finishes iterating it, the pointer + * inside the shared_ptr is nulled out in all copies. + */ + std::shared_ptr stmt; + view_type &view; - struct iterator_t { - protected: - /** - * The double-indirection is so that copies of the iterator - * share the same sqlite3_stmt from a sqlite3_prepare_v2() - * call. When one finishes iterating it, the pointer - * inside the shared_ptr is nulled out in all copies. - */ - std::shared_ptr stmt; - view_t &view; - - /** - * shared_ptr is used over unique_ptr here - * so that the iterator can be copyable. - */ - std::shared_ptr current; - - void extract_value(std::unique_ptr &temp) { - temp = std::make_unique(); - auto &storage = this->view.storage; - auto &impl = storage.template get_impl(); - auto index = 0; - impl.table.for_each_column([&index, &temp, this] (auto &c) { - using field_type = typename std::decay::type::field_type; - auto value = row_extractor().extract(*this->stmt, index++); - if(c.member_pointer){ - auto member_pointer = c.member_pointer; - (*temp).*member_pointer = std::move(value); - }else{ - ((*temp).*(c.setter))(std::move(value)); - } - }); + /** + * shared_ptr is used over unique_ptr here + * so that the iterator can be copyable. + */ + std::shared_ptr current; + + void extract_value(std::unique_ptr &temp) { + temp = std::make_unique(); + auto &storage = this->view.storage; + auto &impl = storage.template get_impl(); + auto index = 0; + impl.table.for_each_column([&index, &temp, this] (auto &c) { + using field_type = typename std::decay::type::field_type; + auto value = row_extractor().extract(*this->stmt, index++); + if(c.member_pointer){ + auto member_pointer = c.member_pointer; + (*temp).*member_pointer = std::move(value); + }else{ + ((*temp).*(c.setter))(std::move(value)); + } + }); + } + + public: + using difference_type = std::ptrdiff_t; + using pointer = value_type *; + using reference = value_type &; + using iterator_category = std::input_iterator_tag; + + iterator_t(sqlite3_stmt *stmt_, view_type &view_): stmt(std::make_shared(stmt_)), view(view_) { + this->operator++(); + } + + iterator_t(const iterator_t &) = default; + + iterator_t(iterator_t&&) = default; + + iterator_t& operator=(iterator_t &&) = default; + + iterator_t& operator=(const iterator_t &) = default; + + ~iterator_t() { + if(this->stmt){ + statement_finalizer f{*this->stmt}; } - - public: - using value_type = T; - using difference_type = std::ptrdiff_t; - using pointer = value_type *; - using reference = value_type &; - using iterator_category = std::input_iterator_tag; - - iterator_t(sqlite3_stmt *stmt_, view_t &view_): stmt(std::make_shared(stmt_)), view(view_) { - this->operator++(); + } + + value_type &operator*() { + if(!this->stmt) { + throw std::system_error(std::make_error_code(orm_error_code::trying_to_dereference_null_iterator)); } - - iterator_t(const iterator_t &) = default; - - iterator_t(iterator_t&&) = default; - - iterator_t& operator=(iterator_t&&) = default; - - iterator_t& operator=(const iterator_t&) = default; - - ~iterator_t() { - if(this->stmt){ - statement_finalizer f{*this->stmt}; - } + if(!this->current){ + std::unique_ptr value; + this->extract_value(value); + this->current = move(value); } - - T& operator*() { - if(!this->stmt) { - throw std::system_error(std::make_error_code(orm_error_code::trying_to_dereference_null_iterator)); - } - if(!this->current){ - std::unique_ptr value; - this->extract_value(value); - this->current = std::move(value); - } - return *this->current; + return *this->current; + } + + value_type *operator->() { + if(!this->stmt) { + throw std::system_error(std::make_error_code(orm_error_code::trying_to_dereference_null_iterator)); } - - T* operator->() { - if(!this->stmt) { - throw std::system_error(std::make_error_code(orm_error_code::trying_to_dereference_null_iterator)); - } - if(!this->current){ - std::unique_ptr value; - this->extract_value(value); - this->current = std::move(value); - } - return &*this->current; + if(!this->current){ + std::unique_ptr value; + this->extract_value(value); + this->current = move(value); } - - void operator++() { - if(this->stmt && *this->stmt){ - auto ret = sqlite3_step(*this->stmt); - switch(ret){ - case SQLITE_ROW: - this->current = nullptr; - break; - case SQLITE_DONE:{ - statement_finalizer f{*this->stmt}; - *this->stmt = nullptr; - }break; - default:{ - throw std::system_error(std::error_code(sqlite3_errcode(this->view.connection->get_db()), get_sqlite_error_category())); - } + return &*this->current; + } + + void operator++() { + if(this->stmt && *this->stmt){ + auto ret = sqlite3_step(*this->stmt); + switch(ret){ + case SQLITE_ROW: + this->current = nullptr; + break; + case SQLITE_DONE:{ + statement_finalizer f{*this->stmt}; + *this->stmt = nullptr; + }break; + default:{ + throw std::system_error(std::error_code(sqlite3_errcode(this->view.connection->get_db()), get_sqlite_error_category())); } } } - - void operator++(int) { - this->operator++(); - } - - bool operator==(const iterator_t &other) const { - if(this->stmt && other.stmt){ - return *this->stmt == *other.stmt; + } + + void operator++(int) { + this->operator++(); + } + + bool operator==(const iterator_t &other) const { + if(this->stmt && other.stmt){ + return *this->stmt == *other.stmt; + }else{ + if(!this->stmt && !other.stmt){ + return true; }else{ - if(!this->stmt && !other.stmt){ - return true; - }else{ - return false; - } + return false; } } - - bool operator!=(const iterator_t &other) const { - return !(*this == other); - } - }; + } + + bool operator!=(const iterator_t &other) const { + return !(*this == other); + } + }; + } +} + + +namespace sqlite_orm { + + namespace internal { + + template + struct view_t { + using mapped_type = T; + using storage_type = S; + using self = view_t; + + storage_type &storage; + std::shared_ptr connection; + std::tuple args; + + view_t(storage_type &stor, decltype(connection) conn, Args&& ...args_): + storage(stor), + connection(std::move(conn)), + args(std::make_tuple(std::forward(args_)...)){} size_t size() { return this->storage.template count(); @@ -6738,11 +6765,11 @@ namespace sqlite_orm { return !this->size(); } - iterator_t end() { + iterator_t end() { return {nullptr, *this}; } - iterator_t begin() { + iterator_t begin() { sqlite3_stmt *stmt = nullptr; auto db = this->connection->get_db(); std::string query; @@ -6819,6 +6846,9 @@ namespace sqlite_orm { template friend struct view_t; + template + friend struct iterator_t; + /** * Check whether connection exists and returns it if yes or creates a new one * and returns it. From efebac00b4ad63dc1a9b8ae774fb549515ff50e1 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Fri, 3 May 2019 19:35:21 +0300 Subject: [PATCH 085/232] added ignore bindable arg to string_from_expression --- dev/iterator.h | 2 +- dev/storage.h | 244 ++++++++++++++++--------------- include/sqlite_orm/sqlite_orm.h | 246 +++++++++++++++++--------------- 3 files changed, 258 insertions(+), 234 deletions(-) diff --git a/dev/iterator.h b/dev/iterator.h index 59b51fe8f..95482960f 100644 --- a/dev/iterator.h +++ b/dev/iterator.h @@ -27,7 +27,7 @@ namespace sqlite_orm { /** * The double-indirection is so that copies of the iterator * share the same sqlite3_stmt from a sqlite3_prepare_v2() - * call. When one finishes iterating it, the pointer + * call. When one finishes iterating it the pointer * inside the shared_ptr is nulled out in all copies. */ std::shared_ptr stmt; diff --git a/dev/storage.h b/dev/storage.h index 906f830e5..1f2698785 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -296,22 +296,26 @@ namespace sqlite_orm { } template - typename std::enable_if::value, std::string>::type string_from_expression(T t, bool /*noTableName*/ = false, bool escape = false) { + typename std::enable_if::value, std::string>::type string_from_expression(const T &t, bool /*noTableName*/ = false, bool escape = false, bool ignoreBindable = false) { auto isNullable = type_is_nullable::value; if(isNullable && !type_is_nullable()(t)){ return "NULL"; }else{ auto needQuotes = std::is_base_of>::value; std::stringstream ss; - if(needQuotes){ + if(needQuotes && ignoreBindable){ ss << "'"; } - std::string text = field_printer()(t); - if(escape){ - text = this->escape(text); + if(ignoreBindable){ + std::string text = field_printer()(t); + if(escape){ + text = this->escape(text); + } + ss << text; + }else{ + ss << "? "; } - ss << text; - if(needQuotes){ + if(needQuotes && ignoreBindable){ ss << "'"; } return ss.str(); @@ -319,18 +323,18 @@ namespace sqlite_orm { } template - std::string string_from_expression(const alias_holder &, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const alias_holder &, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { return T::get(); } template - std::string string_from_expression(const as_t &als, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const as_t &als, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { auto tableAliasString = alias_extractor::get(); - return this->string_from_expression(als.expression) + " AS " + tableAliasString; + return this->string_from_expression(als.expression, noTableName, escape, ignoreBindable) + " AS " + tableAliasString; } template - std::string string_from_expression(const alias_column_t &als, bool noTableName = false, bool /*escape*/ = false) { + std::string string_from_expression(const alias_column_t &als, bool noTableName = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!noTableName){ ss << "'" << T::get() << "'."; @@ -339,28 +343,36 @@ namespace sqlite_orm { return ss.str(); } - std::string string_from_expression(const std::string &t, bool /*noTableName*/ = false, bool escape = false) { + std::string string_from_expression(const std::string &t, bool /*noTableName*/ = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - std::string text = t; - if(escape){ - text = this->escape(text); + if(ignoreBindable){ + std::string text = t; + if(escape){ + text = this->escape(text); + } + ss << "'" << text << "'"; + }else{ + ss << "? "; } - ss << "'" << text << "'"; return ss.str(); } - std::string string_from_expression(const char *t, bool /*noTableName*/ = false, bool escape = false) { + std::string string_from_expression(const char *t, bool /*noTableName*/ = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - std::string text = t; - if(escape){ - text = this->escape(text); + if(ignoreBindable){ + std::string text = t; + if(escape){ + text = this->escape(text); + } + ss << "'" << text << "'"; + }else{ + ss << "? "; } - ss << "'" << text << "'"; return ss.str(); } template - std::string string_from_expression(F O::*m, bool noTableName = false, bool /*escape*/ = false) { + std::string string_from_expression(F O::*m, bool noTableName = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!noTableName){ ss << "'" << this->impl.template find_table_name() << "'."; @@ -369,20 +381,20 @@ namespace sqlite_orm { return ss.str(); } - std::string string_from_expression(const rowid_t &rid, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const rowid_t &rid, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { return static_cast(rid); } - std::string string_from_expression(const oid_t &rid, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const oid_t &rid, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { return static_cast(rid); } - std::string string_from_expression(const _rowid_t &rid, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const _rowid_t &rid, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { return static_cast(rid); } template - std::string string_from_expression(const table_rowid_t &rid, bool noTableName = false, bool /*escape*/ = false) { + std::string string_from_expression(const table_rowid_t &rid, bool noTableName = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!noTableName){ ss << "'" << this->impl.template find_table_name() << "'."; @@ -392,7 +404,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const table_oid_t &rid, bool noTableName = false, bool /*escape*/ = false) { + std::string string_from_expression(const table_oid_t &rid, bool noTableName = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!noTableName){ ss << "'" << this->impl.template find_table_name() << "'."; @@ -402,7 +414,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const table__rowid_t &rid, bool noTableName = false, bool /*escape*/ = false) { + std::string string_from_expression(const table__rowid_t &rid, bool noTableName = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!noTableName){ ss << "'" << this->impl.template find_table_name() << "'."; @@ -412,78 +424,78 @@ namespace sqlite_orm { } template - std::string string_from_expression(const aggregate_functions::group_concat_double_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const aggregate_functions::group_concat_double_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.t); - auto expr2 = this->string_from_expression(f.y); + auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); + auto expr2 = this->string_from_expression(f.y, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ", " << expr2 << ") "; return ss.str(); } template - std::string string_from_expression(const aggregate_functions::group_concat_single_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const aggregate_functions::group_concat_single_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.t); + auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const conc_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const conc_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto lhs = this->string_from_expression(f.l); - auto rhs = this->string_from_expression(f.r); + auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); + auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); ss << "(" << lhs << " || " << rhs << ") "; return ss.str(); } template - std::string string_from_expression(const add_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const add_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto lhs = this->string_from_expression(f.l); - auto rhs = this->string_from_expression(f.r); + auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); + auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); ss << "(" << lhs << " + " << rhs << ") "; return ss.str(); } template - std::string string_from_expression(const sub_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const sub_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto lhs = this->string_from_expression(f.l); - auto rhs = this->string_from_expression(f.r); + auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); + auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); ss << "(" << lhs << " - " << rhs << ") "; return ss.str(); } template - std::string string_from_expression(const mul_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const mul_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto lhs = this->string_from_expression(f.l); - auto rhs = this->string_from_expression(f.r); + auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); + auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); ss << "(" << lhs << " * " << rhs << ") "; return ss.str(); } template - std::string string_from_expression(const div_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const div_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto lhs = this->string_from_expression(f.l); - auto rhs = this->string_from_expression(f.r); + auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); + auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); ss << "(" << lhs << " / " << rhs << ") "; return ss.str(); } template - std::string string_from_expression(const mod_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const mod_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto lhs = this->string_from_expression(f.l); - auto rhs = this->string_from_expression(f.r); + auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); + auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); ss << "(" << lhs << " % " << rhs << ") "; return ss.str(); } template - std::string string_from_expression(const aggregate_functions::min_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const aggregate_functions::min_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.t); ss << static_cast(f) << "(" << expr << ") "; @@ -491,174 +503,174 @@ namespace sqlite_orm { } template - std::string string_from_expression(const aggregate_functions::max_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const aggregate_functions::max_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.t); + auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const aggregate_functions::total_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const aggregate_functions::total_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.t); + auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const aggregate_functions::sum_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const aggregate_functions::sum_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.t); + auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const aggregate_functions::count_asterisk_t &, bool /*noTableName*/ = false, bool /*escape*/ = false) { - return this->string_from_expression(aggregate_functions::count_asterisk_without_type{}); + std::string string_from_expression(const aggregate_functions::count_asterisk_t &, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + return this->string_from_expression(aggregate_functions::count_asterisk_without_type{}, noTableName, escape, ignoreBindable); } - std::string string_from_expression(const aggregate_functions::count_asterisk_without_type &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const aggregate_functions::count_asterisk_without_type &f, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { std::stringstream ss; ss << static_cast(f) << "(*) "; return ss.str(); } template - std::string string_from_expression(const aggregate_functions::count_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const aggregate_functions::count_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.t); + auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const aggregate_functions::avg_t &a, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const aggregate_functions::avg_t &a, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(a.t); + auto expr = this->string_from_expression(a.t, noTableName, escape, ignoreBindable); ss << static_cast(a) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const distinct_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const distinct_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.t); + auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const all_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const all_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.t); + auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const core_functions::rtrim_double_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::rtrim_double_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.x); - auto expr2 = this->string_from_expression(f.y); + auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); + auto expr2 = this->string_from_expression(f.y, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ", " << expr2 << ") "; return ss.str(); } template - std::string string_from_expression(const core_functions::rtrim_single_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::rtrim_single_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.x); + auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const core_functions::ltrim_double_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::ltrim_double_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.x); - auto expr2 = this->string_from_expression(f.y); + auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); + auto expr2 = this->string_from_expression(f.y, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ", " << expr2 << ") "; return ss.str(); } template - std::string string_from_expression(const core_functions::ltrim_single_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::ltrim_single_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.x); + auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const core_functions::trim_double_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::trim_double_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.x); - auto expr2 = this->string_from_expression(f.y); + auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); + auto expr2 = this->string_from_expression(f.y, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ", " << expr2 << ") "; return ss.str(); } template - std::string string_from_expression(const core_functions::trim_single_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::trim_single_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.x); + auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } - std::string string_from_expression(const core_functions::changes_t &ch, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::changes_t &ch, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { std::stringstream ss; ss << static_cast(ch) << "() "; return ss.str(); } template - std::string string_from_expression(const core_functions::length_t &len, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::length_t &len, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(len.t); + auto expr = this->string_from_expression(len.t, noTableName, escape, ignoreBindable); ss << static_cast(len) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const core_functions::datetime_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::datetime_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - ss << static_cast(f) << "(" << this->string_from_expression(f.timestring); + ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); using tuple_t = std::tuple; - tuple_helper::iterator::value - 1, Args...>()(f.modifiers, [&ss, this](auto &v){ - ss << ", " << this->string_from_expression(v); + tuple_helper::iterator::value - 1, Args...>()(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ + ss << ", " << this->string_from_expression(v, noTableName, escape); }); ss << ") "; return ss.str(); } template - std::string string_from_expression(const core_functions::date_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::date_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - ss << static_cast(f) << "(" << this->string_from_expression(f.timestring); + ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); using tuple_t = std::tuple; - tuple_helper::iterator::value - 1, Args...>()(f.modifiers, [&ss, this](auto &v){ - ss << ", " << this->string_from_expression(v); + tuple_helper::iterator::value - 1, Args...>()(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ + ss << ", " << this->string_from_expression(v, noTableName, escape, ignoreBindable); }, false); ss << ") "; return ss.str(); } template - std::string string_from_expression(const core_functions::julianday_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::julianday_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - ss << static_cast(f) << "(" << this->string_from_expression(f.timestring); + ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); using tuple_t = std::tuple; - tuple_helper::iterator::value - 1, Args...>()(f.modifiers, [&ss, this](auto &v){ - ss << ", " << this->string_from_expression(v); + tuple_helper::iterator::value - 1, Args...>()(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ + ss << ", " << this->string_from_expression(v, noTableName, escape, ignoreBindable); }, false); ss << ") "; return ss.str(); } - std::string string_from_expression(const core_functions::random_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::random_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { std::stringstream ss; ss << static_cast(f) << "() "; return ss.str(); @@ -667,13 +679,13 @@ namespace sqlite_orm { #if SQLITE_VERSION_NUMBER >= 3007016 template - std::string string_from_expression(const core_functions::char_t_ &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::char_t_ &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; using tuple_t = decltype(f.args); std::vector args; args.reserve(std::tuple_size::value); - tuple_helper::tuple_for_each(f.args, [&args, this](auto &v){ - auto expression = this->string_from_expression(v); + tuple_helper::tuple_for_each(f.args, [&args, this, noTableName, escape, ignoreBindable](auto &v){ + auto expression = this->string_from_expression(v, noTableName, escape, ignoreBindable); args.emplace_back(std::move(expression)); }); ss << static_cast(f) << "("; @@ -692,31 +704,31 @@ namespace sqlite_orm { #endif template - std::string string_from_expression(const core_functions::upper_t &a, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::upper_t &a, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(a.t); + auto expr = this->string_from_expression(a.t, noTableName, escape, ignoreBindable); ss << static_cast(a) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const core_functions::lower_t &a, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::lower_t &a, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(a.t); + auto expr = this->string_from_expression(a.t, noTableName, escape, ignoreBindable); ss << static_cast(a) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const core_functions::abs_t &a, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::abs_t &a, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(a.t); + auto expr = this->string_from_expression(a.t, noTableName, escape, ignoreBindable); ss << static_cast(a) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const column_pointer &c, bool noTableName = false, bool /*escape*/ = false) { + std::string string_from_expression(const column_pointer &c, bool noTableName = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!noTableName){ ss << "'" << this->impl.template find_table_name() << "'."; @@ -762,7 +774,7 @@ namespace sqlite_orm { * Takes select_t object and returns SELECT query string */ template - std::string string_from_expression(const internal::select_t &sel, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const internal::select_t &sel, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!is_base_of_template::value){ if(!sel.highest_level){ @@ -818,19 +830,19 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::cast_t &c, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const conditions::cast_t &c, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - ss << static_cast(c) << " ( " << this->string_from_expression(c.expression) << " AS " << type_printer().print() << ") "; + ss << static_cast(c) << " ( " << this->string_from_expression(c.expression, noTableName, escape, ignoreBindable) << " AS " << type_printer().print() << ") "; return ss.str(); } template - typename std::enable_if::value, std::string>::type string_from_expression(const T &op, bool /*noTableName*/ = false, bool /*escape*/ = false) + typename std::enable_if::value, std::string>::type string_from_expression(const T &op, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - ss << this->string_from_expression(op.left) << " "; + ss << this->string_from_expression(op.left, noTableName, escape, ignoreBindable) << " "; ss << static_cast(op) << " "; - ss << this->string_from_expression(op.right) << " "; + ss << this->string_from_expression(op.right, noTableName, escape, ignoreBindable) << " "; return ss.str(); } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 6627a8898..9f8874e86 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -6619,7 +6619,7 @@ namespace sqlite_orm { /** * The double-indirection is so that copies of the iterator * share the same sqlite3_stmt from a sqlite3_prepare_v2() - * call. When one finishes iterating it, the pointer + * call. When one finishes iterating it the pointer * inside the shared_ptr is nulled out in all copies. */ std::shared_ptr stmt; @@ -7036,22 +7036,26 @@ namespace sqlite_orm { } template - typename std::enable_if::value, std::string>::type string_from_expression(T t, bool /*noTableName*/ = false, bool escape = false) { + typename std::enable_if::value, std::string>::type string_from_expression(const T &t, bool /*noTableName*/ = false, bool escape = false, bool ignoreBindable = false) { auto isNullable = type_is_nullable::value; if(isNullable && !type_is_nullable()(t)){ return "NULL"; }else{ auto needQuotes = std::is_base_of>::value; std::stringstream ss; - if(needQuotes){ + if(needQuotes && ignoreBindable){ ss << "'"; } - std::string text = field_printer()(t); - if(escape){ - text = this->escape(text); + if(ignoreBindable){ + std::string text = field_printer()(t); + if(escape){ + text = this->escape(text); + } + ss << text; + }else{ + ss << "? "; } - ss << text; - if(needQuotes){ + if(needQuotes && ignoreBindable){ ss << "'"; } return ss.str(); @@ -7059,18 +7063,18 @@ namespace sqlite_orm { } template - std::string string_from_expression(const alias_holder &, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const alias_holder &, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { return T::get(); } template - std::string string_from_expression(const as_t &als, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const as_t &als, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { auto tableAliasString = alias_extractor::get(); - return this->string_from_expression(als.expression) + " AS " + tableAliasString; + return this->string_from_expression(als.expression, noTableName, escape, ignoreBindable) + " AS " + tableAliasString; } template - std::string string_from_expression(const alias_column_t &als, bool noTableName = false, bool /*escape*/ = false) { + std::string string_from_expression(const alias_column_t &als, bool noTableName = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!noTableName){ ss << "'" << T::get() << "'."; @@ -7079,28 +7083,36 @@ namespace sqlite_orm { return ss.str(); } - std::string string_from_expression(const std::string &t, bool /*noTableName*/ = false, bool escape = false) { + std::string string_from_expression(const std::string &t, bool /*noTableName*/ = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - std::string text = t; - if(escape){ - text = this->escape(text); + if(ignoreBindable){ + std::string text = t; + if(escape){ + text = this->escape(text); + } + ss << "'" << text << "'"; + }else{ + ss << "? "; } - ss << "'" << text << "'"; return ss.str(); } - std::string string_from_expression(const char *t, bool /*noTableName*/ = false, bool escape = false) { + std::string string_from_expression(const char *t, bool /*noTableName*/ = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - std::string text = t; - if(escape){ - text = this->escape(text); + if(ignoreBindable){ + std::string text = t; + if(escape){ + text = this->escape(text); + } + ss << "'" << text << "'"; + }else{ + ss << "? "; } - ss << "'" << text << "'"; return ss.str(); } template - std::string string_from_expression(F O::*m, bool noTableName = false, bool /*escape*/ = false) { + std::string string_from_expression(F O::*m, bool noTableName = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!noTableName){ ss << "'" << this->impl.template find_table_name() << "'."; @@ -7109,20 +7121,20 @@ namespace sqlite_orm { return ss.str(); } - std::string string_from_expression(const rowid_t &rid, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const rowid_t &rid, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { return static_cast(rid); } - std::string string_from_expression(const oid_t &rid, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const oid_t &rid, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { return static_cast(rid); } - std::string string_from_expression(const _rowid_t &rid, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const _rowid_t &rid, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { return static_cast(rid); } template - std::string string_from_expression(const table_rowid_t &rid, bool noTableName = false, bool /*escape*/ = false) { + std::string string_from_expression(const table_rowid_t &rid, bool noTableName = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!noTableName){ ss << "'" << this->impl.template find_table_name() << "'."; @@ -7132,7 +7144,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const table_oid_t &rid, bool noTableName = false, bool /*escape*/ = false) { + std::string string_from_expression(const table_oid_t &rid, bool noTableName = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!noTableName){ ss << "'" << this->impl.template find_table_name() << "'."; @@ -7142,7 +7154,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const table__rowid_t &rid, bool noTableName = false, bool /*escape*/ = false) { + std::string string_from_expression(const table__rowid_t &rid, bool noTableName = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!noTableName){ ss << "'" << this->impl.template find_table_name() << "'."; @@ -7152,78 +7164,78 @@ namespace sqlite_orm { } template - std::string string_from_expression(const aggregate_functions::group_concat_double_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const aggregate_functions::group_concat_double_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.t); - auto expr2 = this->string_from_expression(f.y); + auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); + auto expr2 = this->string_from_expression(f.y, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ", " << expr2 << ") "; return ss.str(); } template - std::string string_from_expression(const aggregate_functions::group_concat_single_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const aggregate_functions::group_concat_single_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.t); + auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const conc_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const conc_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto lhs = this->string_from_expression(f.l); - auto rhs = this->string_from_expression(f.r); + auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); + auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); ss << "(" << lhs << " || " << rhs << ") "; return ss.str(); } template - std::string string_from_expression(const add_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const add_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto lhs = this->string_from_expression(f.l); - auto rhs = this->string_from_expression(f.r); + auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); + auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); ss << "(" << lhs << " + " << rhs << ") "; return ss.str(); } template - std::string string_from_expression(const sub_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const sub_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto lhs = this->string_from_expression(f.l); - auto rhs = this->string_from_expression(f.r); + auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); + auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); ss << "(" << lhs << " - " << rhs << ") "; return ss.str(); } template - std::string string_from_expression(const mul_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const mul_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto lhs = this->string_from_expression(f.l); - auto rhs = this->string_from_expression(f.r); + auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); + auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); ss << "(" << lhs << " * " << rhs << ") "; return ss.str(); } template - std::string string_from_expression(const div_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const div_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto lhs = this->string_from_expression(f.l); - auto rhs = this->string_from_expression(f.r); + auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); + auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); ss << "(" << lhs << " / " << rhs << ") "; return ss.str(); } template - std::string string_from_expression(const mod_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const mod_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto lhs = this->string_from_expression(f.l); - auto rhs = this->string_from_expression(f.r); + auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); + auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); ss << "(" << lhs << " % " << rhs << ") "; return ss.str(); } template - std::string string_from_expression(const aggregate_functions::min_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const aggregate_functions::min_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.t); ss << static_cast(f) << "(" << expr << ") "; @@ -7231,174 +7243,174 @@ namespace sqlite_orm { } template - std::string string_from_expression(const aggregate_functions::max_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const aggregate_functions::max_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.t); + auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const aggregate_functions::total_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const aggregate_functions::total_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.t); + auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const aggregate_functions::sum_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const aggregate_functions::sum_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.t); + auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const aggregate_functions::count_asterisk_t &, bool /*noTableName*/ = false, bool /*escape*/ = false) { - return this->string_from_expression(aggregate_functions::count_asterisk_without_type{}); + std::string string_from_expression(const aggregate_functions::count_asterisk_t &, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + return this->string_from_expression(aggregate_functions::count_asterisk_without_type{}, noTableName, escape, ignoreBindable); } - std::string string_from_expression(const aggregate_functions::count_asterisk_without_type &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const aggregate_functions::count_asterisk_without_type &f, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { std::stringstream ss; ss << static_cast(f) << "(*) "; return ss.str(); } template - std::string string_from_expression(const aggregate_functions::count_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const aggregate_functions::count_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.t); + auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const aggregate_functions::avg_t &a, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const aggregate_functions::avg_t &a, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(a.t); + auto expr = this->string_from_expression(a.t, noTableName, escape, ignoreBindable); ss << static_cast(a) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const distinct_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const distinct_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.t); + auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const all_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const all_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.t); + auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const core_functions::rtrim_double_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::rtrim_double_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.x); - auto expr2 = this->string_from_expression(f.y); + auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); + auto expr2 = this->string_from_expression(f.y, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ", " << expr2 << ") "; return ss.str(); } template - std::string string_from_expression(const core_functions::rtrim_single_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::rtrim_single_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.x); + auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const core_functions::ltrim_double_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::ltrim_double_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.x); - auto expr2 = this->string_from_expression(f.y); + auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); + auto expr2 = this->string_from_expression(f.y, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ", " << expr2 << ") "; return ss.str(); } template - std::string string_from_expression(const core_functions::ltrim_single_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::ltrim_single_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.x); + auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const core_functions::trim_double_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::trim_double_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.x); - auto expr2 = this->string_from_expression(f.y); + auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); + auto expr2 = this->string_from_expression(f.y, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ", " << expr2 << ") "; return ss.str(); } template - std::string string_from_expression(const core_functions::trim_single_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::trim_single_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.x); + auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } - std::string string_from_expression(const core_functions::changes_t &ch, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::changes_t &ch, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { std::stringstream ss; ss << static_cast(ch) << "() "; return ss.str(); } template - std::string string_from_expression(const core_functions::length_t &len, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::length_t &len, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(len.t); + auto expr = this->string_from_expression(len.t, noTableName, escape, ignoreBindable); ss << static_cast(len) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const core_functions::datetime_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::datetime_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - ss << static_cast(f) << "(" << this->string_from_expression(f.timestring); + ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); using tuple_t = std::tuple; - tuple_helper::iterator::value - 1, Args...>()(f.modifiers, [&ss, this](auto &v){ - ss << ", " << this->string_from_expression(v); + tuple_helper::iterator::value - 1, Args...>()(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ + ss << ", " << this->string_from_expression(v, noTableName, escape); }); ss << ") "; return ss.str(); } template - std::string string_from_expression(const core_functions::date_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::date_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - ss << static_cast(f) << "(" << this->string_from_expression(f.timestring); + ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); using tuple_t = std::tuple; - tuple_helper::iterator::value - 1, Args...>()(f.modifiers, [&ss, this](auto &v){ - ss << ", " << this->string_from_expression(v); + tuple_helper::iterator::value - 1, Args...>()(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ + ss << ", " << this->string_from_expression(v, noTableName, escape, ignoreBindable); }, false); ss << ") "; return ss.str(); } template - std::string string_from_expression(const core_functions::julianday_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::julianday_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - ss << static_cast(f) << "(" << this->string_from_expression(f.timestring); + ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); using tuple_t = std::tuple; - tuple_helper::iterator::value - 1, Args...>()(f.modifiers, [&ss, this](auto &v){ - ss << ", " << this->string_from_expression(v); + tuple_helper::iterator::value - 1, Args...>()(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ + ss << ", " << this->string_from_expression(v, noTableName, escape, ignoreBindable); }, false); ss << ") "; return ss.str(); } - std::string string_from_expression(const core_functions::random_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::random_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { std::stringstream ss; ss << static_cast(f) << "() "; return ss.str(); @@ -7407,13 +7419,13 @@ namespace sqlite_orm { #if SQLITE_VERSION_NUMBER >= 3007016 template - std::string string_from_expression(const core_functions::char_t_ &f, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::char_t_ &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; using tuple_t = decltype(f.args); std::vector args; args.reserve(std::tuple_size::value); - tuple_helper::tuple_for_each(f.args, [&args, this](auto &v){ - auto expression = this->string_from_expression(v); + tuple_helper::tuple_for_each(f.args, [&args, this, noTableName, escape, ignoreBindable](auto &v){ + auto expression = this->string_from_expression(v, noTableName, escape, ignoreBindable); args.emplace_back(std::move(expression)); }); ss << static_cast(f) << "("; @@ -7432,31 +7444,31 @@ namespace sqlite_orm { #endif template - std::string string_from_expression(const core_functions::upper_t &a, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::upper_t &a, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(a.t); + auto expr = this->string_from_expression(a.t, noTableName, escape, ignoreBindable); ss << static_cast(a) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const core_functions::lower_t &a, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::lower_t &a, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(a.t); + auto expr = this->string_from_expression(a.t, noTableName, escape, ignoreBindable); ss << static_cast(a) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const core_functions::abs_t &a, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const core_functions::abs_t &a, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(a.t); + auto expr = this->string_from_expression(a.t, noTableName, escape, ignoreBindable); ss << static_cast(a) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const column_pointer &c, bool noTableName = false, bool /*escape*/ = false) { + std::string string_from_expression(const column_pointer &c, bool noTableName = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!noTableName){ ss << "'" << this->impl.template find_table_name() << "'."; @@ -7502,7 +7514,7 @@ namespace sqlite_orm { * Takes select_t object and returns SELECT query string */ template - std::string string_from_expression(const internal::select_t &sel, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const internal::select_t &sel, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!is_base_of_template::value){ if(!sel.highest_level){ @@ -7558,19 +7570,19 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::cast_t &c, bool /*noTableName*/ = false, bool /*escape*/ = false) { + std::string string_from_expression(const conditions::cast_t &c, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - ss << static_cast(c) << " ( " << this->string_from_expression(c.expression) << " AS " << type_printer().print() << ") "; + ss << static_cast(c) << " ( " << this->string_from_expression(c.expression, noTableName, escape, ignoreBindable) << " AS " << type_printer().print() << ") "; return ss.str(); } template - typename std::enable_if::value, std::string>::type string_from_expression(const T &op, bool /*noTableName*/ = false, bool /*escape*/ = false) + typename std::enable_if::value, std::string>::type string_from_expression(const T &op, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { std::stringstream ss; - ss << this->string_from_expression(op.left) << " "; + ss << this->string_from_expression(op.left, noTableName, escape, ignoreBindable) << " "; ss << static_cast(op) << " "; - ss << this->string_from_expression(op.right) << " "; + ss << this->string_from_expression(op.right, noTableName, escape, ignoreBindable) << " "; return ss.str(); } From d9f04fda9e15f7687be1c5f1f1e3261423157aff Mon Sep 17 00:00:00 2001 From: fnc12 Date: Fri, 3 May 2019 19:38:24 +0300 Subject: [PATCH 086/232] changed journal mode underlying type from char to signed char --- dev/journal_mode.h | 2 +- dev/pragma.h | 2 +- include/sqlite_orm/sqlite_orm.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dev/journal_mode.h b/dev/journal_mode.h index a1f1a25c1..777defbb2 100644 --- a/dev/journal_mode.h +++ b/dev/journal_mode.h @@ -14,7 +14,7 @@ namespace sqlite_orm { #ifdef DELETE #undef DELETE #endif - enum class journal_mode : char { + enum class journal_mode : signed char { DELETE = 0, TRUNCATE = 1, PERSIST = 2, diff --git a/dev/pragma.h b/dev/pragma.h index 171f6f96f..375b158d8 100644 --- a/dev/pragma.h +++ b/dev/pragma.h @@ -56,7 +56,7 @@ namespace sqlite_orm { protected: storage_type &storage; int _synchronous = -1; - char _journal_mode = -1; // if != -1 stores static_cast(journal_mode) + signed char _journal_mode = -1; // if != -1 stores static_cast(journal_mode) template T get_pragma(const std::string &name) { diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index d3e26e732..4a280459a 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -4150,7 +4150,7 @@ namespace sqlite_orm { #ifdef DELETE #undef DELETE #endif - enum class journal_mode : char { + enum class journal_mode : signed char { DELETE = 0, TRUNCATE = 1, PERSIST = 2, @@ -6366,7 +6366,7 @@ namespace sqlite_orm { protected: storage_type &storage; int _synchronous = -1; - char _journal_mode = -1; // if != -1 stores static_cast(journal_mode) + signed char _journal_mode = -1; // if != -1 stores static_cast(journal_mode) template T get_pragma(const std::string &name) { From 461440f6c2a6ef41ac3b74f0b5f78d6a61ef1cdf Mon Sep 17 00:00:00 2001 From: fnc12 Date: Fri, 10 May 2019 22:07:02 +0300 Subject: [PATCH 087/232] added remove parameter pack --- dev/storage.h | 19 +++++++++++-------- include/sqlite_orm/sqlite_orm.h | 19 +++++++++++-------- tests/tests.cpp | 32 +++++++++++++++++++++++--------- 3 files changed, 45 insertions(+), 25 deletions(-) diff --git a/dev/storage.h b/dev/storage.h index 263e8333f..bd92d031f 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -1364,10 +1364,10 @@ namespace sqlite_orm { /** * Delete routine. * O is an object's type. Must be specified explicitly. - * @param id id of object to be removed. + * @param ids ids of object to be removed. */ - template - void remove(I id) { + template + void remove(Ids ...ids) { this->assert_mapped_type(); auto connection = this->get_or_create_connection(); @@ -1377,11 +1377,9 @@ namespace sqlite_orm { ss << "WHERE "; auto primaryKeyColumnNames = impl.table.primary_key_column_names(); for(size_t i = 0; i < primaryKeyColumnNames.size(); ++i) { - ss << "\"" << primaryKeyColumnNames[i] << "\"" << " = ?"; + ss << "\"" << primaryKeyColumnNames[i] << "\"" << " = ? "; if(i < primaryKeyColumnNames.size() - 1) { - ss << " AND "; - }else{ - ss << " "; + ss << "AND "; } } auto query = ss.str(); @@ -1389,7 +1387,12 @@ namespace sqlite_orm { if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; - statement_binder().bind(stmt, index++, id); + auto idsTuple = std::make_tuple(std::forward(ids)...); + constexpr const auto idsCount = std::tuple_size::value; + tuple_helper::iterator()(idsTuple, [stmt, &index](auto &v){ + using field_type = typename std::decay::type; + statement_binder().bind(stmt, index++, v); + }); if (sqlite3_step(stmt) == SQLITE_DONE) { // done.. }else{ diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 4a280459a..8b5356e37 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -7886,10 +7886,10 @@ namespace sqlite_orm { /** * Delete routine. * O is an object's type. Must be specified explicitly. - * @param id id of object to be removed. + * @param ids ids of object to be removed. */ - template - void remove(I id) { + template + void remove(Ids ...ids) { this->assert_mapped_type(); auto connection = this->get_or_create_connection(); @@ -7899,11 +7899,9 @@ namespace sqlite_orm { ss << "WHERE "; auto primaryKeyColumnNames = impl.table.primary_key_column_names(); for(size_t i = 0; i < primaryKeyColumnNames.size(); ++i) { - ss << "\"" << primaryKeyColumnNames[i] << "\"" << " = ?"; + ss << "\"" << primaryKeyColumnNames[i] << "\"" << " = ? "; if(i < primaryKeyColumnNames.size() - 1) { - ss << " AND "; - }else{ - ss << " "; + ss << "AND "; } } auto query = ss.str(); @@ -7911,7 +7909,12 @@ namespace sqlite_orm { if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; - statement_binder().bind(stmt, index++, id); + auto idsTuple = std::make_tuple(std::forward(ids)...); + constexpr const auto idsCount = std::tuple_size::value; + tuple_helper::iterator()(idsTuple, [stmt, &index](auto &v){ + using field_type = typename std::decay::type; + statement_binder().bind(stmt, index++, v); + }); if (sqlite3_step(stmt) == SQLITE_DONE) { // done.. }else{ diff --git a/tests/tests.cpp b/tests/tests.cpp index 495dad3e6..a2f3ddfd7 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -1565,11 +1565,8 @@ void testRemove() { { auto storage = make_storage("test_remove.sqlite", make_table("objects", - make_column("id", - &Object::id, - primary_key()), - make_column("name", - &Object::name))); + make_column("id", &Object::id, primary_key()), + make_column("name", &Object::name))); storage.sync_schema(); storage.remove_all(); @@ -1581,10 +1578,8 @@ void testRemove() { { auto storage = make_storage("test_remove.sqlite", make_table("objects", - make_column("id", - &Object::id), - make_column("name", - &Object::name), + make_column("id", &Object::id), + make_column("name", &Object::name), primary_key(&Object::id))); storage.sync_schema(); storage.remove_all(); @@ -1594,6 +1589,25 @@ void testRemove() { storage.remove(id1); assert(storage.count() == 0); } + { + auto storage = make_storage("", + make_table("objects", + make_column("id", &Object::id), + make_column("name", &Object::name), + primary_key(&Object::id, &Object::name))); + storage.sync_schema(); + storage.replace(Object{1, "Skillet"}); + assert(storage.count() == 1); + storage.remove(1, "Skillet"); + assert(storage.count() == 0); + + storage.replace(Object{1, "Skillet"}); + storage.replace(Object{2, "Paul Cless"}); + assert(storage.count() == 2); + storage.remove(1, "Skillet"); + assert(storage.count() == 1); + + } } void testInsert() { From 7ea0ec1ac622ed4d62e73371baf2ebbcd4587ffd Mon Sep 17 00:00:00 2001 From: Yevgeniy Zakharov Date: Thu, 16 May 2019 13:34:33 +0300 Subject: [PATCH 088/232] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bf55e1985..258f0c8e3 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ SQLite ORM light header only library for modern C++ | Branch | Travis | Appveyor | Coverity Scan | codecov.io | Website | | :----- | :----- | :------- | :------------ | :--------- | :------ | | [`master`](https://github.com/fcn12/sqlite_orm/tree/master) | [![Build Status](https://travis-ci.org/fnc12/sqlite_orm.svg?branch=master)](https://travis-ci.org/fcn12/sqlite_orm) | [![Build status](https://ci.appveyor.com/api/projects/status/github/fnc12/sqlite_orm?branch=master&svg=true)](https://ci.appveyor.com/project/fnc12/sqlite-orm/history) | | | [![Website](https://img.shields.io/badge/official-website-brightgreen.svg)](https://github.com/fcn12/sqlite_orm/) | -| [`dev`](https://github.com/fcn12/sqlite_orm/tree/dev) | [![Build Status](https://travis-ci.org/fnc12/sqlite_orm.svg?branch=dev)](https://travis-ci.org/fcn12/sqlite_orm) | [![Build status](https://ci.appveyor.com/api/projects/status/github/fnc12/sqlite_orm?branch=dev&svg=true)](https://ci.appveyor.com/project/fnc12/sqlite-orm/history) | | | [![Website](https://img.shields.io/badge/official-website-brightgreen.svg)](https://github.com/fcn12/sqlite_orm/tree/dev) | +| [`dev`](https://github.com/fcn12/sqlite_orm/tree/dev) | [![Build Status](https://travis-ci.org/fnc12/sqlite_orm.svg?branch=dev)](https://travis-ci.org/fcn12/sqlite_orm) | [![Build status](https://ci.appveyor.com/api/projects/status/github/fnc12/sqlite_orm?branch=dev&svg=true)](https://ci.appveyor.com/project/fnc12/sqlite-orm/history) | | | [![Website](https://img.shields.io/badge/official-website-brightgreen.svg)](https://github.com/fnc12/sqlite_orm/tree/dev) | # Advantages From 1b5cb6a27fecabc45c5cbc9f63f02f59ab836092 Mon Sep 17 00:00:00 2001 From: Seyyed Soroosh Hosseinalipour Date: Fri, 17 May 2019 03:20:23 +0430 Subject: [PATCH 089/232] Add cmake policy CMP0057 --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c8fd7bbe..ae4832b78 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,6 @@ cmake_minimum_required (VERSION 3.2) +cmake_policy(SET CMP0057 NEW) + set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) From 1f5a8fee02be66ec7673fddf1df4cb297e55062f Mon Sep 17 00:00:00 2001 From: fnc12 Date: Fri, 17 May 2019 15:33:50 +0300 Subject: [PATCH 090/232] fixed replace with private class members and added unit tests --- dev/storage.h | 26 +++++++------- include/sqlite_orm/sqlite_orm.h | 26 +++++++------- tests/tests.cpp | 63 +++++++++++++++++++++------------ 3 files changed, 69 insertions(+), 46 deletions(-) diff --git a/dev/storage.h b/dev/storage.h index bd92d031f..a7088439d 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -2488,15 +2488,16 @@ namespace sqlite_orm { if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; - impl.table.for_each_column([&o, &index, &stmt] (auto c) { - using field_type = typename decltype(c)::field_type; - const field_type *value = nullptr; + impl.table.for_each_column([&o, &index, &stmt] (auto &c) { + using column_type = typename std::decay::type; + using field_type = typename column_type::field_type; if(c.member_pointer){ - value = &(o.*c.member_pointer); + statement_binder().bind(stmt, index++, o.*c.member_pointer); }else{ - value = &((o).*(c.getter))(); + using getter_type = typename column_type::getter_type; + field_value_holder valueHolder{((o).*(c.getter))()}; + statement_binder().bind(stmt, index++, valueHolder.value); } - statement_binder().bind(stmt, index++, *value); }); if (sqlite3_step(stmt) == SQLITE_DONE) { //.. @@ -2559,15 +2560,16 @@ namespace sqlite_orm { auto index = 1; for(auto it = from; it != to; ++it) { auto &o = *it; - impl.table.for_each_column([&o, &index, &stmt] (auto c) { - using field_type = typename decltype(c)::field_type; - const field_type *value = nullptr; + impl.table.for_each_column([&o, &index, &stmt] (auto &c) { + using column_type = typename std::decay::type; + using field_type = typename column_type::field_type; if(c.member_pointer){ - value = &(o.*c.member_pointer); + statement_binder().bind(stmt, index++, o.*c.member_pointer); }else{ - value = &((o).*(c.getter))(); + using getter_type = typename column_type::getter_type; + field_value_holder valueHolder{((o).*(c.getter))()}; + statement_binder().bind(stmt, index++, valueHolder.value); } - statement_binder().bind(stmt, index++, *value); }); } if (sqlite3_step(stmt) == SQLITE_DONE) { diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 8b5356e37..9c71d36cb 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -9010,15 +9010,16 @@ namespace sqlite_orm { if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; - impl.table.for_each_column([&o, &index, &stmt] (auto c) { - using field_type = typename decltype(c)::field_type; - const field_type *value = nullptr; + impl.table.for_each_column([&o, &index, &stmt] (auto &c) { + using column_type = typename std::decay::type; + using field_type = typename column_type::field_type; if(c.member_pointer){ - value = &(o.*c.member_pointer); + statement_binder().bind(stmt, index++, o.*c.member_pointer); }else{ - value = &((o).*(c.getter))(); + using getter_type = typename column_type::getter_type; + field_value_holder valueHolder{((o).*(c.getter))()}; + statement_binder().bind(stmt, index++, valueHolder.value); } - statement_binder().bind(stmt, index++, *value); }); if (sqlite3_step(stmt) == SQLITE_DONE) { //.. @@ -9081,15 +9082,16 @@ namespace sqlite_orm { auto index = 1; for(auto it = from; it != to; ++it) { auto &o = *it; - impl.table.for_each_column([&o, &index, &stmt] (auto c) { - using field_type = typename decltype(c)::field_type; - const field_type *value = nullptr; + impl.table.for_each_column([&o, &index, &stmt] (auto &c) { + using column_type = typename std::decay::type; + using field_type = typename column_type::field_type; if(c.member_pointer){ - value = &(o.*c.member_pointer); + statement_binder().bind(stmt, index++, o.*c.member_pointer); }else{ - value = &((o).*(c.getter))(); + using getter_type = typename column_type::getter_type; + field_value_holder valueHolder{((o).*(c.getter))()}; + statement_binder().bind(stmt, index++, valueHolder.value); } - statement_binder().bind(stmt, index++, *value); }); } if (sqlite3_step(stmt) == SQLITE_DONE) { diff --git a/tests/tests.cpp b/tests/tests.cpp index a2f3ddfd7..5a900ac65 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -1690,17 +1690,43 @@ void testReplace() { int id; std::string name; }; + + struct User { + + User(int id_, std::string name_): id(id_), name(move(name_)) {} + + int getId() const { + return this->id; + } + + void setId(int id) { + this->id = id; + } + + std::string getName() const { + return this->name; + } + + void setName(std::string name) { + this->name = move(name); + } + + private: + int id = 0; + std::string name; + }; auto storage = make_storage("test_replace.sqlite", make_table("objects", - make_column("id", - &Object::id, - primary_key()), - make_column("name", - &Object::name))); + make_column("id", &Object::id, primary_key()), + make_column("name", &Object::name)), + make_table("users", + make_column("id", &User::getId, &User::setId, primary_key()), + make_column("name", &User::setName, &User::getName))); storage.sync_schema(); storage.remove_all(); + storage.remove_all(); storage.replace(Object{ 100, @@ -1745,6 +1771,10 @@ void testReplace() { std::vector emptyVector; storage.replace_range(emptyVector.begin(), emptyVector.end()); + + + assert(storage.count() == 0); + storage.replace(User{10, "Daddy Yankee"}); } void testEmptyStorage() { @@ -2166,25 +2196,14 @@ void testAggregateFunctions() { auto storage = make_storage("test_aggregate.sqlite", make_table("users", - make_column("id", - &User::id, - primary_key()), - make_column("name", - &User::name), - make_column("age", - &User::age))); + make_column("id", &User::id, primary_key()), + make_column("name", &User::name), + make_column("age", &User::age))); auto storage2 = make_storage("test_aggregate.sqlite", make_table("users", - make_column("id", - &User::getId, - &User::setId, - primary_key()), - make_column("name", - &User::getName, - &User::setName), - make_column("age", - &User::getAge, - &User::setAge))); + make_column("id", &User::getId, &User::setId, primary_key()), + make_column("name", &User::getName, &User::setName), + make_column("age", &User::getAge, &User::setAge))); storage.sync_schema(); storage.remove_all(); From e02c49944feda296e442e67d3043a13a1cb722fe Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sat, 25 May 2019 00:38:15 +0300 Subject: [PATCH 091/232] refactored string_from_expression arguments --- dev/pragma.h | 2 +- dev/storage.h | 167 +++++++++++++++---------------- include/sqlite_orm/sqlite_orm.h | 169 ++++++++++++++++---------------- tests/tests.cpp | 22 +++++ 4 files changed, 194 insertions(+), 166 deletions(-) diff --git a/dev/pragma.h b/dev/pragma.h index 375b158d8..35519d76d 100644 --- a/dev/pragma.h +++ b/dev/pragma.h @@ -91,7 +91,7 @@ namespace sqlite_orm { db = connection->get_db(); } std::stringstream ss; - ss << "PRAGMA " << name << " = " << this->storage.string_from_expression(value); + ss << "PRAGMA " << name << " = " << this->storage.string_from_expression(value, false, false); auto query = ss.str(); auto rc = sqlite3_exec(db, query.c_str(), nullptr, nullptr, nullptr); if(rc != SQLITE_OK) { diff --git a/dev/storage.h b/dev/storage.h index f9b8b605d..2e785c52a 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -296,7 +296,7 @@ namespace sqlite_orm { } template - typename std::enable_if::value, std::string>::type string_from_expression(const T &t, bool /*noTableName*/ = false, bool escape = false, bool ignoreBindable = false) { + typename std::enable_if::value, std::string>::type string_from_expression(const T &t, bool /*noTableName*/, bool escape, bool ignoreBindable = false) { auto isNullable = type_is_nullable::value; if(isNullable && !type_is_nullable()(t)){ return "NULL"; @@ -323,27 +323,27 @@ namespace sqlite_orm { } template - std::string string_from_expression(const alias_holder &, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const alias_holder &, bool /*noTableName*/, bool /*escape*/, bool /*ignoreBindable*/ = false) { return T::get(); } template - std::string string_from_expression(const as_t &als, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const as_t &als, bool noTableName, bool escape, bool ignoreBindable = false) { auto tableAliasString = alias_extractor::get(); return this->string_from_expression(als.expression, noTableName, escape, ignoreBindable) + " AS " + tableAliasString; } template - std::string string_from_expression(const alias_column_t &als, bool noTableName = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const alias_column_t &als, bool noTableName, bool escape, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!noTableName){ ss << "'" << T::get() << "'."; } - ss << this->string_from_expression(als.column, true); + ss << this->string_from_expression(als.column, true, escape); return ss.str(); } - std::string string_from_expression(const std::string &t, bool /*noTableName*/ = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const std::string &t, bool /*noTableName*/, bool escape, bool ignoreBindable = false) { std::stringstream ss; if(ignoreBindable){ std::string text = t; @@ -357,7 +357,7 @@ namespace sqlite_orm { return ss.str(); } - std::string string_from_expression(const char *t, bool /*noTableName*/ = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const char *t, bool /*noTableName*/, bool escape, bool ignoreBindable = false) { std::stringstream ss; if(ignoreBindable){ std::string text = t; @@ -372,7 +372,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(F O::*m, bool noTableName = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(F O::*m, bool noTableName, bool escape, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!noTableName){ ss << "'" << this->impl.template find_table_name() << "'."; @@ -381,20 +381,20 @@ namespace sqlite_orm { return ss.str(); } - std::string string_from_expression(const rowid_t &rid, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const rowid_t &rid, bool /*noTableName*/, bool /*escape*/, bool /*ignoreBindable*/ = false) { return static_cast(rid); } - std::string string_from_expression(const oid_t &rid, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const oid_t &rid, bool /*noTableName*/, bool /*escape*/, bool /*ignoreBindable*/ = false) { return static_cast(rid); } - std::string string_from_expression(const _rowid_t &rid, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const _rowid_t &rid, bool /*noTableName*/, bool /*escape*/, bool /*ignoreBindable*/ = false) { return static_cast(rid); } template - std::string string_from_expression(const table_rowid_t &rid, bool noTableName = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const table_rowid_t &rid, bool noTableName, bool /*escape*/, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!noTableName){ ss << "'" << this->impl.template find_table_name() << "'."; @@ -404,7 +404,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const table_oid_t &rid, bool noTableName = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const table_oid_t &rid, bool noTableName, bool /*escape*/, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!noTableName){ ss << "'" << this->impl.template find_table_name() << "'."; @@ -414,7 +414,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const table__rowid_t &rid, bool noTableName = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const table__rowid_t &rid, bool noTableName, bool /*escape*/, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!noTableName){ ss << "'" << this->impl.template find_table_name() << "'."; @@ -424,7 +424,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const aggregate_functions::group_concat_double_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const aggregate_functions::group_concat_double_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); auto expr2 = this->string_from_expression(f.y, noTableName, escape, ignoreBindable); @@ -433,7 +433,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const aggregate_functions::group_concat_single_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const aggregate_functions::group_concat_single_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; @@ -441,7 +441,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conc_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const conc_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); @@ -450,7 +450,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const add_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const add_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); @@ -459,7 +459,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const sub_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const sub_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); @@ -468,7 +468,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const mul_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const mul_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); @@ -477,7 +477,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const div_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const div_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); @@ -486,7 +486,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const mod_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const mod_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); @@ -495,15 +495,15 @@ namespace sqlite_orm { } template - std::string string_from_expression(const aggregate_functions::min_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const aggregate_functions::min_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.t); + auto expr = this->string_from_expression(f.t, false); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const aggregate_functions::max_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const aggregate_functions::max_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; @@ -511,7 +511,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const aggregate_functions::total_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const aggregate_functions::total_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; @@ -519,7 +519,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const aggregate_functions::sum_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const aggregate_functions::sum_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; @@ -527,18 +527,18 @@ namespace sqlite_orm { } template - std::string string_from_expression(const aggregate_functions::count_asterisk_t &, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const aggregate_functions::count_asterisk_t &, bool noTableName, bool escape, bool ignoreBindable = false) { return this->string_from_expression(aggregate_functions::count_asterisk_without_type{}, noTableName, escape, ignoreBindable); } - std::string string_from_expression(const aggregate_functions::count_asterisk_without_type &f, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const aggregate_functions::count_asterisk_without_type &f, bool /*noTableName*/, bool /*escape*/, bool /*ignoreBindable*/ = false) { std::stringstream ss; ss << static_cast(f) << "(*) "; return ss.str(); } template - std::string string_from_expression(const aggregate_functions::count_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const aggregate_functions::count_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; @@ -546,7 +546,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const aggregate_functions::avg_t &a, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const aggregate_functions::avg_t &a, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(a.t, noTableName, escape, ignoreBindable); ss << static_cast(a) << "(" << expr << ") "; @@ -554,7 +554,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const distinct_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const distinct_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; @@ -562,7 +562,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const all_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const all_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; @@ -570,7 +570,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const core_functions::rtrim_double_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const core_functions::rtrim_double_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); auto expr2 = this->string_from_expression(f.y, noTableName, escape, ignoreBindable); @@ -579,7 +579,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const core_functions::rtrim_single_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const core_functions::rtrim_single_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; @@ -587,7 +587,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const core_functions::ltrim_double_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const core_functions::ltrim_double_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); auto expr2 = this->string_from_expression(f.y, noTableName, escape, ignoreBindable); @@ -596,7 +596,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const core_functions::ltrim_single_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const core_functions::ltrim_single_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; @@ -604,7 +604,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const core_functions::trim_double_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const core_functions::trim_double_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); auto expr2 = this->string_from_expression(f.y, noTableName, escape, ignoreBindable); @@ -613,21 +613,21 @@ namespace sqlite_orm { } template - std::string string_from_expression(const core_functions::trim_single_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const core_functions::trim_single_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } - std::string string_from_expression(const core_functions::changes_t &ch, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const core_functions::changes_t &ch, bool /*noTableName*/, bool /*escape*/, bool /*ignoreBindable*/ = false) { std::stringstream ss; ss << static_cast(ch) << "() "; return ss.str(); } template - std::string string_from_expression(const core_functions::length_t &len, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const core_functions::length_t &len, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(len.t, noTableName, escape, ignoreBindable); ss << static_cast(len) << "(" << expr << ") "; @@ -635,19 +635,19 @@ namespace sqlite_orm { } template - std::string string_from_expression(const core_functions::datetime_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const core_functions::datetime_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); using tuple_t = std::tuple; tuple_helper::iterator::value - 1, Args...>()(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ - ss << ", " << this->string_from_expression(v, noTableName, escape); + ss << ", " << this->string_from_expression(v, noTableName, escape, ignoreBindable); }); ss << ") "; return ss.str(); } template - std::string string_from_expression(const core_functions::date_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const core_functions::date_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); using tuple_t = std::tuple; @@ -659,7 +659,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const core_functions::julianday_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const core_functions::julianday_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); using tuple_t = std::tuple; @@ -670,7 +670,7 @@ namespace sqlite_orm { return ss.str(); } - std::string string_from_expression(const core_functions::random_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const core_functions::random_t &f, bool /*noTableName*/, bool /*escape*/, bool /*ignoreBindable*/ = false) { std::stringstream ss; ss << static_cast(f) << "() "; return ss.str(); @@ -679,7 +679,7 @@ namespace sqlite_orm { #if SQLITE_VERSION_NUMBER >= 3007016 template - std::string string_from_expression(const core_functions::char_t_ &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const core_functions::char_t_ &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; using tuple_t = decltype(f.args); std::vector args; @@ -704,7 +704,7 @@ namespace sqlite_orm { #endif template - std::string string_from_expression(const core_functions::upper_t &a, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const core_functions::upper_t &a, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(a.t, noTableName, escape, ignoreBindable); ss << static_cast(a) << "(" << expr << ") "; @@ -712,7 +712,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const core_functions::lower_t &a, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const core_functions::lower_t &a, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(a.t, noTableName, escape, ignoreBindable); ss << static_cast(a) << "(" << expr << ") "; @@ -720,7 +720,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const core_functions::abs_t &a, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const core_functions::abs_t &a, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(a.t, noTableName, escape, ignoreBindable); ss << static_cast(a) << "(" << expr << ") "; @@ -728,7 +728,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const column_pointer &c, bool noTableName = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const column_pointer &c, bool noTableName, bool /*escape*/, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!noTableName){ ss << "'" << this->impl.template find_table_name() << "'."; @@ -740,7 +740,7 @@ namespace sqlite_orm { template std::vector get_column_names(const T &t) { - auto columnName = this->string_from_expression(t); + auto columnName = this->string_from_expression(t, false, false); if(columnName.length()){ return {columnName}; }else{ @@ -760,7 +760,7 @@ namespace sqlite_orm { std::vector columnNames; columnNames.reserve(static_cast(cols.count())); cols.for_each([&columnNames, this](auto &m) { - auto columnName = this->string_from_expression(m); + auto columnName = this->string_from_expression(m, false, false); if(columnName.length()){ columnNames.push_back(columnName); }else{ @@ -774,7 +774,7 @@ namespace sqlite_orm { * Takes select_t object and returns SELECT query string */ template - std::string string_from_expression(const internal::select_t &sel, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const internal::select_t &sel, bool /*noTableName*/, bool /*escape*/, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!is_base_of_template::value){ if(!sel.highest_level){ @@ -830,14 +830,14 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::cast_t &c, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const conditions::cast_t &c, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; ss << static_cast(c) << " ( " << this->string_from_expression(c.expression, noTableName, escape, ignoreBindable) << " AS " << type_printer().print() << ") "; return ss.str(); } template - typename std::enable_if::value, std::string>::type string_from_expression(const T &op, bool noTableName = false, bool escape = false, bool ignoreBindable = false) + typename std::enable_if::value, std::string>::type string_from_expression(const T &op, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; ss << this->string_from_expression(op.left, noTableName, escape, ignoreBindable) << " "; @@ -847,16 +847,16 @@ namespace sqlite_orm { } template - std::string process_where(const conditions::is_null_t &c) { + std::string process_where(const conditions::is_null_t &c, bool ignoreBindable = false) { std::stringstream ss; - ss << this->string_from_expression(c.t) << " " << static_cast(c) << " "; + ss << this->string_from_expression(c.t, false, false) << " " << static_cast(c) << " "; return ss.str(); } template std::string process_where(const conditions::is_not_null_t &c) { std::stringstream ss; - ss << this->string_from_expression(c.t) << " " << static_cast(c) << " "; + ss << this->string_from_expression(c.t, false, false) << " " << static_cast(c) << " "; return ss.str(); } @@ -885,13 +885,13 @@ namespace sqlite_orm { template typename std::enable_if::value, std::string>::type process_where(const T &c) { - return this->string_from_expression(c); + return this->string_from_expression(c, false, false); } template typename std::enable_if::value, std::string>::type process_where(const C &c) { - auto leftString = this->string_from_expression(c.l, false, true); - auto rightString = this->string_from_expression(c.r, false, true); + auto leftString = this->string_from_expression(c.l, false, true, true); + auto rightString = this->string_from_expression(c.r, false, true, true); std::stringstream ss; ss << leftString << " " << static_cast(c) << " " << rightString; return ss.str(); @@ -912,9 +912,9 @@ namespace sqlite_orm { template std::string process_where(const conditions::in_t &inCondition) { std::stringstream ss; - auto leftString = this->string_from_expression(inCondition.l); + auto leftString = this->string_from_expression(inCondition.l, false, false); ss << leftString << " " << static_cast(inCondition) << " "; - ss << this->string_from_expression(inCondition.arg); + ss << this->string_from_expression(inCondition.arg, false); ss << " "; return ss.str(); } @@ -922,11 +922,11 @@ namespace sqlite_orm { template std::string process_where(const conditions::in_t> &inCondition) { std::stringstream ss; - auto leftString = this->string_from_expression(inCondition.l); + auto leftString = this->string_from_expression(inCondition.l, false, false); ss << leftString << " " << static_cast(inCondition) << " ( "; for(size_t index = 0; index < inCondition.arg.size(); ++index) { auto &value = inCondition.arg[index]; - ss << " " << this->string_from_expression(value); + ss << " " << this->string_from_expression(value, false, false); if(index < inCondition.arg.size() - 1) { ss << ", "; } @@ -938,29 +938,31 @@ namespace sqlite_orm { template std::string process_where(const conditions::like_t &l) { std::stringstream ss; - ss << this->string_from_expression(l.a) << " " << static_cast(l) << " " << this->string_from_expression(l.t) << " "; + ss << this->string_from_expression(l.a, false, false) << " "; + ss << static_cast(l) << " "; + ss << this->string_from_expression(l.t, false, false) << " "; return ss.str(); } template std::string process_where(const conditions::between_t &bw) { std::stringstream ss; - auto expr = this->string_from_expression(bw.expr); - ss << expr << " " << static_cast(bw) << " " << this->string_from_expression(bw.b1) << " AND " << this->string_from_expression(bw.b2) << " "; + auto expr = this->string_from_expression(bw.expr, false, false); + ss << expr << " " << static_cast(bw) << " " << this->string_from_expression(bw.b1, false, false) << " AND " << this->string_from_expression(bw.b2, false, false) << " "; return ss.str(); } template std::string process_where(const conditions::exists_t &e) { std::stringstream ss; - ss << static_cast(e) << " " << this->string_from_expression(e.t) << " "; + ss << static_cast(e) << " " << this->string_from_expression(e.t, false, false) << " "; return ss.str(); } template std::string process_order_by(const conditions::order_by_t &orderBy) { std::stringstream ss; - auto columnName = this->string_from_expression(orderBy.o); + auto columnName = this->string_from_expression(orderBy.o, false, false); ss << columnName << " "; if(orderBy._collate_argument.length()){ ss << "COLLATE " << orderBy._collate_argument << " "; @@ -1081,7 +1083,7 @@ namespace sqlite_orm { std::vector expressions; using tuple_t = std::tuple; tuple_helper::iterator::value - 1, Args...>()(groupBy.args, [&expressions, this](auto &v){ - auto expression = this->string_from_expression(v); + auto expression = this->string_from_expression(v, false, false); expressions.push_back(expression); }); ss << static_cast(groupBy) << " "; @@ -1355,7 +1357,7 @@ namespace sqlite_orm { std::vector setPairs; set.for_each([this, &setPairs](auto &asgn){ std::stringstream sss; - sss << this->string_from_expression(asgn.l, true) << " = " << this->string_from_expression(asgn.r) << " "; + sss << this->string_from_expression(asgn.l, true, false) << " = " << this->string_from_expression(asgn.r, false, false) << " "; setPairs.push_back(sss.str()); }); auto setPairsCount = setPairs.size(); @@ -1713,7 +1715,7 @@ namespace sqlite_orm { std::string res; std::stringstream ss; ss << "SELECT " << static_cast(sqlite_orm::group_concat(0)) << "("; - auto columnName = this->string_from_expression(m); + auto columnName = this->string_from_expression(m, false, false); if(columnName.length()){ ss << columnName; if(y){ @@ -2005,7 +2007,7 @@ namespace sqlite_orm { int res = 0; std::stringstream ss; ss << "SELECT " << static_cast(sqlite_orm::count(0)) << "("; - auto columnName = this->string_from_expression(m); + auto columnName = this->string_from_expression(m, false, false); if(columnName.length()){ ss << columnName << ") FROM '"<< impl.table.name << "' "; this->process_conditions(ss, std::make_tuple(std::forward(args)...)); @@ -2042,7 +2044,7 @@ namespace sqlite_orm { double res = 0; std::stringstream ss; ss << "SELECT " << static_cast(sqlite_orm::avg(0)) << "("; - auto columnName = this->string_from_expression(m); + auto columnName = this->string_from_expression(m, false, false); if(columnName.length()){ ss << columnName << ") FROM '"<< impl.table.name << "' "; this->process_conditions(ss, std::make_tuple(std::forward(args)...)); @@ -2112,7 +2114,7 @@ namespace sqlite_orm { std::unique_ptr res; std::stringstream ss; ss << "SELECT " << static_cast(sqlite_orm::max(0)) << "("; - auto columnName = this->string_from_expression(m); + auto columnName = this->string_from_expression(m, false, false); if(columnName.length()){ ss << columnName << ") FROM '" << impl.table.name << "' "; this->process_conditions(ss, std::make_tuple(std::forward(args)...)); @@ -2151,7 +2153,7 @@ namespace sqlite_orm { std::unique_ptr res; std::stringstream ss; ss << "SELECT " << static_cast(sqlite_orm::min(0)) << "("; - auto columnName = this->string_from_expression(m); + auto columnName = this->string_from_expression(m, false, false); if(columnName.length()){ ss << columnName << ") FROM '" << impl.table.name << "' "; this->process_conditions(ss, std::make_tuple(std::forward(args)...)); @@ -2190,7 +2192,7 @@ namespace sqlite_orm { std::unique_ptr res; std::stringstream ss; ss << "SELECT " << static_cast(sqlite_orm::sum(0)) << "("; - auto columnName = this->string_from_expression(m); + auto columnName = this->string_from_expression(m, false, false); if(columnName.length()){ ss << columnName << ") FROM '"<< impl.table.name << "' "; this->process_conditions(ss, std::make_tuple(std::forward(args)...)); @@ -2226,7 +2228,7 @@ namespace sqlite_orm { double res = 0; std::stringstream ss; ss << "SELECT " << static_cast(sqlite_orm::total(0)) << "("; - auto columnName = this->string_from_expression(m); + auto columnName = this->string_from_expression(m, false, false); if(!columnName.empty()){ ss << columnName << ") "; auto tableNamesSet = this->parse_table_names(m); @@ -2274,7 +2276,8 @@ namespace sqlite_orm { static_assert(!is_base_of_template::value || std::tuple_size>::value == 0, "Cannot use args with a compound operator"); using select_type = select_t; - auto query = this->string_from_expression(select_type{std::move(m), std::make_tuple(std::forward(args)...), true}); + auto query = this->string_from_expression(select_type{std::move(m), std::make_tuple(std::forward(args)...), true}, + false, false, true); auto connection = this->get_or_create_connection(); sqlite3_stmt *stmt; if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { @@ -2453,7 +2456,7 @@ namespace sqlite_orm { std::vector columnNames; columnNames.reserve(colsCount); cols.for_each([&columnNames, this](auto &m) { - auto columnName = this->string_from_expression(m, true); + auto columnName = this->string_from_expression(m, true, false); if(columnName.length()){ columnNames.push_back(columnName); }else{ diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 453be0733..070d3df1f 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -6403,7 +6403,7 @@ namespace sqlite_orm { db = connection->get_db(); } std::stringstream ss; - ss << "PRAGMA " << name << " = " << this->storage.string_from_expression(value); + ss << "PRAGMA " << name << " = " << this->storage.string_from_expression(value, false, false); auto query = ss.str(); auto rc = sqlite3_exec(db, query.c_str(), nullptr, nullptr, nullptr); if(rc != SQLITE_OK) { @@ -7036,7 +7036,7 @@ namespace sqlite_orm { } template - typename std::enable_if::value, std::string>::type string_from_expression(const T &t, bool /*noTableName*/ = false, bool escape = false, bool ignoreBindable = false) { + typename std::enable_if::value, std::string>::type string_from_expression(const T &t, bool /*noTableName*/, bool escape, bool ignoreBindable = false) { auto isNullable = type_is_nullable::value; if(isNullable && !type_is_nullable()(t)){ return "NULL"; @@ -7063,27 +7063,27 @@ namespace sqlite_orm { } template - std::string string_from_expression(const alias_holder &, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const alias_holder &, bool /*noTableName*/, bool /*escape*/, bool /*ignoreBindable*/ = false) { return T::get(); } template - std::string string_from_expression(const as_t &als, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const as_t &als, bool noTableName, bool escape, bool ignoreBindable = false) { auto tableAliasString = alias_extractor::get(); return this->string_from_expression(als.expression, noTableName, escape, ignoreBindable) + " AS " + tableAliasString; } template - std::string string_from_expression(const alias_column_t &als, bool noTableName = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const alias_column_t &als, bool noTableName, bool escape, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!noTableName){ ss << "'" << T::get() << "'."; } - ss << this->string_from_expression(als.column, true); + ss << this->string_from_expression(als.column, true, escape); return ss.str(); } - std::string string_from_expression(const std::string &t, bool /*noTableName*/ = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const std::string &t, bool /*noTableName*/, bool escape, bool ignoreBindable = false) { std::stringstream ss; if(ignoreBindable){ std::string text = t; @@ -7097,7 +7097,7 @@ namespace sqlite_orm { return ss.str(); } - std::string string_from_expression(const char *t, bool /*noTableName*/ = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const char *t, bool /*noTableName*/, bool escape, bool ignoreBindable = false) { std::stringstream ss; if(ignoreBindable){ std::string text = t; @@ -7112,7 +7112,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(F O::*m, bool noTableName = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(F O::*m, bool noTableName, bool escape, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!noTableName){ ss << "'" << this->impl.template find_table_name() << "'."; @@ -7121,20 +7121,20 @@ namespace sqlite_orm { return ss.str(); } - std::string string_from_expression(const rowid_t &rid, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const rowid_t &rid, bool /*noTableName*/, bool /*escape*/, bool /*ignoreBindable*/ = false) { return static_cast(rid); } - std::string string_from_expression(const oid_t &rid, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const oid_t &rid, bool /*noTableName*/, bool /*escape*/, bool /*ignoreBindable*/ = false) { return static_cast(rid); } - std::string string_from_expression(const _rowid_t &rid, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const _rowid_t &rid, bool /*noTableName*/, bool /*escape*/, bool /*ignoreBindable*/ = false) { return static_cast(rid); } template - std::string string_from_expression(const table_rowid_t &rid, bool noTableName = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const table_rowid_t &rid, bool noTableName, bool /*escape*/, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!noTableName){ ss << "'" << this->impl.template find_table_name() << "'."; @@ -7144,7 +7144,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const table_oid_t &rid, bool noTableName = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const table_oid_t &rid, bool noTableName, bool /*escape*/, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!noTableName){ ss << "'" << this->impl.template find_table_name() << "'."; @@ -7154,7 +7154,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const table__rowid_t &rid, bool noTableName = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const table__rowid_t &rid, bool noTableName, bool /*escape*/, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!noTableName){ ss << "'" << this->impl.template find_table_name() << "'."; @@ -7164,7 +7164,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const aggregate_functions::group_concat_double_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const aggregate_functions::group_concat_double_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); auto expr2 = this->string_from_expression(f.y, noTableName, escape, ignoreBindable); @@ -7173,7 +7173,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const aggregate_functions::group_concat_single_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const aggregate_functions::group_concat_single_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; @@ -7181,7 +7181,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conc_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const conc_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); @@ -7190,7 +7190,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const add_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const add_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); @@ -7199,7 +7199,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const sub_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const sub_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); @@ -7208,7 +7208,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const mul_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const mul_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); @@ -7217,7 +7217,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const div_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const div_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); @@ -7226,7 +7226,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const mod_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const mod_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); @@ -7235,15 +7235,15 @@ namespace sqlite_orm { } template - std::string string_from_expression(const aggregate_functions::min_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const aggregate_functions::min_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.t); + auto expr = this->string_from_expression(f.t, false); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } template - std::string string_from_expression(const aggregate_functions::max_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const aggregate_functions::max_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; @@ -7251,7 +7251,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const aggregate_functions::total_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const aggregate_functions::total_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; @@ -7259,7 +7259,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const aggregate_functions::sum_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const aggregate_functions::sum_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; @@ -7267,18 +7267,18 @@ namespace sqlite_orm { } template - std::string string_from_expression(const aggregate_functions::count_asterisk_t &, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const aggregate_functions::count_asterisk_t &, bool noTableName, bool escape, bool ignoreBindable = false) { return this->string_from_expression(aggregate_functions::count_asterisk_without_type{}, noTableName, escape, ignoreBindable); } - std::string string_from_expression(const aggregate_functions::count_asterisk_without_type &f, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const aggregate_functions::count_asterisk_without_type &f, bool /*noTableName*/, bool /*escape*/, bool /*ignoreBindable*/ = false) { std::stringstream ss; ss << static_cast(f) << "(*) "; return ss.str(); } template - std::string string_from_expression(const aggregate_functions::count_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const aggregate_functions::count_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; @@ -7286,7 +7286,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const aggregate_functions::avg_t &a, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const aggregate_functions::avg_t &a, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(a.t, noTableName, escape, ignoreBindable); ss << static_cast(a) << "(" << expr << ") "; @@ -7294,7 +7294,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const distinct_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const distinct_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; @@ -7302,7 +7302,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const all_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const all_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; @@ -7310,7 +7310,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const core_functions::rtrim_double_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const core_functions::rtrim_double_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); auto expr2 = this->string_from_expression(f.y, noTableName, escape, ignoreBindable); @@ -7319,7 +7319,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const core_functions::rtrim_single_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const core_functions::rtrim_single_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; @@ -7327,7 +7327,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const core_functions::ltrim_double_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const core_functions::ltrim_double_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); auto expr2 = this->string_from_expression(f.y, noTableName, escape, ignoreBindable); @@ -7336,7 +7336,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const core_functions::ltrim_single_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const core_functions::ltrim_single_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; @@ -7344,7 +7344,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const core_functions::trim_double_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const core_functions::trim_double_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); auto expr2 = this->string_from_expression(f.y, noTableName, escape, ignoreBindable); @@ -7353,21 +7353,21 @@ namespace sqlite_orm { } template - std::string string_from_expression(const core_functions::trim_single_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const core_functions::trim_single_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } - std::string string_from_expression(const core_functions::changes_t &ch, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const core_functions::changes_t &ch, bool /*noTableName*/, bool /*escape*/, bool /*ignoreBindable*/ = false) { std::stringstream ss; ss << static_cast(ch) << "() "; return ss.str(); } template - std::string string_from_expression(const core_functions::length_t &len, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const core_functions::length_t &len, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(len.t, noTableName, escape, ignoreBindable); ss << static_cast(len) << "(" << expr << ") "; @@ -7375,19 +7375,19 @@ namespace sqlite_orm { } template - std::string string_from_expression(const core_functions::datetime_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const core_functions::datetime_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); using tuple_t = std::tuple; tuple_helper::iterator::value - 1, Args...>()(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ - ss << ", " << this->string_from_expression(v, noTableName, escape); + ss << ", " << this->string_from_expression(v, noTableName, escape, ignoreBindable); }); ss << ") "; return ss.str(); } template - std::string string_from_expression(const core_functions::date_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const core_functions::date_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); using tuple_t = std::tuple; @@ -7399,7 +7399,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const core_functions::julianday_t &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const core_functions::julianday_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); using tuple_t = std::tuple; @@ -7410,7 +7410,7 @@ namespace sqlite_orm { return ss.str(); } - std::string string_from_expression(const core_functions::random_t &f, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const core_functions::random_t &f, bool /*noTableName*/, bool /*escape*/, bool /*ignoreBindable*/ = false) { std::stringstream ss; ss << static_cast(f) << "() "; return ss.str(); @@ -7419,7 +7419,7 @@ namespace sqlite_orm { #if SQLITE_VERSION_NUMBER >= 3007016 template - std::string string_from_expression(const core_functions::char_t_ &f, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const core_functions::char_t_ &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; using tuple_t = decltype(f.args); std::vector args; @@ -7444,7 +7444,7 @@ namespace sqlite_orm { #endif template - std::string string_from_expression(const core_functions::upper_t &a, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const core_functions::upper_t &a, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(a.t, noTableName, escape, ignoreBindable); ss << static_cast(a) << "(" << expr << ") "; @@ -7452,7 +7452,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const core_functions::lower_t &a, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const core_functions::lower_t &a, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(a.t, noTableName, escape, ignoreBindable); ss << static_cast(a) << "(" << expr << ") "; @@ -7460,7 +7460,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const core_functions::abs_t &a, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const core_functions::abs_t &a, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; auto expr = this->string_from_expression(a.t, noTableName, escape, ignoreBindable); ss << static_cast(a) << "(" << expr << ") "; @@ -7468,7 +7468,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(const column_pointer &c, bool noTableName = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const column_pointer &c, bool noTableName, bool /*escape*/, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!noTableName){ ss << "'" << this->impl.template find_table_name() << "'."; @@ -7480,7 +7480,7 @@ namespace sqlite_orm { template std::vector get_column_names(const T &t) { - auto columnName = this->string_from_expression(t); + auto columnName = this->string_from_expression(t, false, false); if(columnName.length()){ return {columnName}; }else{ @@ -7500,7 +7500,7 @@ namespace sqlite_orm { std::vector columnNames; columnNames.reserve(static_cast(cols.count())); cols.for_each([&columnNames, this](auto &m) { - auto columnName = this->string_from_expression(m); + auto columnName = this->string_from_expression(m, false, false); if(columnName.length()){ columnNames.push_back(columnName); }else{ @@ -7514,7 +7514,7 @@ namespace sqlite_orm { * Takes select_t object and returns SELECT query string */ template - std::string string_from_expression(const internal::select_t &sel, bool /*noTableName*/ = false, bool /*escape*/ = false, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const internal::select_t &sel, bool /*noTableName*/, bool /*escape*/, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!is_base_of_template::value){ if(!sel.highest_level){ @@ -7570,14 +7570,14 @@ namespace sqlite_orm { } template - std::string string_from_expression(const conditions::cast_t &c, bool noTableName = false, bool escape = false, bool ignoreBindable = false) { + std::string string_from_expression(const conditions::cast_t &c, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; ss << static_cast(c) << " ( " << this->string_from_expression(c.expression, noTableName, escape, ignoreBindable) << " AS " << type_printer().print() << ") "; return ss.str(); } template - typename std::enable_if::value, std::string>::type string_from_expression(const T &op, bool noTableName = false, bool escape = false, bool ignoreBindable = false) + typename std::enable_if::value, std::string>::type string_from_expression(const T &op, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; ss << this->string_from_expression(op.left, noTableName, escape, ignoreBindable) << " "; @@ -7587,16 +7587,16 @@ namespace sqlite_orm { } template - std::string process_where(const conditions::is_null_t &c) { + std::string process_where(const conditions::is_null_t &c, bool ignoreBindable = false) { std::stringstream ss; - ss << this->string_from_expression(c.t) << " " << static_cast(c) << " "; + ss << this->string_from_expression(c.t, false, false) << " " << static_cast(c) << " "; return ss.str(); } template std::string process_where(const conditions::is_not_null_t &c) { std::stringstream ss; - ss << this->string_from_expression(c.t) << " " << static_cast(c) << " "; + ss << this->string_from_expression(c.t, false, false) << " " << static_cast(c) << " "; return ss.str(); } @@ -7625,13 +7625,13 @@ namespace sqlite_orm { template typename std::enable_if::value, std::string>::type process_where(const T &c) { - return this->string_from_expression(c); + return this->string_from_expression(c, false, false); } template typename std::enable_if::value, std::string>::type process_where(const C &c) { - auto leftString = this->string_from_expression(c.l, false, true); - auto rightString = this->string_from_expression(c.r, false, true); + auto leftString = this->string_from_expression(c.l, false, true, true); + auto rightString = this->string_from_expression(c.r, false, true, true); std::stringstream ss; ss << leftString << " " << static_cast(c) << " " << rightString; return ss.str(); @@ -7652,9 +7652,9 @@ namespace sqlite_orm { template std::string process_where(const conditions::in_t &inCondition) { std::stringstream ss; - auto leftString = this->string_from_expression(inCondition.l); + auto leftString = this->string_from_expression(inCondition.l, false, false); ss << leftString << " " << static_cast(inCondition) << " "; - ss << this->string_from_expression(inCondition.arg); + ss << this->string_from_expression(inCondition.arg, false); ss << " "; return ss.str(); } @@ -7662,11 +7662,11 @@ namespace sqlite_orm { template std::string process_where(const conditions::in_t> &inCondition) { std::stringstream ss; - auto leftString = this->string_from_expression(inCondition.l); + auto leftString = this->string_from_expression(inCondition.l, false, false); ss << leftString << " " << static_cast(inCondition) << " ( "; for(size_t index = 0; index < inCondition.arg.size(); ++index) { auto &value = inCondition.arg[index]; - ss << " " << this->string_from_expression(value); + ss << " " << this->string_from_expression(value, false, false); if(index < inCondition.arg.size() - 1) { ss << ", "; } @@ -7678,29 +7678,31 @@ namespace sqlite_orm { template std::string process_where(const conditions::like_t &l) { std::stringstream ss; - ss << this->string_from_expression(l.a) << " " << static_cast(l) << " " << this->string_from_expression(l.t) << " "; + ss << this->string_from_expression(l.a, false, false) << " "; + ss << static_cast(l) << " "; + ss << this->string_from_expression(l.t, false, false) << " "; return ss.str(); } template std::string process_where(const conditions::between_t &bw) { std::stringstream ss; - auto expr = this->string_from_expression(bw.expr); - ss << expr << " " << static_cast(bw) << " " << this->string_from_expression(bw.b1) << " AND " << this->string_from_expression(bw.b2) << " "; + auto expr = this->string_from_expression(bw.expr, false, false); + ss << expr << " " << static_cast(bw) << " " << this->string_from_expression(bw.b1, false, false) << " AND " << this->string_from_expression(bw.b2, false, false) << " "; return ss.str(); } template std::string process_where(const conditions::exists_t &e) { std::stringstream ss; - ss << static_cast(e) << " " << this->string_from_expression(e.t) << " "; + ss << static_cast(e) << " " << this->string_from_expression(e.t, false, false) << " "; return ss.str(); } template std::string process_order_by(const conditions::order_by_t &orderBy) { std::stringstream ss; - auto columnName = this->string_from_expression(orderBy.o); + auto columnName = this->string_from_expression(orderBy.o, false, false); ss << columnName << " "; if(orderBy._collate_argument.length()){ ss << "COLLATE " << orderBy._collate_argument << " "; @@ -7821,7 +7823,7 @@ namespace sqlite_orm { std::vector expressions; using tuple_t = std::tuple; tuple_helper::iterator::value - 1, Args...>()(groupBy.args, [&expressions, this](auto &v){ - auto expression = this->string_from_expression(v); + auto expression = this->string_from_expression(v, false, false); expressions.push_back(expression); }); ss << static_cast(groupBy) << " "; @@ -8095,7 +8097,7 @@ namespace sqlite_orm { std::vector setPairs; set.for_each([this, &setPairs](auto &asgn){ std::stringstream sss; - sss << this->string_from_expression(asgn.l, true) << " = " << this->string_from_expression(asgn.r) << " "; + sss << this->string_from_expression(asgn.l, true, false) << " = " << this->string_from_expression(asgn.r, false, false) << " "; setPairs.push_back(sss.str()); }); auto setPairsCount = setPairs.size(); @@ -8453,7 +8455,7 @@ namespace sqlite_orm { std::string res; std::stringstream ss; ss << "SELECT " << static_cast(sqlite_orm::group_concat(0)) << "("; - auto columnName = this->string_from_expression(m); + auto columnName = this->string_from_expression(m, false, false); if(columnName.length()){ ss << columnName; if(y){ @@ -8745,7 +8747,7 @@ namespace sqlite_orm { int res = 0; std::stringstream ss; ss << "SELECT " << static_cast(sqlite_orm::count(0)) << "("; - auto columnName = this->string_from_expression(m); + auto columnName = this->string_from_expression(m, false, false); if(columnName.length()){ ss << columnName << ") FROM '"<< impl.table.name << "' "; this->process_conditions(ss, std::make_tuple(std::forward(args)...)); @@ -8782,7 +8784,7 @@ namespace sqlite_orm { double res = 0; std::stringstream ss; ss << "SELECT " << static_cast(sqlite_orm::avg(0)) << "("; - auto columnName = this->string_from_expression(m); + auto columnName = this->string_from_expression(m, false, false); if(columnName.length()){ ss << columnName << ") FROM '"<< impl.table.name << "' "; this->process_conditions(ss, std::make_tuple(std::forward(args)...)); @@ -8852,7 +8854,7 @@ namespace sqlite_orm { std::unique_ptr res; std::stringstream ss; ss << "SELECT " << static_cast(sqlite_orm::max(0)) << "("; - auto columnName = this->string_from_expression(m); + auto columnName = this->string_from_expression(m, false, false); if(columnName.length()){ ss << columnName << ") FROM '" << impl.table.name << "' "; this->process_conditions(ss, std::make_tuple(std::forward(args)...)); @@ -8891,7 +8893,7 @@ namespace sqlite_orm { std::unique_ptr res; std::stringstream ss; ss << "SELECT " << static_cast(sqlite_orm::min(0)) << "("; - auto columnName = this->string_from_expression(m); + auto columnName = this->string_from_expression(m, false, false); if(columnName.length()){ ss << columnName << ") FROM '" << impl.table.name << "' "; this->process_conditions(ss, std::make_tuple(std::forward(args)...)); @@ -8930,7 +8932,7 @@ namespace sqlite_orm { std::unique_ptr res; std::stringstream ss; ss << "SELECT " << static_cast(sqlite_orm::sum(0)) << "("; - auto columnName = this->string_from_expression(m); + auto columnName = this->string_from_expression(m, false, false); if(columnName.length()){ ss << columnName << ") FROM '"<< impl.table.name << "' "; this->process_conditions(ss, std::make_tuple(std::forward(args)...)); @@ -8966,7 +8968,7 @@ namespace sqlite_orm { double res = 0; std::stringstream ss; ss << "SELECT " << static_cast(sqlite_orm::total(0)) << "("; - auto columnName = this->string_from_expression(m); + auto columnName = this->string_from_expression(m, false, false); if(!columnName.empty()){ ss << columnName << ") "; auto tableNamesSet = this->parse_table_names(m); @@ -9014,7 +9016,8 @@ namespace sqlite_orm { static_assert(!is_base_of_template::value || std::tuple_size>::value == 0, "Cannot use args with a compound operator"); using select_type = select_t; - auto query = this->string_from_expression(select_type{std::move(m), std::make_tuple(std::forward(args)...), true}); + auto query = this->string_from_expression(select_type{std::move(m), std::make_tuple(std::forward(args)...), true}, + false, false, true); auto connection = this->get_or_create_connection(); sqlite3_stmt *stmt; if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { @@ -9193,7 +9196,7 @@ namespace sqlite_orm { std::vector columnNames; columnNames.reserve(colsCount); cols.for_each([&columnNames, this](auto &m) { - auto columnName = this->string_from_expression(m, true); + auto columnName = this->string_from_expression(m, true, false); if(columnName.length()){ columnNames.push_back(columnName); }else{ diff --git a/tests/tests.cpp b/tests/tests.cpp index cf5d9f12d..fbf1a0330 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -12,6 +12,26 @@ using namespace sqlite_orm; using std::cout; using std::endl; +void testIsNull() { + struct User { + int id = 0; + std::unique_ptr name; + }; + auto storage = make_storage("", + make_table("users", + make_column("id", &User::id, primary_key()), + make_column("name", &User::name))); + storage.sync_schema(); + + storage.replace(User{1, std::make_unique("Sheldon")}); + storage.replace(User{2}); + storage.replace(User{3, std::make_unique("Leonard")}); + + assert(storage.count() == 3); + assert(storage.count(where(is_null(&User::name))) == 1); + assert(storage.count(where(is_not_null(&User::name))) == 2); +} + void testIterateBlob() { struct Test { int64_t id; @@ -2499,4 +2519,6 @@ int main(int, char **) { testWhere(); testIterateBlob(); + + testIsNull(); } From b8c36a9ff9d014a5f5b3fcd3de3fceaef9c84cd4 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sat, 25 May 2019 00:57:31 +0300 Subject: [PATCH 092/232] fixed subquery example --- dev/storage.h | 2 +- include/sqlite_orm/sqlite_orm.h | 2 +- tests/tests.cpp | 12 +++++++----- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/dev/storage.h b/dev/storage.h index 2e785c52a..44649258e 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -914,7 +914,7 @@ namespace sqlite_orm { std::stringstream ss; auto leftString = this->string_from_expression(inCondition.l, false, false); ss << leftString << " " << static_cast(inCondition) << " "; - ss << this->string_from_expression(inCondition.arg, false); + ss << this->string_from_expression(inCondition.arg, false, false); ss << " "; return ss.str(); } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 070d3df1f..62029dfa9 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -7654,7 +7654,7 @@ namespace sqlite_orm { std::stringstream ss; auto leftString = this->string_from_expression(inCondition.l, false, false); ss << leftString << " " << static_cast(inCondition) << " "; - ss << this->string_from_expression(inCondition.arg, false); + ss << this->string_from_expression(inCondition.arg, false, false); ss << " "; return ss.str(); } diff --git a/tests/tests.cpp b/tests/tests.cpp index fbf1a0330..667daf019 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -6,6 +6,7 @@ #include // std::cout, std::endl #include #include // remove +#include // std::iota using namespace sqlite_orm; @@ -44,11 +45,8 @@ void testIterateBlob() { make_column("id", &Test::id, autoincrement(), primary_key()))); db.sync_schema(true); - std::vector key; - key.resize(255); - for (int i = 0; i < 255; i++){ - key[i] = i; - } + std::vector key(255); + iota(key.begin(), key.end(), 0); Test v; v.key = key; @@ -59,6 +57,10 @@ void testIterateBlob() { cout << db.dump(obj) << endl; } // test that view_t and iterator_t compile + for(const auto &obj : db.iterate()){ + cout << db.dump(obj) << endl; + } // test that view_t and iterator_t compile + /*for (auto& w : db.iterate(where(c(&Test::key) == key))) { cout << w.id << endl; }*/ From 400fae7342703402f5e0bea84fbb02c53c7db450 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sat, 25 May 2019 10:18:45 +0300 Subject: [PATCH 093/232] fixed left join example --- dev/storage.h | 2 +- include/sqlite_orm/sqlite_orm.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/storage.h b/dev/storage.h index 44649258e..45019485d 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -985,7 +985,7 @@ namespace sqlite_orm { template void process_join_constraint(std::stringstream &ss, const conditions::using_t &u) { - ss << static_cast(u) << " (" << this->string_from_expression(u.column, true) << " ) "; + ss << static_cast(u) << " (" << this->string_from_expression(u.column, true, false) << " ) "; } void process_single_condition(std::stringstream &ss, const conditions::limit_t &limt) { diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 62029dfa9..792ed3161 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -7725,7 +7725,7 @@ namespace sqlite_orm { template void process_join_constraint(std::stringstream &ss, const conditions::using_t &u) { - ss << static_cast(u) << " (" << this->string_from_expression(u.column, true) << " ) "; + ss << static_cast(u) << " (" << this->string_from_expression(u.column, true, false) << " ) "; } void process_single_condition(std::stringstream &ss, const conditions::limit_t &limt) { From 2e8aa5a53f4f4b8cdc379c30d2a3f74895080415 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 30 May 2019 18:43:59 +0300 Subject: [PATCH 094/232] added iterating over strings --- dev/ast_iterator.h | 101 ++++++++++ dev/conditions.h | 1 + dev/operators.h | 98 ++++------ dev/statement_binder.h | 34 ++++ dev/storage.h | 90 ++++++--- include/sqlite_orm/sqlite_orm.h | 328 ++++++++++++++++++++++++-------- tests/tests.cpp | 267 +++++++++++++++----------- 7 files changed, 648 insertions(+), 271 deletions(-) create mode 100644 dev/ast_iterator.h diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h new file mode 100644 index 000000000..5670affa4 --- /dev/null +++ b/dev/ast_iterator.h @@ -0,0 +1,101 @@ +#pragma once + +#include "conditions.h" +#include "select_constraints.h" +#include "operators.h" + +#include + +namespace sqlite_orm { + + namespace internal { + + /** + * T is an ast element. E.g. where_t + */ + template + struct ast_iterator { + using node_type = T; + + /** + * L is a callable type. Mostly is templated lambda + */ + template + void operator()(const T &t, const L &l) const { + std::cout << "t is " << typeid(t).name() << std::endl; + } + }; + + template + void iterate_ast(const T &t, const L &l) { + ast_iterator iterator; + iterator(t, l); + } + + template + struct ast_iterator, void> { + using node_type = conditions::where_t; + + // L is a callable type. Mostly is templated lambda + template + void operator()(const node_type &where, const L &l) const { + iterate_ast(where.c, l); + } + }; + + template + struct ast_iterator::value>::type> { + using node_type = T; + + template + void operator()(const node_type &binaryCondition, const L &l) const { + l(binaryCondition.l); + l(binaryCondition.r); + } + }; + + template + struct ast_iterator::value>::type> { + using node_type = T; + + template + void operator()(const node_type &binaryOperator, const L &l) const { + l(binaryOperator.l); + l(binaryOperator.r); + } + }; + + template + struct ast_iterator, void> { + using node_type = assign_t; + + template + void operator()(const node_type &assign, const C &l) const { + l(assign.r); + } + }; + + template + struct ast_iterator, void> { + using node_type = columns_t; + + template + void operator()(const node_type &cols, const L &l) const { + cols.for_each([&l](auto &col){ + iterate_ast(col, l); + }); + } + }; + + /*template + struct ast_iterator, void> { + using node_type = conc_t; + + template + void operator()(const node_type &conc, const C &l) const { + l(conc.l); + l(conc.r); + } + };*/ + } +} diff --git a/dev/conditions.h b/dev/conditions.h index 66d243b65..4980efdbb 100644 --- a/dev/conditions.h +++ b/dev/conditions.h @@ -399,6 +399,7 @@ namespace sqlite_orm { /** * WHERE argument holder. + * C is conditions type. Can be any condition like: is_equal_t, is_null_t, exists_t etc */ template struct where_t { diff --git a/dev/operators.h b/dev/operators.h index 8fc002ece..aab06f453 100644 --- a/dev/operators.h +++ b/dev/operators.h @@ -11,93 +11,77 @@ namespace sqlite_orm { */ struct arithmetic_t {}; + template + struct binary_operator { + using left_type = L; + using right_type = R; + + left_type l; + right_type r; + + binary_operator() = default; + + binary_operator(left_type l_, right_type r_) : l(std::move(l_)), r(std::move(r_)) {} + }; + /** * Result of concatenation || operator */ template - struct conc_t { - L l; - R r; + struct conc_t : binary_operator { + using super = binary_operator; + + using super::super; }; /** * Result of addition + operator */ template - struct add_t : arithmetic_t { - using left_type = L; - using right_type = R; - - left_type l; - right_type r; - - add_t() = default; + struct add_t : arithmetic_t, binary_operator { + using super = binary_operator; - add_t(left_type l_, right_type r_) : l(std::move(l_)), r(std::move(r_)) {} + using super::super; }; /** - * Result of subscribe - operator + * Result of substitute - operator */ template - struct sub_t : arithmetic_t { - using left_type = L; - using right_type = R; - - left_type l; - right_type r; - - sub_t() = default; + struct sub_t : arithmetic_t, binary_operator { + using super = binary_operator; - sub_t(left_type l_, right_type r_) : l(std::move(l_)), r(std::move(r_)) {} + using super::super; }; /** * Result of multiply * operator */ template - struct mul_t : arithmetic_t { - using left_type = L; - using right_type = R; - - left_type l; - right_type r; - - mul_t() = default; + struct mul_t : arithmetic_t, binary_operator { + using super = binary_operator; - mul_t(left_type l_, right_type r_) : l(std::move(l_)), r(std::move(r_)) {} + using super::super; }; /** * Result of divide / operator */ template - struct div_t : arithmetic_t { - using left_type = L; - using right_type = R; - - left_type l; - right_type r; - - div_t() = default; + struct div_t : arithmetic_t, binary_operator { + using super = binary_operator; - div_t(left_type l_, right_type r_) : l(std::move(l_)), r(std::move(r_)) {} + using super::super; }; /** * Result of mod % operator */ template - struct mod_t : arithmetic_t { - using left_type = L; - using right_type = R; - - left_type l; - right_type r; - - mod_t() = default; + struct mod_t : arithmetic_t, binary_operator { + using super = binary_operator; - mod_t(left_type l_, right_type r_) : l(std::move(l_)), r(std::move(r_)) {} + using super::super; }; /** @@ -136,7 +120,7 @@ namespace sqlite_orm { template assign_t operator=(R r) const { - return {this->t, r}; + return {this->t, std::move(r)}; } }; @@ -148,7 +132,7 @@ namespace sqlite_orm { template internal::expression_t c(T t) { using result_type = internal::expression_t; - return result_type(t); + return result_type(std::move(t)); } /** @@ -156,7 +140,7 @@ namespace sqlite_orm { */ template internal::conc_t conc(L l, R r) { - return {l, r}; + return {std::move(l), std::move(r)}; } /** @@ -164,7 +148,7 @@ namespace sqlite_orm { */ template internal::add_t add(L l, R r) { - return {l, r}; + return {std::move(l), std::move(r)}; } /** @@ -172,22 +156,22 @@ namespace sqlite_orm { */ template internal::sub_t sub(L l, R r) { - return {l, r}; + return {std::move(l), std::move(r)}; } template internal::mul_t mul(L l, R r) { - return {l, r}; + return {std::move(l), std::move(r)}; } template internal::div_t div(L l, R r) { - return {l, r}; + return {std::move(l), std::move(r)}; } template internal::mod_t mod(L l, R r) { - return {l, r}; + return {std::move(l), std::move(r)}; } template diff --git a/dev/statement_binder.h b/dev/statement_binder.h index c924e0cd4..e26c00fe1 100644 --- a/dev/statement_binder.h +++ b/dev/statement_binder.h @@ -127,5 +127,39 @@ namespace sqlite_orm { template using is_bindable = decltype(is_bindable_impl(std::declval*>())); + + struct conditional_binder_base { + sqlite3_stmt *stmt = nullptr; + int &index; + + conditional_binder_base(decltype(stmt) stmt_, decltype(index) index_): + stmt(stmt_), + index(index_) + {} + }; + + template + struct conditional_binder; + + template + struct conditional_binder : conditional_binder_base { + + using conditional_binder_base::conditional_binder_base; + + void operator()(const T &t) const { + /*auto bindResult =*/ statement_binder().bind(this->stmt, this->index++, t); +// auto errorText = +// bindResult = bindResult; + } + }; + + template + struct conditional_binder : conditional_binder_base { + using conditional_binder_base::conditional_binder_base; + + void operator()(const T &t) const { + //.. + } + }; } } diff --git a/dev/storage.h b/dev/storage.h index 45019485d..a14797e5b 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -15,6 +15,7 @@ #include // std::forward, std::pair #include // std::set #include // std::find +#include #include "alias.h" #include "database_connection.h" @@ -45,6 +46,7 @@ #include "limit_accesor.h" #include "field_value_holder.h" #include "view.h" +#include "ast_iterator.h" namespace sqlite_orm { @@ -306,7 +308,7 @@ namespace sqlite_orm { if(needQuotes && ignoreBindable){ ss << "'"; } - if(ignoreBindable){ + if(!ignoreBindable){ std::string text = field_printer()(t); if(escape){ text = this->escape(text); @@ -345,7 +347,7 @@ namespace sqlite_orm { std::string string_from_expression(const std::string &t, bool /*noTableName*/, bool escape, bool ignoreBindable = false) { std::stringstream ss; - if(ignoreBindable){ + if(!ignoreBindable){ std::string text = t; if(escape){ text = this->escape(text); @@ -740,7 +742,7 @@ namespace sqlite_orm { template std::vector get_column_names(const T &t) { - auto columnName = this->string_from_expression(t, false, false); + auto columnName = this->string_from_expression(t, false, false, true); if(columnName.length()){ return {columnName}; }else{ @@ -760,7 +762,7 @@ namespace sqlite_orm { std::vector columnNames; columnNames.reserve(static_cast(cols.count())); cols.for_each([&columnNames, this](auto &m) { - auto columnName = this->string_from_expression(m, false, false); + auto columnName = this->string_from_expression(m, false, false, true); if(columnName.length()){ columnNames.push_back(columnName); }else{ @@ -774,7 +776,7 @@ namespace sqlite_orm { * Takes select_t object and returns SELECT query string */ template - std::string string_from_expression(const internal::select_t &sel, bool /*noTableName*/, bool /*escape*/, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const internal::select_t &sel, bool /*noTableName*/, bool /*escape*/, bool ignoreBindable) { std::stringstream ss; if(!is_base_of_template::value){ if(!sel.highest_level){ @@ -847,16 +849,16 @@ namespace sqlite_orm { } template - std::string process_where(const conditions::is_null_t &c, bool ignoreBindable = false) { + std::string process_where(const conditions::is_null_t &c) { std::stringstream ss; - ss << this->string_from_expression(c.t, false, false) << " " << static_cast(c) << " "; + ss << this->string_from_expression(c.t, false, false, true) << " " << static_cast(c) << " "; return ss.str(); } template std::string process_where(const conditions::is_not_null_t &c) { std::stringstream ss; - ss << this->string_from_expression(c.t, false, false) << " " << static_cast(c) << " "; + ss << this->string_from_expression(c.t, false, false, true) << " " << static_cast(c) << " "; return ss.str(); } @@ -885,7 +887,7 @@ namespace sqlite_orm { template typename std::enable_if::value, std::string>::type process_where(const T &c) { - return this->string_from_expression(c, false, false); + return this->string_from_expression(c, false, false, true); } template @@ -912,9 +914,9 @@ namespace sqlite_orm { template std::string process_where(const conditions::in_t &inCondition) { std::stringstream ss; - auto leftString = this->string_from_expression(inCondition.l, false, false); + auto leftString = this->string_from_expression(inCondition.l, false, false, true); ss << leftString << " " << static_cast(inCondition) << " "; - ss << this->string_from_expression(inCondition.arg, false, false); + ss << this->string_from_expression(inCondition.arg, false, false, true); ss << " "; return ss.str(); } @@ -922,11 +924,11 @@ namespace sqlite_orm { template std::string process_where(const conditions::in_t> &inCondition) { std::stringstream ss; - auto leftString = this->string_from_expression(inCondition.l, false, false); + auto leftString = this->string_from_expression(inCondition.l, false, false, true); ss << leftString << " " << static_cast(inCondition) << " ( "; for(size_t index = 0; index < inCondition.arg.size(); ++index) { auto &value = inCondition.arg[index]; - ss << " " << this->string_from_expression(value, false, false); + ss << " " << this->string_from_expression(value, false, false, true); if(index < inCondition.arg.size() - 1) { ss << ", "; } @@ -938,31 +940,31 @@ namespace sqlite_orm { template std::string process_where(const conditions::like_t &l) { std::stringstream ss; - ss << this->string_from_expression(l.a, false, false) << " "; + ss << this->string_from_expression(l.a, false, false, true) << " "; ss << static_cast(l) << " "; - ss << this->string_from_expression(l.t, false, false) << " "; + ss << this->string_from_expression(l.t, false, false, true) << " "; return ss.str(); } template std::string process_where(const conditions::between_t &bw) { std::stringstream ss; - auto expr = this->string_from_expression(bw.expr, false, false); - ss << expr << " " << static_cast(bw) << " " << this->string_from_expression(bw.b1, false, false) << " AND " << this->string_from_expression(bw.b2, false, false) << " "; + auto expr = this->string_from_expression(bw.expr, false, false, true); + ss << expr << " " << static_cast(bw) << " " << this->string_from_expression(bw.b1, false, false, true) << " AND " << this->string_from_expression(bw.b2, false, false) << " "; return ss.str(); } template std::string process_where(const conditions::exists_t &e) { std::stringstream ss; - ss << static_cast(e) << " " << this->string_from_expression(e.t, false, false) << " "; + ss << static_cast(e) << " " << this->string_from_expression(e.t, false, false, true) << " "; return ss.str(); } template std::string process_order_by(const conditions::order_by_t &orderBy) { std::stringstream ss; - auto columnName = this->string_from_expression(orderBy.o, false, false); + auto columnName = this->string_from_expression(orderBy.o, false, false, true); ss << columnName << " "; if(orderBy._collate_argument.length()){ ss << "COLLATE " << orderBy._collate_argument << " "; @@ -985,7 +987,7 @@ namespace sqlite_orm { template void process_join_constraint(std::stringstream &ss, const conditions::using_t &u) { - ss << static_cast(u) << " (" << this->string_from_expression(u.column, true, false) << " ) "; + ss << static_cast(u) << " (" << this->string_from_expression(u.column, true, false, true) << " ) "; } void process_single_condition(std::stringstream &ss, const conditions::limit_t &limt) { @@ -1083,7 +1085,7 @@ namespace sqlite_orm { std::vector expressions; using tuple_t = std::tuple; tuple_helper::iterator::value - 1, Args...>()(groupBy.args, [&expressions, this](auto &v){ - auto expression = this->string_from_expression(v, false, false); + auto expression = this->string_from_expression(v, false, false, true); expressions.push_back(expression); }); ss << static_cast(groupBy) << " "; @@ -1367,11 +1369,31 @@ namespace sqlite_orm { ss << ", "; } } - this->process_conditions(ss, std::make_tuple(std::forward(wh)...)); + auto whereArgsTuple = std::make_tuple(std::forward(wh)...); + this->process_conditions(ss, whereArgsTuple); auto query = ss.str(); sqlite3_stmt *stmt; if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; + auto index = 1; + set.for_each([&index, stmt](auto &setArg){ + iterate_ast(setArg, [&index, stmt](auto &node){ + using node_type = typename std::decay::type; + conditional_binder> binder{stmt, index}; + binder(node); + }); + }); + tuple_helper::iterator::value - 1, Wargs...>()(whereArgsTuple, [stmt, &index](auto &v){ + using arg_type = typename std::decay::type; +// std::cout << "v is " << typeid(arg_type).name() << std::endl; + + iterate_ast(v, [stmt, &index](auto &node){ + using node_type = typename std::decay::type; + conditional_binder> binder{stmt, index}; + binder(node); + }); + }); + if (sqlite3_step(stmt) == SQLITE_DONE) { // done.. }else{ @@ -2276,12 +2298,32 @@ namespace sqlite_orm { static_assert(!is_base_of_template::value || std::tuple_size>::value == 0, "Cannot use args with a compound operator"); using select_type = select_t; - auto query = this->string_from_expression(select_type{std::move(m), std::make_tuple(std::forward(args)...), true}, - false, false, true); + select_type sel{std::move(m), std::make_tuple(std::forward(args)...), true}; + auto query = this->string_from_expression(sel, false, false, true); auto connection = this->get_or_create_connection(); sqlite3_stmt *stmt; if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; + auto index = 1; + using conditions_type = typename select_type::conditions_type; + + iterate_ast(sel.col, [stmt, &index](auto &node){ + using node_type = typename std::decay::type; + conditional_binder> binder{stmt, index}; + binder(node); + }); + + tuple_helper::iterator::value - 1, Args...>()(sel.conditions, [stmt, &index](auto &v){ + using arg_type = typename std::decay::type; + std::cout << "v is " << typeid(arg_type).name() << std::endl; + + iterate_ast(v, [stmt, &index](auto &node){ + using node_type = typename std::decay::type; + conditional_binder> binder{stmt, index}; + binder(node); + }); + }); + std::vector res; int stepRes; do{ diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 792ed3161..20fc86f46 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -937,93 +937,77 @@ namespace sqlite_orm { */ struct arithmetic_t {}; + template + struct binary_operator { + using left_type = L; + using right_type = R; + + left_type l; + right_type r; + + binary_operator() = default; + + binary_operator(left_type l_, right_type r_) : l(std::move(l_)), r(std::move(r_)) {} + }; + /** * Result of concatenation || operator */ template - struct conc_t { - L l; - R r; + struct conc_t : binary_operator { + using super = binary_operator; + + using super::super; }; /** * Result of addition + operator */ template - struct add_t : arithmetic_t { - using left_type = L; - using right_type = R; - - left_type l; - right_type r; - - add_t() = default; + struct add_t : arithmetic_t, binary_operator { + using super = binary_operator; - add_t(left_type l_, right_type r_) : l(std::move(l_)), r(std::move(r_)) {} + using super::super; }; /** - * Result of subscribe - operator + * Result of substitute - operator */ template - struct sub_t : arithmetic_t { - using left_type = L; - using right_type = R; - - left_type l; - right_type r; - - sub_t() = default; + struct sub_t : arithmetic_t, binary_operator { + using super = binary_operator; - sub_t(left_type l_, right_type r_) : l(std::move(l_)), r(std::move(r_)) {} + using super::super; }; /** * Result of multiply * operator */ template - struct mul_t : arithmetic_t { - using left_type = L; - using right_type = R; + struct mul_t : arithmetic_t, binary_operator { + using super = binary_operator; - left_type l; - right_type r; - - mul_t() = default; - - mul_t(left_type l_, right_type r_) : l(std::move(l_)), r(std::move(r_)) {} + using super::super; }; /** * Result of divide / operator */ template - struct div_t : arithmetic_t { - using left_type = L; - using right_type = R; + struct div_t : arithmetic_t, binary_operator { + using super = binary_operator; - left_type l; - right_type r; - - div_t() = default; - - div_t(left_type l_, right_type r_) : l(std::move(l_)), r(std::move(r_)) {} + using super::super; }; /** * Result of mod % operator */ template - struct mod_t : arithmetic_t { - using left_type = L; - using right_type = R; + struct mod_t : arithmetic_t, binary_operator { + using super = binary_operator; - left_type l; - right_type r; - - mod_t() = default; - - mod_t(left_type l_, right_type r_) : l(std::move(l_)), r(std::move(r_)) {} + using super::super; }; /** @@ -1062,7 +1046,7 @@ namespace sqlite_orm { template assign_t operator=(R r) const { - return {this->t, r}; + return {this->t, std::move(r)}; } }; @@ -1074,7 +1058,7 @@ namespace sqlite_orm { template internal::expression_t c(T t) { using result_type = internal::expression_t; - return result_type(t); + return result_type(std::move(t)); } /** @@ -1082,7 +1066,7 @@ namespace sqlite_orm { */ template internal::conc_t conc(L l, R r) { - return {l, r}; + return {std::move(l), std::move(r)}; } /** @@ -1090,7 +1074,7 @@ namespace sqlite_orm { */ template internal::add_t add(L l, R r) { - return {l, r}; + return {std::move(l), std::move(r)}; } /** @@ -1098,22 +1082,22 @@ namespace sqlite_orm { */ template internal::sub_t sub(L l, R r) { - return {l, r}; + return {std::move(l), std::move(r)}; } template internal::mul_t mul(L l, R r) { - return {l, r}; + return {std::move(l), std::move(r)}; } template internal::div_t div(L l, R r) { - return {l, r}; + return {std::move(l), std::move(r)}; } template internal::mod_t mod(L l, R r) { - return {l, r}; + return {std::move(l), std::move(r)}; } template @@ -1947,6 +1931,7 @@ namespace sqlite_orm { /** * WHERE argument holder. + * C is conditions type. Can be any condition like: is_equal_t, is_null_t, exists_t etc */ template struct where_t { @@ -4116,6 +4101,40 @@ namespace sqlite_orm { template using is_bindable = decltype(is_bindable_impl(std::declval*>())); + + struct conditional_binder_base { + sqlite3_stmt *stmt = nullptr; + int &index; + + conditional_binder_base(decltype(stmt) stmt_, decltype(index) index_): + stmt(stmt_), + index(index_) + {} + }; + + template + struct conditional_binder; + + template + struct conditional_binder : conditional_binder_base { + + using conditional_binder_base::conditional_binder_base; + + void operator()(const T &t) const { + /*auto bindResult =*/ statement_binder().bind(this->stmt, this->index++, t); +// auto errorText = +// bindResult = bindResult; + } + }; + + template + struct conditional_binder : conditional_binder_base { + using conditional_binder_base::conditional_binder_base; + + void operator()(const T &t) const { + //.. + } + }; } } #pragma once @@ -6196,6 +6215,7 @@ namespace sqlite_orm { #include // std::forward, std::pair #include // std::set #include // std::find +#include // #include "alias.h" @@ -6785,6 +6805,112 @@ namespace sqlite_orm { } } +// #include "ast_iterator.h" + + +// #include "conditions.h" + +// #include "select_constraints.h" + +// #include "operators.h" + + +#include + +namespace sqlite_orm { + + namespace internal { + + /** + * T is an ast element. E.g. where_t + */ + template + struct ast_iterator { + using node_type = T; + + /** + * L is a callable type. Mostly is templated lambda + */ + template + void operator()(const T &t, const L &l) const { + std::cout << "t is " << typeid(t).name() << std::endl; + } + }; + + template + void iterate_ast(const T &t, const L &l) { + ast_iterator iterator; + iterator(t, l); + } + + template + struct ast_iterator, void> { + using node_type = conditions::where_t; + + // L is a callable type. Mostly is templated lambda + template + void operator()(const node_type &where, const L &l) const { + iterate_ast(where.c, l); + } + }; + + template + struct ast_iterator::value>::type> { + using node_type = T; + + template + void operator()(const node_type &binaryCondition, const L &l) const { + l(binaryCondition.l); + l(binaryCondition.r); + } + }; + + template + struct ast_iterator::value>::type> { + using node_type = T; + + template + void operator()(const node_type &binaryOperator, const L &l) const { + l(binaryOperator.l); + l(binaryOperator.r); + } + }; + + template + struct ast_iterator, void> { + using node_type = assign_t; + + template + void operator()(const node_type &assign, const C &l) const { + l(assign.r); + } + }; + + template + struct ast_iterator, void> { + using node_type = columns_t; + + template + void operator()(const node_type &cols, const L &l) const { + cols.for_each([&l](auto &col){ + iterate_ast(col, l); + }); + } + }; + + /*template + struct ast_iterator, void> { + using node_type = conc_t; + + template + void operator()(const node_type &conc, const C &l) const { + l(conc.l); + l(conc.r); + } + };*/ + } +} + namespace sqlite_orm { @@ -7046,7 +7172,7 @@ namespace sqlite_orm { if(needQuotes && ignoreBindable){ ss << "'"; } - if(ignoreBindable){ + if(!ignoreBindable){ std::string text = field_printer()(t); if(escape){ text = this->escape(text); @@ -7085,7 +7211,7 @@ namespace sqlite_orm { std::string string_from_expression(const std::string &t, bool /*noTableName*/, bool escape, bool ignoreBindable = false) { std::stringstream ss; - if(ignoreBindable){ + if(!ignoreBindable){ std::string text = t; if(escape){ text = this->escape(text); @@ -7480,7 +7606,7 @@ namespace sqlite_orm { template std::vector get_column_names(const T &t) { - auto columnName = this->string_from_expression(t, false, false); + auto columnName = this->string_from_expression(t, false, false, true); if(columnName.length()){ return {columnName}; }else{ @@ -7500,7 +7626,7 @@ namespace sqlite_orm { std::vector columnNames; columnNames.reserve(static_cast(cols.count())); cols.for_each([&columnNames, this](auto &m) { - auto columnName = this->string_from_expression(m, false, false); + auto columnName = this->string_from_expression(m, false, false, true); if(columnName.length()){ columnNames.push_back(columnName); }else{ @@ -7514,7 +7640,7 @@ namespace sqlite_orm { * Takes select_t object and returns SELECT query string */ template - std::string string_from_expression(const internal::select_t &sel, bool /*noTableName*/, bool /*escape*/, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const internal::select_t &sel, bool /*noTableName*/, bool /*escape*/, bool ignoreBindable) { std::stringstream ss; if(!is_base_of_template::value){ if(!sel.highest_level){ @@ -7587,16 +7713,16 @@ namespace sqlite_orm { } template - std::string process_where(const conditions::is_null_t &c, bool ignoreBindable = false) { + std::string process_where(const conditions::is_null_t &c) { std::stringstream ss; - ss << this->string_from_expression(c.t, false, false) << " " << static_cast(c) << " "; + ss << this->string_from_expression(c.t, false, false, true) << " " << static_cast(c) << " "; return ss.str(); } template std::string process_where(const conditions::is_not_null_t &c) { std::stringstream ss; - ss << this->string_from_expression(c.t, false, false) << " " << static_cast(c) << " "; + ss << this->string_from_expression(c.t, false, false, true) << " " << static_cast(c) << " "; return ss.str(); } @@ -7625,7 +7751,7 @@ namespace sqlite_orm { template typename std::enable_if::value, std::string>::type process_where(const T &c) { - return this->string_from_expression(c, false, false); + return this->string_from_expression(c, false, false, true); } template @@ -7652,9 +7778,9 @@ namespace sqlite_orm { template std::string process_where(const conditions::in_t &inCondition) { std::stringstream ss; - auto leftString = this->string_from_expression(inCondition.l, false, false); + auto leftString = this->string_from_expression(inCondition.l, false, false, true); ss << leftString << " " << static_cast(inCondition) << " "; - ss << this->string_from_expression(inCondition.arg, false, false); + ss << this->string_from_expression(inCondition.arg, false, false, true); ss << " "; return ss.str(); } @@ -7662,11 +7788,11 @@ namespace sqlite_orm { template std::string process_where(const conditions::in_t> &inCondition) { std::stringstream ss; - auto leftString = this->string_from_expression(inCondition.l, false, false); + auto leftString = this->string_from_expression(inCondition.l, false, false, true); ss << leftString << " " << static_cast(inCondition) << " ( "; for(size_t index = 0; index < inCondition.arg.size(); ++index) { auto &value = inCondition.arg[index]; - ss << " " << this->string_from_expression(value, false, false); + ss << " " << this->string_from_expression(value, false, false, true); if(index < inCondition.arg.size() - 1) { ss << ", "; } @@ -7678,31 +7804,31 @@ namespace sqlite_orm { template std::string process_where(const conditions::like_t &l) { std::stringstream ss; - ss << this->string_from_expression(l.a, false, false) << " "; + ss << this->string_from_expression(l.a, false, false, true) << " "; ss << static_cast(l) << " "; - ss << this->string_from_expression(l.t, false, false) << " "; + ss << this->string_from_expression(l.t, false, false, true) << " "; return ss.str(); } template std::string process_where(const conditions::between_t &bw) { std::stringstream ss; - auto expr = this->string_from_expression(bw.expr, false, false); - ss << expr << " " << static_cast(bw) << " " << this->string_from_expression(bw.b1, false, false) << " AND " << this->string_from_expression(bw.b2, false, false) << " "; + auto expr = this->string_from_expression(bw.expr, false, false, true); + ss << expr << " " << static_cast(bw) << " " << this->string_from_expression(bw.b1, false, false, true) << " AND " << this->string_from_expression(bw.b2, false, false) << " "; return ss.str(); } template std::string process_where(const conditions::exists_t &e) { std::stringstream ss; - ss << static_cast(e) << " " << this->string_from_expression(e.t, false, false) << " "; + ss << static_cast(e) << " " << this->string_from_expression(e.t, false, false, true) << " "; return ss.str(); } template std::string process_order_by(const conditions::order_by_t &orderBy) { std::stringstream ss; - auto columnName = this->string_from_expression(orderBy.o, false, false); + auto columnName = this->string_from_expression(orderBy.o, false, false, true); ss << columnName << " "; if(orderBy._collate_argument.length()){ ss << "COLLATE " << orderBy._collate_argument << " "; @@ -7725,7 +7851,7 @@ namespace sqlite_orm { template void process_join_constraint(std::stringstream &ss, const conditions::using_t &u) { - ss << static_cast(u) << " (" << this->string_from_expression(u.column, true, false) << " ) "; + ss << static_cast(u) << " (" << this->string_from_expression(u.column, true, false, true) << " ) "; } void process_single_condition(std::stringstream &ss, const conditions::limit_t &limt) { @@ -7823,7 +7949,7 @@ namespace sqlite_orm { std::vector expressions; using tuple_t = std::tuple; tuple_helper::iterator::value - 1, Args...>()(groupBy.args, [&expressions, this](auto &v){ - auto expression = this->string_from_expression(v, false, false); + auto expression = this->string_from_expression(v, false, false, true); expressions.push_back(expression); }); ss << static_cast(groupBy) << " "; @@ -8107,11 +8233,31 @@ namespace sqlite_orm { ss << ", "; } } - this->process_conditions(ss, std::make_tuple(std::forward(wh)...)); + auto whereArgsTuple = std::make_tuple(std::forward(wh)...); + this->process_conditions(ss, whereArgsTuple); auto query = ss.str(); sqlite3_stmt *stmt; if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; + auto index = 1; + set.for_each([&index, stmt](auto &setArg){ + iterate_ast(setArg, [&index, stmt](auto &node){ + using node_type = typename std::decay::type; + conditional_binder> binder{stmt, index}; + binder(node); + }); + }); + tuple_helper::iterator::value - 1, Wargs...>()(whereArgsTuple, [stmt, &index](auto &v){ + using arg_type = typename std::decay::type; +// std::cout << "v is " << typeid(arg_type).name() << std::endl; + + iterate_ast(v, [stmt, &index](auto &node){ + using node_type = typename std::decay::type; + conditional_binder> binder{stmt, index}; + binder(node); + }); + }); + if (sqlite3_step(stmt) == SQLITE_DONE) { // done.. }else{ @@ -9016,12 +9162,32 @@ namespace sqlite_orm { static_assert(!is_base_of_template::value || std::tuple_size>::value == 0, "Cannot use args with a compound operator"); using select_type = select_t; - auto query = this->string_from_expression(select_type{std::move(m), std::make_tuple(std::forward(args)...), true}, - false, false, true); + select_type sel{std::move(m), std::make_tuple(std::forward(args)...), true}; + auto query = this->string_from_expression(sel, false, false, true); auto connection = this->get_or_create_connection(); sqlite3_stmt *stmt; if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; + auto index = 1; + using conditions_type = typename select_type::conditions_type; + + iterate_ast(sel.col, [stmt, &index](auto &node){ + using node_type = typename std::decay::type; + conditional_binder> binder{stmt, index}; + binder(node); + }); + + tuple_helper::iterator::value - 1, Args...>()(sel.conditions, [stmt, &index](auto &v){ + using arg_type = typename std::decay::type; + std::cout << "v is " << typeid(arg_type).name() << std::endl; + + iterate_ast(v, [stmt, &index](auto &node){ + using node_type = typename std::decay::type; + conditional_binder> binder{stmt, index}; + binder(node); + }); + }); + std::vector res; int stepRes; do{ diff --git a/tests/tests.cpp b/tests/tests.cpp index 667daf019..25d673b6d 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -497,10 +497,8 @@ void testJoinIteratorConstructorCompilationError() { auto storage = make_storage("join_error.sqlite", make_table("tags", - make_column("object_id", - &Tag::objectId), - make_column("text", - &Tag::text))); + make_column("object_id", &Tag::objectId), + make_column("text", &Tag::text))); storage.sync_schema(); auto offs = 0; @@ -834,11 +832,8 @@ void testVacuum() { auto storage = make_storage("vacuum.sqlite", make_table("items", - make_column("id", - &Item::id, - primary_key()), - make_column("name", - &Item::name))); + make_column("id", &Item::id, primary_key()), + make_column("name", &Item::name))); storage.sync_schema(); storage.insert(Item{ 0, "One" }); storage.insert(Item{ 0, "Two" }); @@ -879,12 +874,9 @@ void testOperators() { auto storage = make_storage("", make_table("objects", - make_column("name", - &Object::name), - make_column("name_len", - &Object::nameLen), - make_column("number", - &Object::number))); + make_column("name", &Object::name), + make_column("name_len", &Object::nameLen), + make_column("number", &Object::number))); storage.sync_schema(); std::vector names { @@ -894,86 +886,126 @@ void testOperators() { for(auto &name : names) { storage.insert(Object{ name , int(name.length()), number }); } - std::string suffix = "ototo"; - auto rows = storage.select(columns(conc(&Object::name, suffix), - c(&Object::name) || suffix, - &Object::name || c(suffix), - c(&Object::name) || c(suffix), - - add(&Object::nameLen, &Object::number), - c(&Object::nameLen) + &Object::number, - &Object::nameLen + c(&Object::number), - c(&Object::nameLen) + c(&Object::number), - c(&Object::nameLen) + 1000, - - sub(&Object::nameLen, &Object::number), - c(&Object::nameLen) - &Object::number, - &Object::nameLen - c(&Object::number), - c(&Object::nameLen) - c(&Object::number), - c(&Object::nameLen) - 1000, - - mul(&Object::nameLen, &Object::number), - c(&Object::nameLen) * &Object::number, - &Object::nameLen * c(&Object::number), - c(&Object::nameLen) * c(&Object::number), - c(&Object::nameLen) * 1000, - - div(&Object::nameLen, &Object::number), - c(&Object::nameLen) / &Object::number, - &Object::nameLen / c(&Object::number), - c(&Object::nameLen) / c(&Object::number), - c(&Object::nameLen) / 2)); - - for(size_t i = 0; i < rows.size(); ++i) { - auto &row = rows[i]; - auto &name = names[i]; - assert(std::get<0>(row) == name + suffix); - assert(std::get<1>(row) == std::get<0>(row)); - assert(std::get<2>(row) == std::get<1>(row)); - assert(std::get<3>(row) == std::get<2>(row)); - - auto expectedAddNumber = int(name.length()) + number; - assert(std::get<4>(row) == expectedAddNumber); - assert(std::get<5>(row) == std::get<4>(row)); - assert(std::get<6>(row) == std::get<5>(row)); - assert(std::get<7>(row) == std::get<6>(row)); - assert(std::get<8>(row) == int(name.length()) + 1000); - - auto expectedSubNumber = int(name.length()) - number; - assert(std::get<9>(row) == expectedSubNumber); - assert(std::get<10>(row) == std::get<9>(row)); - assert(std::get<11>(row) == std::get<10>(row)); - assert(std::get<12>(row) == std::get<11>(row)); - assert(std::get<13>(row) == int(name.length()) - 1000); - - auto expectedMulNumber = int(name.length()) * number; - assert(std::get<14>(row) == expectedMulNumber); - assert(std::get<15>(row) == std::get<14>(row)); - assert(std::get<16>(row) == std::get<15>(row)); - assert(std::get<17>(row) == std::get<16>(row)); - assert(std::get<18>(row) == int(name.length()) * 1000); + { + auto rows = storage.select(c(&Object::nameLen) + 1000); + for(size_t i = 0; i < rows.size(); ++i){ + auto &row = rows[i]; + auto &name = names[i]; + assert(int(row) == name.length() + 1000); + } + } + { + auto rows = storage.select(columns(c(&Object::nameLen) + 1000)); + for(size_t i = 0; i < rows.size(); ++i){ + auto &row = rows[i]; + auto &name = names[i]; + assert(int(std::get<0>(row)) == name.length() + 1000); + } + } + { + std::string suffix = "ototo"; + auto rows = storage.select(c(&Object::name) || suffix); + for(size_t i = 0; i < rows.size(); ++i){ + auto &row = rows[i]; + auto &name = names[i]; + assert(row == name + suffix); + } + } + { + std::string suffix = "ototo"; + auto rows = storage.select(columns(conc(&Object::name, suffix))); + for(size_t i = 0; i < rows.size(); ++i){ + auto &row = rows[i]; + auto &name = names[i]; + assert(std::get<0>(row) == name + suffix); + } + } + { + std::string suffix = "ototo"; + auto rows = storage.select(columns(conc(&Object::name, suffix), + c(&Object::name) || suffix, + &Object::name || c(suffix), + c(&Object::name) || c(suffix), + + add(&Object::nameLen, &Object::number), + c(&Object::nameLen) + &Object::number, + &Object::nameLen + c(&Object::number), + c(&Object::nameLen) + c(&Object::number), + c(&Object::nameLen) + 1000, + + sub(&Object::nameLen, &Object::number), + c(&Object::nameLen) - &Object::number, + &Object::nameLen - c(&Object::number), + c(&Object::nameLen) - c(&Object::number), + c(&Object::nameLen) - 1000, + + mul(&Object::nameLen, &Object::number), + c(&Object::nameLen) * &Object::number, + &Object::nameLen * c(&Object::number), + c(&Object::nameLen) * c(&Object::number), + c(&Object::nameLen) * 1000, + + div(&Object::nameLen, &Object::number), + c(&Object::nameLen) / &Object::number, + &Object::nameLen / c(&Object::number), + c(&Object::nameLen) / c(&Object::number), + c(&Object::nameLen) / 2)); - auto expectedDivNumber = int(name.length()) / number; - assert(std::get<19>(row) == expectedDivNumber); - assert(std::get<20>(row) == std::get<19>(row)); - assert(std::get<21>(row) == std::get<20>(row)); - assert(std::get<22>(row) == std::get<21>(row)); - assert(std::get<23>(row) == int(name.length()) / 2); - } - - auto rows2 = storage.select(columns(mod(&Object::nameLen, &Object::number), - c(&Object::nameLen) % &Object::number, - &Object::nameLen % c(&Object::number), - c(&Object::nameLen) % c(&Object::number), - c(&Object::nameLen) % 5)); - for(size_t i = 0; i < rows2.size(); ++i) { - auto &row = rows2[i]; - auto &name = names[i]; - assert(std::get<0>(row) == static_cast(name.length()) % number); - assert(std::get<1>(row) == std::get<0>(row)); - assert(std::get<2>(row) == std::get<1>(row)); - assert(std::get<3>(row) == std::get<2>(row)); - assert(std::get<4>(row) == static_cast(name.length()) % 5); + for(size_t i = 0; i < rows.size(); ++i) { + auto &row = rows[i]; + auto &name = names[i]; + assert(std::get<0>(row) == name + suffix); + assert(std::get<1>(row) == std::get<0>(row)); + assert(std::get<2>(row) == std::get<1>(row)); + assert(std::get<3>(row) == std::get<2>(row)); + + auto expectedAddNumber = int(name.length()) + number; + assert(std::get<4>(row) == expectedAddNumber); + assert(std::get<5>(row) == std::get<4>(row)); + assert(std::get<6>(row) == std::get<5>(row)); + assert(std::get<7>(row) == std::get<6>(row)); + { + auto &rowValue = std::get<8>(row); + assert(rowValue == int(name.length()) + 1000); + } + + auto expectedSubNumber = int(name.length()) - number; + assert(std::get<9>(row) == expectedSubNumber); + assert(std::get<10>(row) == std::get<9>(row)); + assert(std::get<11>(row) == std::get<10>(row)); + assert(std::get<12>(row) == std::get<11>(row)); + assert(std::get<13>(row) == int(name.length()) - 1000); + + auto expectedMulNumber = int(name.length()) * number; + assert(std::get<14>(row) == expectedMulNumber); + assert(std::get<15>(row) == std::get<14>(row)); + assert(std::get<16>(row) == std::get<15>(row)); + assert(std::get<17>(row) == std::get<16>(row)); + assert(std::get<18>(row) == int(name.length()) * 1000); + + auto expectedDivNumber = int(name.length()) / number; + assert(std::get<19>(row) == expectedDivNumber); + assert(std::get<20>(row) == std::get<19>(row)); + assert(std::get<21>(row) == std::get<20>(row)); + assert(std::get<22>(row) == std::get<21>(row)); + assert(std::get<23>(row) == int(name.length()) / 2); + } + } + { + auto rows = storage.select(columns(mod(&Object::nameLen, &Object::number), + c(&Object::nameLen) % &Object::number, + &Object::nameLen % c(&Object::number), + c(&Object::nameLen) % c(&Object::number), + c(&Object::nameLen) % 5)); + for(size_t i = 0; i < rows.size(); ++i) { + auto &row = rows[i]; + auto &name = names[i]; + assert(std::get<0>(row) == static_cast(name.length()) % number); + assert(std::get<1>(row) == std::get<0>(row)); + assert(std::get<2>(row) == std::get<1>(row)); + assert(std::get<3>(row) == std::get<2>(row)); + assert(std::get<4>(row) == static_cast(name.length()) % 5); + } } } @@ -1494,6 +1526,29 @@ void testSelect() { sqlite3_finalize(stmt); auto secondId = sqlite3_last_insert_rowid(db); + + { + // SELECT ID, CURRENT_WORD, BEFORE_WORD, AFTER_WORD, OCCURANCES + // FROM WORDS + // WHERE ID = firstId + + sql = "SELECT ID, CURRENT_WORD, BEFORE_WORD, AFTER_WORD, OCCURANCES FROM WORDS WHERE ID = ?"; + rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr); + assert(rc == SQLITE_OK); + + sqlite3_bind_int64(stmt, 1, firstId); + rc = sqlite3_step(stmt); + if(rc != SQLITE_ROW){ + cout << sqlite3_errmsg(db) << endl; + throw std::runtime_error(sqlite3_errmsg(db)); + } + assert(sqlite3_column_int(stmt, 0) == firstId); + assert(::strcmp((const char *)sqlite3_column_text(stmt, 1), "best") == 0); + assert(::strcmp((const char *)sqlite3_column_text(stmt, 2), "behaviour") == 0); + assert(::strcmp((const char *)sqlite3_column_text(stmt, 3), "hey") == 0); + assert(sqlite3_column_int(stmt, 4) == 5); + sqlite3_finalize(stmt); + } sqlite3_close(db); @@ -1507,18 +1562,11 @@ void testSelect() { auto storage = make_storage(dbFileName, make_table("WORDS", - make_column("ID", - &Word::id, - primary_key(), - autoincrement()), - make_column("CURRENT_WORD", - &Word::currentWord), - make_column("BEFORE_WORD", - &Word::beforeWord), - make_column("AFTER_WORD", - &Word::afterWord), - make_column("OCCURANCES", - &Word::occurances))); + make_column("ID", &Word::id, primary_key(), autoincrement()), + make_column("CURRENT_WORD", &Word::currentWord), + make_column("BEFORE_WORD", &Word::beforeWord), + make_column("AFTER_WORD", &Word::afterWord), + make_column("OCCURANCES", &Word::occurances))); storage.sync_schema(); // sync schema must not alter any data cause schemas are the same @@ -2434,7 +2482,7 @@ int main(int, char **) { cout << "version = " << make_storage("").libversion() << endl; - testTypeParsing(); + /*testTypeParsing(); testSyncSchema(); @@ -2487,10 +2535,11 @@ int main(int, char **) { testIssue105(); testMultiOrderBy(); + */ testOperators(); - testAutoVacuum(); + /*testAutoVacuum(); testVacuum(); @@ -2522,5 +2571,5 @@ int main(int, char **) { testIterateBlob(); - testIsNull(); + testIsNull();*/ } From 15c4151514310b7b0665107e307f6d05f73e49ba Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 30 May 2019 23:11:55 +0300 Subject: [PATCH 095/232] added os to appveyor --- appveyor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 9a6fcc924..b73649ddd 100755 --- a/appveyor.yml +++ b/appveyor.yml @@ -9,6 +9,8 @@ install: image: - Visual Studio 2017 + +os: Visual Studio 2015 Preview # configurations to add to build matrix # TODO: MinGW Makefiles and MSYS Makefiles From 45fd0e718ee17bfd624fdf09dd568aac124340c9 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 30 May 2019 23:52:42 +0300 Subject: [PATCH 096/232] specified vs version --- appveyor.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index b73649ddd..a52f88b8c 100755 --- a/appveyor.yml +++ b/appveyor.yml @@ -8,9 +8,7 @@ install: - git submodule update --init --recursive image: - - Visual Studio 2017 - -os: Visual Studio 2015 Preview + - Visual Studio 2017 v15.7.5 # configurations to add to build matrix # TODO: MinGW Makefiles and MSYS Makefiles From 0daef2d965463cdf303cec40e41d242d0a0a5594 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Fri, 31 May 2019 15:47:53 +0300 Subject: [PATCH 097/232] removed declval cause it make vc++ crash --- dev/statement_binder.h | 17 ++++------------- include/sqlite_orm/sqlite_orm.h | 28 +++++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/dev/statement_binder.h b/dev/statement_binder.h index e26c00fe1..1eb6a56c6 100644 --- a/dev/statement_binder.h +++ b/dev/statement_binder.h @@ -18,7 +18,7 @@ namespace sqlite_orm { * Helper class used for binding fields to sqlite3 statements. */ template - struct statement_binder; + struct statement_binder : std::false_type {}; /** * Specialization for arithmetic types. @@ -118,15 +118,8 @@ namespace sqlite_orm { namespace internal { - // got it from here https://stackoverflow.com/questions/44229676/how-to-decide-if-a-template-specialization-exist - - template - std::true_type is_bindable_impl(T *); - - std::false_type is_bindable_impl(...); - - template - using is_bindable = decltype(is_bindable_impl(std::declval*>())); + template + using is_bindable = std::integral_constant>::value>; struct conditional_binder_base { sqlite3_stmt *stmt = nullptr; @@ -147,9 +140,7 @@ namespace sqlite_orm { using conditional_binder_base::conditional_binder_base; void operator()(const T &t) const { - /*auto bindResult =*/ statement_binder().bind(this->stmt, this->index++, t); -// auto errorText = -// bindResult = bindResult; + statement_binder().bind(this->stmt, this->index++, t); } }; diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 20fc86f46..2f68da141 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -3992,7 +3992,7 @@ namespace sqlite_orm { * Helper class used for binding fields to sqlite3 statements. */ template - struct statement_binder; + struct statement_binder : std::false_type {}; /** * Specialization for arithmetic types. @@ -4094,13 +4094,35 @@ namespace sqlite_orm { // got it from here https://stackoverflow.com/questions/44229676/how-to-decide-if-a-template-specialization-exist - template + /*template std::true_type is_bindable_impl(T *); std::false_type is_bindable_impl(...); template - using is_bindable = decltype(is_bindable_impl(std::declval*>())); +// using is_bindable = decltype(is_bindable_impl(std::declval*>())); + using is_bindable = decltype(is_bindable_impl(statement_binder*));*/ + + /*template + struct is_bindable_impl { + + template + struct SFINAE {}; + + template + static char test(SFINAE*); + + template + static int test(...); + + static const bool value = sizeof(test(0)) == sizeof(char); + }; + + template + using is_bindable = is_bindable_impl>;*/ + + template + using is_bindable = std::integral_constant>::value>; struct conditional_binder_base { sqlite3_stmt *stmt = nullptr; From ae4ea94e113ea75f6ac2b5af6429022403121218 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Fri, 31 May 2019 15:53:39 +0300 Subject: [PATCH 098/232] reverted appveyor version --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index a52f88b8c..9a6fcc924 100755 --- a/appveyor.yml +++ b/appveyor.yml @@ -8,7 +8,7 @@ install: - git submodule update --init --recursive image: - - Visual Studio 2017 v15.7.5 + - Visual Studio 2017 # configurations to add to build matrix # TODO: MinGW Makefiles and MSYS Makefiles From 504794c4b6814b064f24415e256652bee919e18f Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sun, 2 Jun 2019 10:50:06 +0300 Subject: [PATCH 099/232] refactored bindings --- dev/ast_iterator.h | 87 ++++- dev/conditions.h | 38 +- dev/statement_binder.h | 6 +- dev/storage.h | 335 ++++-------------- dev/view.h | 7 + include/sqlite_orm/sqlite_orm.h | 602 ++++++++++++-------------------- tests/tests.cpp | 90 +++-- 7 files changed, 457 insertions(+), 708 deletions(-) diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index 5670affa4..79b0136f7 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -1,10 +1,11 @@ #pragma once +#include // std::vector + #include "conditions.h" #include "select_constraints.h" #include "operators.h" - -#include +#include "tuple_helper.h" namespace sqlite_orm { @@ -22,7 +23,7 @@ namespace sqlite_orm { */ template void operator()(const T &t, const L &l) const { - std::cout << "t is " << typeid(t).name() << std::endl; + l(t); } }; @@ -49,8 +50,8 @@ namespace sqlite_orm { template void operator()(const node_type &binaryCondition, const L &l) const { - l(binaryCondition.l); - l(binaryCondition.r); + iterate_ast(binaryCondition.l, l); + iterate_ast(binaryCondition.r, l); } }; @@ -60,8 +61,8 @@ namespace sqlite_orm { template void operator()(const node_type &binaryOperator, const L &l) const { - l(binaryOperator.l); - l(binaryOperator.r); + iterate_ast(binaryOperator.l, l); + iterate_ast(binaryOperator.r, l); } }; @@ -71,7 +72,7 @@ namespace sqlite_orm { template void operator()(const node_type &assign, const C &l) const { - l(assign.r); + iterate_ast(assign.r, l); } }; @@ -87,15 +88,71 @@ namespace sqlite_orm { } }; - /*template - struct ast_iterator, void> { - using node_type = conc_t; + template + struct ast_iterator, void> { + using node_type = conditions::in_t; template - void operator()(const node_type &conc, const C &l) const { - l(conc.l); - l(conc.r); + void operator()(const node_type &in, const C &l) const { + iterate_ast(in.l, l); + iterate_ast(in.arg, l); } - };*/ + }; + + template + struct ast_iterator, void> { + using node_type = std::vector; + + template + void operator()(const node_type &vec, const L &l) const { + for(auto &i : vec) { + iterate_ast(i, l); + } + } + }; + + template<> + struct ast_iterator, void> { + using node_type = std::vector; + + template + void operator()(const node_type &vec, const L &l) const { + l(vec); + } + }; + + template + struct ast_iterator::value>::type> { + using node_type = T; + + template + void operator()(const node_type &c, const L &l) const { + iterate_ast(c.left, l); + iterate_ast(c.right, l); + } + }; + + template + struct ast_iterator, void> { + using node_type = select_t; + + template + void operator()(const node_type &sel, const L &l) const { + iterate_ast(sel.col, l); + iterate_ast(sel.conditions, l); + } + }; + + template + struct ast_iterator, void> { + using node_type = std::tuple; + + template + void operator()(const node_type &tuple, const L &l) const { + tuple_helper::iterator::value - 1, Args...>()(tuple, [&l](auto &v){ + iterate_ast(v, l); + }); + } + }; } } diff --git a/dev/conditions.h b/dev/conditions.h index 4980efdbb..6f81b05a9 100644 --- a/dev/conditions.h +++ b/dev/conditions.h @@ -100,50 +100,44 @@ namespace sqlite_orm { }; /** - * Result of and operator + * Base class for binary conditions */ template - struct and_condition_t : public condition_t { + struct binary_condition : public condition_t { L l; R r; - and_condition_t() = default; - - and_condition_t(L l_, R r_): l(l_), r(r_) {} + binary_condition() = default; - operator std::string () const { - return "AND"; - } + binary_condition(L l_, R r_): l(l_), r(r_) {} }; /** - * Result of or operator + * Result of and operator */ template - struct or_condition_t : public condition_t { - L l; - R r; + struct and_condition_t : public binary_condition { + using super = binary_condition; - or_condition_t() = default; - - or_condition_t(L l_, R r_): l(l_), r(r_) {} + using super::super; operator std::string () const { - return "OR"; + return "AND"; } }; /** - * Base class for binary conditions + * Result of or operator */ template - struct binary_condition : public condition_t { - L l; - R r; + struct or_condition_t : public binary_condition { + using super = binary_condition; - binary_condition() = default; + using super::super; - binary_condition(L l_, R r_): l(l_), r(r_) {} + operator std::string () const { + return "OR"; + } }; /** diff --git a/dev/statement_binder.h b/dev/statement_binder.h index 1eb6a56c6..e2925d89f 100644 --- a/dev/statement_binder.h +++ b/dev/statement_binder.h @@ -105,9 +105,9 @@ namespace sqlite_orm { /** * Specialization for optional type (std::vector). */ - template - struct statement_binder>::value>> { - int bind(sqlite3_stmt *stmt, int index, const V &value) { + template<> + struct statement_binder, void> { + int bind(sqlite3_stmt *stmt, int index, const std::vector &value) { if (value.size()) { return sqlite3_bind_blob(stmt, index, (const void *)&value.front(), int(value.size()), SQLITE_TRANSIENT); }else{ diff --git a/dev/storage.h b/dev/storage.h index a14797e5b..8e89239a7 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -15,7 +15,6 @@ #include // std::forward, std::pair #include // std::set #include // std::find -#include #include "alias.h" #include "database_connection.h" @@ -499,7 +498,7 @@ namespace sqlite_orm { template std::string string_from_expression(const aggregate_functions::min_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.t, false); + auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } @@ -1105,16 +1104,11 @@ namespace sqlite_orm { } template - void process_conditions(std::stringstream &ss, std::tuple args) { - this->process_single_condition(ss, tuple_helper::head(args)); - this->process_conditions(ss, tuple_helper::tail(args)); - } - - /** - * Recursion end. - */ - void process_conditions(std::stringstream &, std::tuple<> /*args*/) { - //.. + void process_conditions(std::stringstream &ss, const std::tuple &args) { + using argsType = typename std::decay::type; + tuple_helper::iterator::value - 1, Args...>()(args, [this, &ss](auto &v){ + this->process_single_condition(ss, v); + }); } void on_open_internal(sqlite3 *db) { @@ -1383,17 +1377,11 @@ namespace sqlite_orm { binder(node); }); }); - tuple_helper::iterator::value - 1, Wargs...>()(whereArgsTuple, [stmt, &index](auto &v){ - using arg_type = typename std::decay::type; -// std::cout << "v is " << typeid(arg_type).name() << std::endl; - - iterate_ast(v, [stmt, &index](auto &node){ - using node_type = typename std::decay::type; - conditional_binder> binder{stmt, index}; - binder(node); - }); + iterate_ast(whereArgsTuple, [stmt, &index](auto &node){ + using node_type = typename std::decay::type; + conditional_binder> binder{stmt, index}; + binder(node); }); - if (sqlite3_step(stmt) == SQLITE_DONE) { // done.. }else{ @@ -1419,7 +1407,7 @@ namespace sqlite_orm { * @return impl for O */ template - auto& generate_select_asterisk(std::string *query, std::tuple args) { + auto& generate_select_asterisk(std::string *query, const std::tuple &args) { std::stringstream ss; ss << "SELECT "; auto &impl = this->get_impl(); @@ -1729,39 +1717,19 @@ namespace sqlite_orm { } template - std::string group_concat_internal(F O::*m, std::unique_ptr y, Args&& ...args) { + std::string group_concat_internal(F O::*m, std::unique_ptr y, Args&& ...args) { this->assert_mapped_type(); - - auto connection = this->get_or_create_connection(); - auto &impl = this->get_impl(); - std::string res; - std::stringstream ss; - ss << "SELECT " << static_cast(sqlite_orm::group_concat(0)) << "("; - auto columnName = this->string_from_expression(m, false, false); - if(columnName.length()){ - ss << columnName; - if(y){ - ss << ",\"" << *y << "\""; - } - ss << ") FROM '"<< impl.table.name << "' "; - this->process_conditions(ss, std::make_tuple(std::forward(args)...)); - auto query = ss.str(); - auto rc = sqlite3_exec(connection->get_db(), - query.c_str(), - [](void *data, int argc, char **argv,char **) -> int { - auto &res = *(std::string*)data; - if(argc){ - res = row_extractor().extract(argv[0]); - } - return 0; - }, &res, nullptr); - if(rc != SQLITE_OK) { - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); - } + std::vector rows; + if(y){ + rows = this->select(sqlite_orm::group_concat(m, move(*y)), std::forward(args)...); }else{ - throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + rows = this->select(sqlite_orm::group_concat(m), std::forward(args)...); + } + if(!rows.empty()){ + return move(rows.front()); + }else{ + return {}; } - return res; } public: @@ -1778,10 +1746,17 @@ namespace sqlite_orm { auto connection = this->get_or_create_connection(); C res; std::string query; - auto &impl = this->generate_select_asterisk(&query, std::make_tuple(std::forward(args)...)); + auto argsTuple = std::make_tuple(std::forward(args)...); + auto &impl = this->generate_select_asterisk(&query, argsTuple); sqlite3_stmt *stmt; if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; + auto index = 1; + iterate_ast(argsTuple, [stmt, &index](auto &node){ + using node_type = typename std::decay::type; + conditional_binder> binder{stmt, index}; + binder(node); + }); int stepRes; do{ stepRes = sqlite3_step(stmt); @@ -1983,37 +1958,18 @@ namespace sqlite_orm { } /** - * SELECT COUNT(*) with no conditions routine. https://www.sqlite.org/lang_aggfunc.html#count + * SELECT COUNT(*) https://www.sqlite.org/lang_aggfunc.html#count * @return Number of O object in table. */ template::type> int count(Args&& ...args) { - this->assert_mapped_type(); - auto tableAliasString = alias_extractor::get(); - - auto connection = this->get_or_create_connection(); - auto &impl = this->get_impl(); - int res = 0; - std::stringstream ss; - ss << "SELECT " << static_cast(sqlite_orm::count()) << "(*) FROM '" << impl.table.name << "' "; - if(!tableAliasString.empty()) { - ss << "'" << tableAliasString << "' "; - } - this->process_conditions(ss, std::make_tuple(std::forward(args)...)); - auto query = ss.str(); - auto rc = sqlite3_exec(connection->get_db(), - query.c_str(), - [](void *data, int argc, char **argv, char **) -> int { - auto &res = *(int*)data; - if(argc){ - res = row_extractor().extract(argv[0]); - } - return 0; - }, &res, nullptr); - if(rc != SQLITE_OK) { - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + this->assert_mapped_type(); + auto rows = this->select(sqlite_orm::count(), std::forward(args)...); + if(!rows.empty()){ + return rows.front(); + }else{ + return 0; } - return res; } /** @@ -2023,33 +1979,12 @@ namespace sqlite_orm { template int count(F O::*m, Args&& ...args) { this->assert_mapped_type(); - - auto connection = this->get_or_create_connection(); - auto &impl = this->get_impl(); - int res = 0; - std::stringstream ss; - ss << "SELECT " << static_cast(sqlite_orm::count(0)) << "("; - auto columnName = this->string_from_expression(m, false, false); - if(columnName.length()){ - ss << columnName << ") FROM '"<< impl.table.name << "' "; - this->process_conditions(ss, std::make_tuple(std::forward(args)...)); - auto query = ss.str(); - auto rc = sqlite3_exec(connection->get_db(), - query.c_str(), - [](void *data, int argc, char **argv,char **) -> int { - auto &res = *(int*)data; - if(argc){ - res = row_extractor().extract(argv[0]); - } - return 0; - }, &res, nullptr); - if(rc != SQLITE_OK) { - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); - } + auto rows = this->select(sqlite_orm::count(m), std::forward(args)...); + if(!rows.empty()){ + return rows.front(); }else{ - throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + return 0; } - return res; } /** @@ -2060,33 +1995,12 @@ namespace sqlite_orm { template double avg(F O::*m, Args&& ...args) { this->assert_mapped_type(); - - auto connection = this->get_or_create_connection(); - auto &impl = this->get_impl(); - double res = 0; - std::stringstream ss; - ss << "SELECT " << static_cast(sqlite_orm::avg(0)) << "("; - auto columnName = this->string_from_expression(m, false, false); - if(columnName.length()){ - ss << columnName << ") FROM '"<< impl.table.name << "' "; - this->process_conditions(ss, std::make_tuple(std::forward(args)...)); - auto query = ss.str(); - auto rc = sqlite3_exec(connection->get_db(), - query.c_str(), - [](void *data, int argc, char **argv,char **)->int{ - auto &res = *(double*)data; - if(argc){ - res = row_extractor().extract(argv[0]); - } - return 0; - }, &res, nullptr); - if(rc != SQLITE_OK) { - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); - } + auto rows = this->select(sqlite_orm::avg(m), std::forward(args)...); + if(!rows.empty()){ + return rows.front(); }else{ - throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + return 0; } - return res; } template @@ -2113,13 +2027,19 @@ namespace sqlite_orm { * @return group_concat query result. */ template - std::string group_concat(F O::*m, const std::string &y, Args&& ...args) { - return this->group_concat_internal(m, std::make_unique(y), std::forward(args)...); + std::string group_concat(F O::*m, std::string y, Args&& ...args) { + return this->group_concat_internal(m, std::make_unique(move(y)), std::forward(args)...); } template std::string group_concat(F O::*m, const char *y, Args&& ...args) { - return this->group_concat_internal(m, std::make_unique(y), std::forward(args)...); + std::unique_ptr str; + if(y){ + str = std::make_unique(y); + }else{ + str = std::make_unique(); + } + return this->group_concat_internal(m, move(str), std::forward(args)...); } /** @@ -2130,35 +2050,12 @@ namespace sqlite_orm { template::type> std::unique_ptr max(F O::*m, Args&& ...args) { this->assert_mapped_type(); - - auto connection = this->get_or_create_connection(); - auto &impl = this->get_impl(); - std::unique_ptr res; - std::stringstream ss; - ss << "SELECT " << static_cast(sqlite_orm::max(0)) << "("; - auto columnName = this->string_from_expression(m, false, false); - if(columnName.length()){ - ss << columnName << ") FROM '" << impl.table.name << "' "; - this->process_conditions(ss, std::make_tuple(std::forward(args)...)); - auto query = ss.str(); - auto rc = sqlite3_exec(connection->get_db(), - query.c_str(), - [](void *data, int argc, char **argv,char **)->int{ - auto &res = *(std::unique_ptr*)data; - if(argc){ - if(argv[0]){ - res = std::make_unique(row_extractor().extract(argv[0])); - } - } - return 0; - }, &res, nullptr); - if(rc != SQLITE_OK) { - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); - } + auto rows = this->select(sqlite_orm::max(m), std::forward(args)...); + if(!rows.empty()){ + return std::move(rows.front()); }else{ - throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + return {}; } - return res; } /** @@ -2169,35 +2066,12 @@ namespace sqlite_orm { template::type> std::unique_ptr min(F O::*m, Args&& ...args) { this->assert_mapped_type(); - - auto connection = this->get_or_create_connection(); - auto &impl = this->get_impl(); - std::unique_ptr res; - std::stringstream ss; - ss << "SELECT " << static_cast(sqlite_orm::min(0)) << "("; - auto columnName = this->string_from_expression(m, false, false); - if(columnName.length()){ - ss << columnName << ") FROM '" << impl.table.name << "' "; - this->process_conditions(ss, std::make_tuple(std::forward(args)...)); - auto query = ss.str(); - auto rc = sqlite3_exec(connection->get_db(), - query.c_str(), - [](void *data, int argc, char **argv,char **)->int{ - auto &res = *(std::unique_ptr*)data; - if(argc){ - if(argv[0]){ - res = std::make_unique(row_extractor().extract(argv[0])); - } - } - return 0; - }, &res, nullptr); - if(rc != SQLITE_OK) { - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); - } + auto rows = this->select(sqlite_orm::min(m), std::forward(args)...); + if(!rows.empty()){ + return std::move(rows.front()); }else{ - throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + return {}; } - return res; } /** @@ -2208,33 +2082,16 @@ namespace sqlite_orm { template::type> std::unique_ptr sum(F O::*m, Args&& ...args) { this->assert_mapped_type(); - - auto connection = this->get_or_create_connection(); - auto &impl = this->get_impl(); - std::unique_ptr res; - std::stringstream ss; - ss << "SELECT " << static_cast(sqlite_orm::sum(0)) << "("; - auto columnName = this->string_from_expression(m, false, false); - if(columnName.length()){ - ss << columnName << ") FROM '"<< impl.table.name << "' "; - this->process_conditions(ss, std::make_tuple(std::forward(args)...)); - auto query = ss.str(); - auto rc = sqlite3_exec(connection->get_db(), - query.c_str(), - [](void *data, int argc, char **argv, char **)->int{ - auto &res = *(std::unique_ptr*)data; - if(argc){ - res = std::make_unique(row_extractor().extract(argv[0])); - } - return 0; - }, &res, nullptr); - if(rc != SQLITE_OK) { - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + std::vector> rows = this->select(sqlite_orm::sum(m), std::forward(args)...); + if(!rows.empty()){ + if(rows.front()){ + return std::make_unique(std::move(*rows.front())); + }else{ + return {}; } }else{ - throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + return {}; } - return res; } /** @@ -2245,44 +2102,12 @@ namespace sqlite_orm { template double total(F O::*m, Args&& ...args) { this->assert_mapped_type(); - - auto connection = this->get_or_create_connection(); - double res = 0; - std::stringstream ss; - ss << "SELECT " << static_cast(sqlite_orm::total(0)) << "("; - auto columnName = this->string_from_expression(m, false, false); - if(!columnName.empty()){ - ss << columnName << ") "; - auto tableNamesSet = this->parse_table_names(m); - if(!tableNamesSet.empty()){ - ss << "FROM " ; - std::vector> tableNames(tableNamesSet.begin(), tableNamesSet.end()); - for(size_t i = 0; i < tableNames.size(); ++i) { - ss << "'" << tableNames[i].first << "' "; - if(i < tableNames.size() - 1) { - ss << ","; - } - ss << " "; - } - } - this->process_conditions(ss, std::make_tuple(std::forward(args)...)); - auto query = ss.str(); - auto rc = sqlite3_exec(connection->get_db(), - query.c_str(), - [](void *data, int argc, char **argv, char **)->int{ - auto &res = *(double*)data; - if(argc){ - res = row_extractor().extract(argv[0]); - } - return 0; - }, &res, nullptr); - if(rc != SQLITE_OK) { - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); - } + auto rows = this->select(sqlite_orm::total(m), std::forward(args)...); + if(!rows.empty()){ + return std::move(rows.front()); }else{ - throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + return {}; } - return res; } /** @@ -2305,25 +2130,11 @@ namespace sqlite_orm { if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; - using conditions_type = typename select_type::conditions_type; - - iterate_ast(sel.col, [stmt, &index](auto &node){ + iterate_ast(sel, [stmt, &index](auto &node){ using node_type = typename std::decay::type; conditional_binder> binder{stmt, index}; binder(node); }); - - tuple_helper::iterator::value - 1, Args...>()(sel.conditions, [stmt, &index](auto &v){ - using arg_type = typename std::decay::type; - std::cout << "v is " << typeid(arg_type).name() << std::endl; - - iterate_ast(v, [stmt, &index](auto &node){ - using node_type = typename std::decay::type; - conditional_binder> binder{stmt, index}; - binder(node); - }); - }); - std::vector res; int stepRes; do{ diff --git a/dev/view.h b/dev/view.h index 4b54b1342..d7d467e6c 100644 --- a/dev/view.h +++ b/dev/view.h @@ -12,6 +12,7 @@ #include "statement_finalizer.h" #include "error_code.h" #include "iterator.h" +#include "ast_iterator.h" namespace sqlite_orm { @@ -51,6 +52,12 @@ namespace sqlite_orm { this->storage.template generate_select_asterisk(&query, this->args); auto ret = sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr); if(ret == SQLITE_OK){ + auto index = 1; + iterate_ast(this->args, [&index, stmt](auto &node){ + using node_type = typename std::decay::type; + conditional_binder> binder{stmt, index}; + binder(node); + }); return {stmt, *this}; }else{ throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 2f68da141..d72dec023 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -1632,50 +1632,44 @@ namespace sqlite_orm { }; /** - * Result of and operator + * Base class for binary conditions */ template - struct and_condition_t : public condition_t { + struct binary_condition : public condition_t { L l; R r; - and_condition_t() = default; - - and_condition_t(L l_, R r_): l(l_), r(r_) {} + binary_condition() = default; - operator std::string () const { - return "AND"; - } + binary_condition(L l_, R r_): l(l_), r(r_) {} }; /** - * Result of or operator + * Result of and operator */ template - struct or_condition_t : public condition_t { - L l; - R r; + struct and_condition_t : public binary_condition { + using super = binary_condition; - or_condition_t() = default; - - or_condition_t(L l_, R r_): l(l_), r(r_) {} + using super::super; operator std::string () const { - return "OR"; + return "AND"; } }; /** - * Base class for binary conditions + * Result of or operator */ template - struct binary_condition : public condition_t { - L l; - R r; + struct or_condition_t : public binary_condition { + using super = binary_condition; - binary_condition() = default; + using super::super; - binary_condition(L l_, R r_): l(l_), r(r_) {} + operator std::string () const { + return "OR"; + } }; /** @@ -4079,9 +4073,9 @@ namespace sqlite_orm { /** * Specialization for optional type (std::vector). */ - template - struct statement_binder>::value>> { - int bind(sqlite3_stmt *stmt, int index, const V &value) { + template<> + struct statement_binder, void> { + int bind(sqlite3_stmt *stmt, int index, const std::vector &value) { if (value.size()) { return sqlite3_bind_blob(stmt, index, (const void *)&value.front(), int(value.size()), SQLITE_TRANSIENT); }else{ @@ -4092,35 +4086,6 @@ namespace sqlite_orm { namespace internal { - // got it from here https://stackoverflow.com/questions/44229676/how-to-decide-if-a-template-specialization-exist - - /*template - std::true_type is_bindable_impl(T *); - - std::false_type is_bindable_impl(...); - - template -// using is_bindable = decltype(is_bindable_impl(std::declval*>())); - using is_bindable = decltype(is_bindable_impl(statement_binder*));*/ - - /*template - struct is_bindable_impl { - - template - struct SFINAE {}; - - template - static char test(SFINAE*); - - template - static int test(...); - - static const bool value = sizeof(test(0)) == sizeof(char); - }; - - template - using is_bindable = is_bindable_impl>;*/ - template using is_bindable = std::integral_constant>::value>; @@ -4143,9 +4108,7 @@ namespace sqlite_orm { using conditional_binder_base::conditional_binder_base; void operator()(const T &t) const { - /*auto bindResult =*/ statement_binder().bind(this->stmt, this->index++, t); -// auto errorText = -// bindResult = bindResult; + statement_binder().bind(this->stmt, this->index++, t); } }; @@ -6237,7 +6200,6 @@ namespace sqlite_orm { #include // std::forward, std::pair #include // std::set #include // std::find -#include // #include "alias.h" @@ -6779,65 +6741,19 @@ namespace sqlite_orm { } } - -namespace sqlite_orm { - - namespace internal { - - template - struct view_t { - using mapped_type = T; - using storage_type = S; - using self = view_t; - - storage_type &storage; - std::shared_ptr connection; - std::tuple args; - - view_t(storage_type &stor, decltype(connection) conn, Args&& ...args_): - storage(stor), - connection(std::move(conn)), - args(std::make_tuple(std::forward(args_)...)){} - - size_t size() { - return this->storage.template count(); - } - - bool empty() { - return !this->size(); - } - - iterator_t end() { - return {nullptr, *this}; - } - - iterator_t begin() { - sqlite3_stmt *stmt = nullptr; - auto db = this->connection->get_db(); - std::string query; - this->storage.template generate_select_asterisk(&query, this->args); - auto ret = sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr); - if(ret == SQLITE_OK){ - return {stmt, *this}; - }else{ - throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); - } - } - }; - } -} - // #include "ast_iterator.h" +#include // std::vector + // #include "conditions.h" // #include "select_constraints.h" // #include "operators.h" +// #include "tuple_helper.h" -#include namespace sqlite_orm { @@ -6855,7 +6771,7 @@ namespace sqlite_orm { */ template void operator()(const T &t, const L &l) const { - std::cout << "t is " << typeid(t).name() << std::endl; + l(t); } }; @@ -6882,8 +6798,8 @@ namespace sqlite_orm { template void operator()(const node_type &binaryCondition, const L &l) const { - l(binaryCondition.l); - l(binaryCondition.r); + iterate_ast(binaryCondition.l, l); + iterate_ast(binaryCondition.r, l); } }; @@ -6893,8 +6809,8 @@ namespace sqlite_orm { template void operator()(const node_type &binaryOperator, const L &l) const { - l(binaryOperator.l); - l(binaryOperator.r); + iterate_ast(binaryOperator.l, l); + iterate_ast(binaryOperator.r, l); } }; @@ -6904,7 +6820,7 @@ namespace sqlite_orm { template void operator()(const node_type &assign, const C &l) const { - l(assign.r); + iterate_ast(assign.r, l); } }; @@ -6920,20 +6836,132 @@ namespace sqlite_orm { } }; - /*template - struct ast_iterator, void> { - using node_type = conc_t; + template + struct ast_iterator, void> { + using node_type = conditions::in_t; template - void operator()(const node_type &conc, const C &l) const { - l(conc.l); - l(conc.r); + void operator()(const node_type &in, const C &l) const { + iterate_ast(in.l, l); + iterate_ast(in.arg, l); + } + }; + + template + struct ast_iterator, void> { + using node_type = std::vector; + + template + void operator()(const node_type &vec, const L &l) const { + for(auto &i : vec) { + iterate_ast(i, l); + } + } + }; + + template<> + struct ast_iterator, void> { + using node_type = std::vector; + + template + void operator()(const node_type &vec, const L &l) const { + l(vec); + } + }; + + template + struct ast_iterator::value>::type> { + using node_type = T; + + template + void operator()(const node_type &c, const L &l) const { + iterate_ast(c.left, l); + iterate_ast(c.right, l); } - };*/ + }; + + template + struct ast_iterator, void> { + using node_type = select_t; + + template + void operator()(const node_type &sel, const L &l) const { + iterate_ast(sel.col, l); + iterate_ast(sel.conditions, l); + } + }; + + template + struct ast_iterator, void> { + using node_type = std::tuple; + + template + void operator()(const node_type &tuple, const L &l) const { + tuple_helper::iterator::value - 1, Args...>()(tuple, [&l](auto &v){ + iterate_ast(v, l); + }); + } + }; } } +namespace sqlite_orm { + + namespace internal { + + template + struct view_t { + using mapped_type = T; + using storage_type = S; + using self = view_t; + + storage_type &storage; + std::shared_ptr connection; + std::tuple args; + + view_t(storage_type &stor, decltype(connection) conn, Args&& ...args_): + storage(stor), + connection(std::move(conn)), + args(std::make_tuple(std::forward(args_)...)){} + + size_t size() { + return this->storage.template count(); + } + + bool empty() { + return !this->size(); + } + + iterator_t end() { + return {nullptr, *this}; + } + + iterator_t begin() { + sqlite3_stmt *stmt = nullptr; + auto db = this->connection->get_db(); + std::string query; + this->storage.template generate_select_asterisk(&query, this->args); + auto ret = sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr); + if(ret == SQLITE_OK){ + auto index = 1; + iterate_ast(this->args, [&index, stmt](auto &node){ + using node_type = typename std::decay::type; + conditional_binder> binder{stmt, index}; + binder(node); + }); + return {stmt, *this}; + }else{ + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); + } + } + }; + } +} + +// #include "ast_iterator.h" + + namespace sqlite_orm { namespace internal { @@ -7385,7 +7413,7 @@ namespace sqlite_orm { template std::string string_from_expression(const aggregate_functions::min_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.t, false); + auto expr = this->string_from_expression(f.t, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } @@ -7991,16 +8019,11 @@ namespace sqlite_orm { } template - void process_conditions(std::stringstream &ss, std::tuple args) { - this->process_single_condition(ss, tuple_helper::head(args)); - this->process_conditions(ss, tuple_helper::tail(args)); - } - - /** - * Recursion end. - */ - void process_conditions(std::stringstream &, std::tuple<> /*args*/) { - //.. + void process_conditions(std::stringstream &ss, const std::tuple &args) { + using argsType = typename std::decay::type; + tuple_helper::iterator::value - 1, Args...>()(args, [this, &ss](auto &v){ + this->process_single_condition(ss, v); + }); } void on_open_internal(sqlite3 *db) { @@ -8269,17 +8292,11 @@ namespace sqlite_orm { binder(node); }); }); - tuple_helper::iterator::value - 1, Wargs...>()(whereArgsTuple, [stmt, &index](auto &v){ - using arg_type = typename std::decay::type; -// std::cout << "v is " << typeid(arg_type).name() << std::endl; - - iterate_ast(v, [stmt, &index](auto &node){ - using node_type = typename std::decay::type; - conditional_binder> binder{stmt, index}; - binder(node); - }); + iterate_ast(whereArgsTuple, [stmt, &index](auto &node){ + using node_type = typename std::decay::type; + conditional_binder> binder{stmt, index}; + binder(node); }); - if (sqlite3_step(stmt) == SQLITE_DONE) { // done.. }else{ @@ -8305,7 +8322,7 @@ namespace sqlite_orm { * @return impl for O */ template - auto& generate_select_asterisk(std::string *query, std::tuple args) { + auto& generate_select_asterisk(std::string *query, const std::tuple &args) { std::stringstream ss; ss << "SELECT "; auto &impl = this->get_impl(); @@ -8615,39 +8632,19 @@ namespace sqlite_orm { } template - std::string group_concat_internal(F O::*m, std::unique_ptr y, Args&& ...args) { + std::string group_concat_internal(F O::*m, std::unique_ptr y, Args&& ...args) { this->assert_mapped_type(); - - auto connection = this->get_or_create_connection(); - auto &impl = this->get_impl(); - std::string res; - std::stringstream ss; - ss << "SELECT " << static_cast(sqlite_orm::group_concat(0)) << "("; - auto columnName = this->string_from_expression(m, false, false); - if(columnName.length()){ - ss << columnName; - if(y){ - ss << ",\"" << *y << "\""; - } - ss << ") FROM '"<< impl.table.name << "' "; - this->process_conditions(ss, std::make_tuple(std::forward(args)...)); - auto query = ss.str(); - auto rc = sqlite3_exec(connection->get_db(), - query.c_str(), - [](void *data, int argc, char **argv,char **) -> int { - auto &res = *(std::string*)data; - if(argc){ - res = row_extractor().extract(argv[0]); - } - return 0; - }, &res, nullptr); - if(rc != SQLITE_OK) { - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); - } + std::vector rows; + if(y){ + rows = this->select(sqlite_orm::group_concat(m, move(*y)), std::forward(args)...); }else{ - throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + rows = this->select(sqlite_orm::group_concat(m), std::forward(args)...); + } + if(!rows.empty()){ + return move(rows.front()); + }else{ + return {}; } - return res; } public: @@ -8664,10 +8661,17 @@ namespace sqlite_orm { auto connection = this->get_or_create_connection(); C res; std::string query; - auto &impl = this->generate_select_asterisk(&query, std::make_tuple(std::forward(args)...)); + auto argsTuple = std::make_tuple(std::forward(args)...); + auto &impl = this->generate_select_asterisk(&query, argsTuple); sqlite3_stmt *stmt; if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; + auto index = 1; + iterate_ast(argsTuple, [stmt, &index](auto &node){ + using node_type = typename std::decay::type; + conditional_binder> binder{stmt, index}; + binder(node); + }); int stepRes; do{ stepRes = sqlite3_step(stmt); @@ -8869,37 +8873,18 @@ namespace sqlite_orm { } /** - * SELECT COUNT(*) with no conditions routine. https://www.sqlite.org/lang_aggfunc.html#count + * SELECT COUNT(*) https://www.sqlite.org/lang_aggfunc.html#count * @return Number of O object in table. */ template::type> int count(Args&& ...args) { - this->assert_mapped_type(); - auto tableAliasString = alias_extractor::get(); - - auto connection = this->get_or_create_connection(); - auto &impl = this->get_impl(); - int res = 0; - std::stringstream ss; - ss << "SELECT " << static_cast(sqlite_orm::count()) << "(*) FROM '" << impl.table.name << "' "; - if(!tableAliasString.empty()) { - ss << "'" << tableAliasString << "' "; - } - this->process_conditions(ss, std::make_tuple(std::forward(args)...)); - auto query = ss.str(); - auto rc = sqlite3_exec(connection->get_db(), - query.c_str(), - [](void *data, int argc, char **argv, char **) -> int { - auto &res = *(int*)data; - if(argc){ - res = row_extractor().extract(argv[0]); - } - return 0; - }, &res, nullptr); - if(rc != SQLITE_OK) { - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + this->assert_mapped_type(); + auto rows = this->select(sqlite_orm::count(), std::forward(args)...); + if(!rows.empty()){ + return rows.front(); + }else{ + return 0; } - return res; } /** @@ -8909,33 +8894,12 @@ namespace sqlite_orm { template int count(F O::*m, Args&& ...args) { this->assert_mapped_type(); - - auto connection = this->get_or_create_connection(); - auto &impl = this->get_impl(); - int res = 0; - std::stringstream ss; - ss << "SELECT " << static_cast(sqlite_orm::count(0)) << "("; - auto columnName = this->string_from_expression(m, false, false); - if(columnName.length()){ - ss << columnName << ") FROM '"<< impl.table.name << "' "; - this->process_conditions(ss, std::make_tuple(std::forward(args)...)); - auto query = ss.str(); - auto rc = sqlite3_exec(connection->get_db(), - query.c_str(), - [](void *data, int argc, char **argv,char **) -> int { - auto &res = *(int*)data; - if(argc){ - res = row_extractor().extract(argv[0]); - } - return 0; - }, &res, nullptr); - if(rc != SQLITE_OK) { - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); - } + auto rows = this->select(sqlite_orm::count(m), std::forward(args)...); + if(!rows.empty()){ + return rows.front(); }else{ - throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + return 0; } - return res; } /** @@ -8946,33 +8910,12 @@ namespace sqlite_orm { template double avg(F O::*m, Args&& ...args) { this->assert_mapped_type(); - - auto connection = this->get_or_create_connection(); - auto &impl = this->get_impl(); - double res = 0; - std::stringstream ss; - ss << "SELECT " << static_cast(sqlite_orm::avg(0)) << "("; - auto columnName = this->string_from_expression(m, false, false); - if(columnName.length()){ - ss << columnName << ") FROM '"<< impl.table.name << "' "; - this->process_conditions(ss, std::make_tuple(std::forward(args)...)); - auto query = ss.str(); - auto rc = sqlite3_exec(connection->get_db(), - query.c_str(), - [](void *data, int argc, char **argv,char **)->int{ - auto &res = *(double*)data; - if(argc){ - res = row_extractor().extract(argv[0]); - } - return 0; - }, &res, nullptr); - if(rc != SQLITE_OK) { - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); - } + auto rows = this->select(sqlite_orm::avg(m), std::forward(args)...); + if(!rows.empty()){ + return rows.front(); }else{ - throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + return 0; } - return res; } template @@ -8999,13 +8942,19 @@ namespace sqlite_orm { * @return group_concat query result. */ template - std::string group_concat(F O::*m, const std::string &y, Args&& ...args) { - return this->group_concat_internal(m, std::make_unique(y), std::forward(args)...); + std::string group_concat(F O::*m, std::string y, Args&& ...args) { + return this->group_concat_internal(m, std::make_unique(move(y)), std::forward(args)...); } template std::string group_concat(F O::*m, const char *y, Args&& ...args) { - return this->group_concat_internal(m, std::make_unique(y), std::forward(args)...); + std::unique_ptr str; + if(y){ + str = std::make_unique(y); + }else{ + str = std::make_unique(); + } + return this->group_concat_internal(m, move(str), std::forward(args)...); } /** @@ -9016,35 +8965,12 @@ namespace sqlite_orm { template::type> std::unique_ptr max(F O::*m, Args&& ...args) { this->assert_mapped_type(); - - auto connection = this->get_or_create_connection(); - auto &impl = this->get_impl(); - std::unique_ptr res; - std::stringstream ss; - ss << "SELECT " << static_cast(sqlite_orm::max(0)) << "("; - auto columnName = this->string_from_expression(m, false, false); - if(columnName.length()){ - ss << columnName << ") FROM '" << impl.table.name << "' "; - this->process_conditions(ss, std::make_tuple(std::forward(args)...)); - auto query = ss.str(); - auto rc = sqlite3_exec(connection->get_db(), - query.c_str(), - [](void *data, int argc, char **argv,char **)->int{ - auto &res = *(std::unique_ptr*)data; - if(argc){ - if(argv[0]){ - res = std::make_unique(row_extractor().extract(argv[0])); - } - } - return 0; - }, &res, nullptr); - if(rc != SQLITE_OK) { - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); - } + auto rows = this->select(sqlite_orm::max(m), std::forward(args)...); + if(!rows.empty()){ + return std::move(rows.front()); }else{ - throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + return {}; } - return res; } /** @@ -9055,35 +8981,12 @@ namespace sqlite_orm { template::type> std::unique_ptr min(F O::*m, Args&& ...args) { this->assert_mapped_type(); - - auto connection = this->get_or_create_connection(); - auto &impl = this->get_impl(); - std::unique_ptr res; - std::stringstream ss; - ss << "SELECT " << static_cast(sqlite_orm::min(0)) << "("; - auto columnName = this->string_from_expression(m, false, false); - if(columnName.length()){ - ss << columnName << ") FROM '" << impl.table.name << "' "; - this->process_conditions(ss, std::make_tuple(std::forward(args)...)); - auto query = ss.str(); - auto rc = sqlite3_exec(connection->get_db(), - query.c_str(), - [](void *data, int argc, char **argv,char **)->int{ - auto &res = *(std::unique_ptr*)data; - if(argc){ - if(argv[0]){ - res = std::make_unique(row_extractor().extract(argv[0])); - } - } - return 0; - }, &res, nullptr); - if(rc != SQLITE_OK) { - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); - } + auto rows = this->select(sqlite_orm::min(m), std::forward(args)...); + if(!rows.empty()){ + return std::move(rows.front()); }else{ - throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + return {}; } - return res; } /** @@ -9094,33 +8997,16 @@ namespace sqlite_orm { template::type> std::unique_ptr sum(F O::*m, Args&& ...args) { this->assert_mapped_type(); - - auto connection = this->get_or_create_connection(); - auto &impl = this->get_impl(); - std::unique_ptr res; - std::stringstream ss; - ss << "SELECT " << static_cast(sqlite_orm::sum(0)) << "("; - auto columnName = this->string_from_expression(m, false, false); - if(columnName.length()){ - ss << columnName << ") FROM '"<< impl.table.name << "' "; - this->process_conditions(ss, std::make_tuple(std::forward(args)...)); - auto query = ss.str(); - auto rc = sqlite3_exec(connection->get_db(), - query.c_str(), - [](void *data, int argc, char **argv, char **)->int{ - auto &res = *(std::unique_ptr*)data; - if(argc){ - res = std::make_unique(row_extractor().extract(argv[0])); - } - return 0; - }, &res, nullptr); - if(rc != SQLITE_OK) { - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + std::vector> rows = this->select(sqlite_orm::sum(m), std::forward(args)...); + if(!rows.empty()){ + if(rows.front()){ + return std::make_unique(std::move(*rows.front())); + }else{ + return {}; } }else{ - throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + return {}; } - return res; } /** @@ -9131,44 +9017,12 @@ namespace sqlite_orm { template double total(F O::*m, Args&& ...args) { this->assert_mapped_type(); - - auto connection = this->get_or_create_connection(); - double res = 0; - std::stringstream ss; - ss << "SELECT " << static_cast(sqlite_orm::total(0)) << "("; - auto columnName = this->string_from_expression(m, false, false); - if(!columnName.empty()){ - ss << columnName << ") "; - auto tableNamesSet = this->parse_table_names(m); - if(!tableNamesSet.empty()){ - ss << "FROM " ; - std::vector> tableNames(tableNamesSet.begin(), tableNamesSet.end()); - for(size_t i = 0; i < tableNames.size(); ++i) { - ss << "'" << tableNames[i].first << "' "; - if(i < tableNames.size() - 1) { - ss << ","; - } - ss << " "; - } - } - this->process_conditions(ss, std::make_tuple(std::forward(args)...)); - auto query = ss.str(); - auto rc = sqlite3_exec(connection->get_db(), - query.c_str(), - [](void *data, int argc, char **argv, char **)->int{ - auto &res = *(double*)data; - if(argc){ - res = row_extractor().extract(argv[0]); - } - return 0; - }, &res, nullptr); - if(rc != SQLITE_OK) { - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); - } + auto rows = this->select(sqlite_orm::total(m), std::forward(args)...); + if(!rows.empty()){ + return std::move(rows.front()); }else{ - throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); + return {}; } - return res; } /** @@ -9191,25 +9045,11 @@ namespace sqlite_orm { if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; - using conditions_type = typename select_type::conditions_type; - - iterate_ast(sel.col, [stmt, &index](auto &node){ + iterate_ast(sel, [stmt, &index](auto &node){ using node_type = typename std::decay::type; conditional_binder> binder{stmt, index}; binder(node); }); - - tuple_helper::iterator::value - 1, Args...>()(sel.conditions, [stmt, &index](auto &v){ - using arg_type = typename std::decay::type; - std::cout << "v is " << typeid(arg_type).name() << std::endl; - - iterate_ast(v, [stmt, &index](auto &node){ - using node_type = typename std::decay::type; - conditional_binder> binder{stmt, index}; - binder(node); - }); - }); - std::vector res; int stepRes; do{ diff --git a/tests/tests.cpp b/tests/tests.cpp index 25d673b6d..13c193a1c 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -42,16 +42,15 @@ void testIterateBlob() { auto db = make_storage("", make_table("Test", make_column("key", &Test::key), - make_column("id", &Test::id, autoincrement(), primary_key()))); + make_column("id", &Test::id, primary_key()))); db.sync_schema(true); std::vector key(255); iota(key.begin(), key.end(), 0); - Test v; - v.key = key; + Test v{5, key}; - db.insert(v); + db.replace(v); for(auto &obj : db.iterate()){ cout << db.dump(obj) << endl; @@ -61,9 +60,19 @@ void testIterateBlob() { cout << db.dump(obj) << endl; } // test that view_t and iterator_t compile - /*for (auto& w : db.iterate(where(c(&Test::key) == key))) { + auto keysCount = db.count(where(c(&Test::key) == key)); + auto keysCountRows = db.select(count(), where(c(&Test::key) == key)); + assert(keysCountRows.size() == 1); + assert(keysCountRows.front() == 1); + assert(keysCount == keysCountRows.front()); + assert(db.get_all(where(c(&Test::key) == key)).size() == 1); + + int iterationsCount = 0; + for (auto& w : db.iterate(where(c(&Test::key) == key))) { cout << w.id << endl; - }*/ + ++iterationsCount; + } + assert(iterationsCount == 1); } void testCast() { @@ -2309,21 +2318,9 @@ void testAggregateFunctions() { storage.sync_schema(); storage.remove_all(); - storage.replace(User{ - 1, - "Bebe Rexha", - 28, - }); - storage.replace(User{ - 2, - "Rihanna", - 29, - }); - storage.replace(User{ - 3, - "Cheryl Cole", - 34, - }); + storage.replace(User{ 1, "Bebe Rexha", 28}); + storage.replace(User{ 2, "Rihanna", 29 }); + storage.replace(User{ 3, "Cheryl Cole", 34 }); auto avgId = storage.avg(&User::id); assert(avgId == 2); @@ -2346,11 +2343,54 @@ void testAggregateFunctions() { auto avgRaw2 = storage2.select(avg(&User::getId)).front(); assert(avgRaw2 == avgId); + auto avgRaw3 = storage2.select(avg(&User::setId)).front(); + assert(avgRaw3 == avgRaw2); + auto distinctAvg2 = storage2.select(distinct(avg(&User::setId))).front(); assert(distinctAvg2 == avgId); + auto distinctAvg3 = storage2.select(distinct(avg(&User::getId))).front(); + assert(distinctAvg3 == distinctAvg2); + auto allAvg2 = storage2.select(all(avg(&User::getId))).front(); assert(allAvg2 == avgId); + + auto allAvg3 = storage2.select(all(avg(&User::setId))).front(); + assert(allAvg3 == allAvg2); + + // next we test that all aggregate functions support arguments bindings. + // This is why id = 1 condition is important here + { + auto avg1 = storage.avg(&User::id, where(is_equal(&User::id, 1))); + assert(avg1 == 1); + } + { + auto count1 = storage.count(&User::id, where(is_equal(&User::id, 1))); + assert(count1 == 1); + } + { + auto max1 = storage.max(&User::id, where(is_equal(&User::id, 1))); + assert(max1); + assert(*max1 == 1); + } + { + auto min1 = storage.min(&User::id, where(is_equal(&User::id, 1))); + assert(min1); + assert(*min1 == 1); + } + { + auto total1 = storage.total(&User::id, where(is_equal(&User::id, 1))); + assert(total1 == 1); + } + { + auto sum1 = storage.sum(&User::id, where(is_equal(&User::id, 1))); + assert(sum1); + assert(*sum1 == 1); + } + { + auto groupConcat = storage.group_concat(&User::name, where(is_equal(&User::id, 1))); + assert(groupConcat == "Bebe Rexha"); + } } void testBusyTimeout() { @@ -2471,6 +2511,7 @@ void testWhere() { assert(users3.size() == 0); auto users4 = storage.get_all(where(true and c(&User::id) == 1)); +// cout << "users4.size() = " << users4.size() << endl; assert(users4.size() == 1); assert(users4.front().id == 1); @@ -2482,7 +2523,7 @@ int main(int, char **) { cout << "version = " << make_storage("").libversion() << endl; - /*testTypeParsing(); + testTypeParsing(); testSyncSchema(); @@ -2535,11 +2576,10 @@ int main(int, char **) { testIssue105(); testMultiOrderBy(); - */ testOperators(); - /*testAutoVacuum(); + testAutoVacuum(); testVacuum(); @@ -2571,5 +2611,5 @@ int main(int, char **) { testIterateBlob(); - testIsNull();*/ + testIsNull(); } From ae5a90f31c352dfd8d35d1287216424ddc387915 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sun, 2 Jun 2019 12:43:03 +0300 Subject: [PATCH 100/232] fixed count type in storage_t::count --- dev/storage.h | 13 ++++++++++--- include/sqlite_orm/sqlite_orm.h | 13 ++++++++++--- tests/tests.cpp | 26 ++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/dev/storage.h b/dev/storage.h index 8e89239a7..255f14ab2 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -1203,11 +1203,18 @@ namespace sqlite_orm { auto &impl = this->get_impl(); std::stringstream ss; ss << "DELETE FROM '" << impl.table.name << "' "; - this->process_conditions(ss, std::make_tuple(std::forward(args)...)); + auto argsTuple = std::make_tuple(std::forward(args)...); + this->process_conditions(ss, argsTuple); auto query = ss.str(); sqlite3_stmt *stmt; if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; + auto index = 1; + iterate_ast(argsTuple, [stmt, &index](auto &node){ + using node_type = typename std::decay::type; + conditional_binder> binder{stmt, index}; + binder(node); + }); if (sqlite3_step(stmt) == SQLITE_DONE) { // done.. }else{ @@ -1963,8 +1970,8 @@ namespace sqlite_orm { */ template::type> int count(Args&& ...args) { - this->assert_mapped_type(); - auto rows = this->select(sqlite_orm::count(), std::forward(args)...); + this->assert_mapped_type(); + auto rows = this->select(sqlite_orm::count(), std::forward(args)...); if(!rows.empty()){ return rows.front(); }else{ diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index d72dec023..e3ed39855 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -8118,11 +8118,18 @@ namespace sqlite_orm { auto &impl = this->get_impl(); std::stringstream ss; ss << "DELETE FROM '" << impl.table.name << "' "; - this->process_conditions(ss, std::make_tuple(std::forward(args)...)); + auto argsTuple = std::make_tuple(std::forward(args)...); + this->process_conditions(ss, argsTuple); auto query = ss.str(); sqlite3_stmt *stmt; if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; + auto index = 1; + iterate_ast(argsTuple, [stmt, &index](auto &node){ + using node_type = typename std::decay::type; + conditional_binder> binder{stmt, index}; + binder(node); + }); if (sqlite3_step(stmt) == SQLITE_DONE) { // done.. }else{ @@ -8878,8 +8885,8 @@ namespace sqlite_orm { */ template::type> int count(Args&& ...args) { - this->assert_mapped_type(); - auto rows = this->select(sqlite_orm::count(), std::forward(args)...); + this->assert_mapped_type(); + auto rows = this->select(sqlite_orm::count(), std::forward(args)...); if(!rows.empty()){ return rows.front(); }else{ diff --git a/tests/tests.cpp b/tests/tests.cpp index 13c193a1c..2b821414b 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -1721,6 +1721,30 @@ void testRemove() { } } +void testRemoveAll() { + cout << __func__ << endl; + + struct Object { + int id; + std::string name; + }; + + auto storage = make_storage("", + make_table("objects", + make_column("id", &Object::id, primary_key()), + make_column("name", &Object::name))); + storage.sync_schema(); + + storage.replace(Object{ 1, "Ototo" }); + storage.replace(Object{ 2, "Contigo" }); + + assert(storage.count() == 2); + + storage.remove_all(where(c(&Object::id) == 1)); + + assert(storage.count() == 1); +} + void testInsert() { cout << __func__ << endl; @@ -2612,4 +2636,6 @@ int main(int, char **) { testIterateBlob(); testIsNull(); + + testRemoveAll(); } From b751c067108a7402735d9e236e5a737bde1814a3 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sun, 2 Jun 2019 13:27:05 +0300 Subject: [PATCH 101/232] fixed having --- dev/ast_iterator.h | 12 +++++++++++- dev/storage.h | 4 ++-- include/sqlite_orm/sqlite_orm.h | 16 +++++++++++++--- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index 79b0136f7..eac1b1a6a 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -151,7 +151,17 @@ namespace sqlite_orm { void operator()(const node_type &tuple, const L &l) const { tuple_helper::iterator::value - 1, Args...>()(tuple, [&l](auto &v){ iterate_ast(v, l); - }); + }, false); + } + }; + + template + struct ast_iterator, void> { + using node_type = conditions::having_t; + + template + void operator()(const node_type &hav, const L &l) const { + iterate_ast(hav.t, l); } }; } diff --git a/dev/storage.h b/dev/storage.h index 255f14ab2..1540cc834 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -1108,7 +1108,7 @@ namespace sqlite_orm { using argsType = typename std::decay::type; tuple_helper::iterator::value - 1, Args...>()(args, [this, &ss](auto &v){ this->process_single_condition(ss, v); - }); + }, false); } void on_open_internal(sqlite3 *db) { @@ -1433,7 +1433,7 @@ namespace sqlite_orm { } } ss << "FROM '" << impl.table.name << "' "; - this->process_conditions(ss, move(args)); + this->process_conditions(ss, args); if(query){ *query = ss.str(); } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index e3ed39855..f620135e7 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -6899,7 +6899,17 @@ namespace sqlite_orm { void operator()(const node_type &tuple, const L &l) const { tuple_helper::iterator::value - 1, Args...>()(tuple, [&l](auto &v){ iterate_ast(v, l); - }); + }, false); + } + }; + + template + struct ast_iterator, void> { + using node_type = conditions::having_t; + + template + void operator()(const node_type &hav, const L &l) const { + iterate_ast(hav.t, l); } }; } @@ -8023,7 +8033,7 @@ namespace sqlite_orm { using argsType = typename std::decay::type; tuple_helper::iterator::value - 1, Args...>()(args, [this, &ss](auto &v){ this->process_single_condition(ss, v); - }); + }, false); } void on_open_internal(sqlite3 *db) { @@ -8348,7 +8358,7 @@ namespace sqlite_orm { } } ss << "FROM '" << impl.table.name << "' "; - this->process_conditions(ss, move(args)); + this->process_conditions(ss, args); if(query){ *query = ss.str(); } From 422160c69b774016d5e9df0216d0d4b8457f1b1e Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sun, 2 Jun 2019 23:36:20 +0300 Subject: [PATCH 102/232] fixed collate example --- dev/conditions.h | 2 ++ dev/constraints.h | 2 ++ dev/join_iterator.h | 50 +++++++++++++----------------- examples/collate.cpp | 28 +++-------------- include/sqlite_orm/sqlite_orm.h | 54 +++++++++++++++------------------ 5 files changed, 55 insertions(+), 81 deletions(-) diff --git a/dev/conditions.h b/dev/conditions.h index 6f81b05a9..ccadd80c9 100644 --- a/dev/conditions.h +++ b/dev/conditions.h @@ -399,6 +399,8 @@ namespace sqlite_orm { struct where_t { C c; + where_t() = default; + operator std::string () const { return "WHERE"; } diff --git a/dev/constraints.h b/dev/constraints.h index 10715d7f6..f5d4b6373 100644 --- a/dev/constraints.h +++ b/dev/constraints.h @@ -301,6 +301,8 @@ namespace sqlite_orm { struct collate_t { internal::collate_argument argument; + collate_t() : collate_t(internal::collate_argument::binary) {} + collate_t(internal::collate_argument argument_): argument(argument_) {} operator std::string() const { diff --git a/dev/join_iterator.h b/dev/join_iterator.h index afba92142..43428fb08 100644 --- a/dev/join_iterator.h +++ b/dev/join_iterator.h @@ -10,7 +10,7 @@ namespace sqlite_orm { struct join_iterator { template - void operator()(L) { + void operator()(const L &) { //.. } }; @@ -19,7 +19,7 @@ namespace sqlite_orm { struct join_iterator<> { template - void operator()(L) { + void operator()(const L &) { //.. } }; @@ -28,10 +28,8 @@ namespace sqlite_orm { struct join_iterator : public join_iterator{ using super = join_iterator; - H h; - template - void operator()(L l) { + void operator()(const L &l) { this->super::operator()(l); } @@ -40,12 +38,11 @@ namespace sqlite_orm { template struct join_iterator, Tail...> : public join_iterator{ using super = join_iterator; - - conditions::cross_join_t h; + using join_type = conditions::cross_join_t; template - void operator()(L l) { - l(h); + void operator()(const L &l) { + l(*this); this->super::operator()(l); } }; @@ -53,12 +50,11 @@ namespace sqlite_orm { template struct join_iterator, Tail...> : public join_iterator{ using super = join_iterator; - - conditions::natural_join_t h; + using join_type = conditions::natural_join_t; template - void operator()(L l) { - l(h); + void operator()(const L &l) { + l(*this); this->super::operator()(l); } }; @@ -66,12 +62,11 @@ namespace sqlite_orm { template struct join_iterator, Tail...> : public join_iterator { using super = join_iterator; - - conditions::left_join_t h; + using join_type = conditions::left_join_t; template - void operator()(L l) { - l(h); + void operator()(const L &l) { + l(*this); this->super::operator()(l); } }; @@ -79,12 +74,11 @@ namespace sqlite_orm { template struct join_iterator, Tail...> : public join_iterator { using super = join_iterator; - - conditions::join_t h; + using join_type = conditions::join_t; template - void operator()(L l) { - l(h); + void operator()(const L &l) { + l(*this); this->super::operator()(l); } }; @@ -92,12 +86,11 @@ namespace sqlite_orm { template struct join_iterator, Tail...> : public join_iterator { using super = join_iterator; - - conditions::left_outer_join_t h; + using join_type = conditions::left_outer_join_t; template - void operator()(L l) { - l(h); + void operator()(const L &l) { + l(*this); this->super::operator()(l); } }; @@ -105,12 +98,11 @@ namespace sqlite_orm { template struct join_iterator, Tail...> : public join_iterator { using super = join_iterator; - - conditions::inner_join_t h; + using join_type = conditions::inner_join_t; template - void operator()(L l) { - l(h); + void operator()(const L &l) { + l(*this); this->super::operator()(l); } }; diff --git a/examples/collate.cpp b/examples/collate.cpp index 87078ec13..ba02838fc 100644 --- a/examples/collate.cpp +++ b/examples/collate.cpp @@ -34,21 +34,9 @@ int main(int, char**) { storage.remove_all(); storage.remove_all(); - storage.insert(User{ - 0, - "Lil Kim", - time(nullptr), - }); - storage.insert(User{ - 0, - "lil kim", - time(nullptr), - }); - storage.insert(User{ - 0, - "Nicki Minaj", - time(nullptr), - }); + storage.insert(User{ 0, "Lil Kim", time(nullptr) }); + storage.insert(User{ 0, "lil kim", time(nullptr) }); + storage.insert(User{ 0, "Nicki Minaj", time(nullptr) }); // SELECT COUNT(*) FROM users WHERE name = 'lil kim' auto preciseLilKimsCount = storage.count(where(is_equal(&User::name, "lil kim"))); @@ -61,14 +49,8 @@ int main(int, char**) { // SELECT COUNT(*) FROM users cout << "total users count = " << storage.count() << endl; - storage.insert(Foo{ - "Touch", - 10, - }); - storage.insert(Foo{ - "touch", - 20, - }); + storage.insert(Foo{ "Touch", 10 }); + storage.insert(Foo{ "touch", 20 }); cout << "foo count = " << storage.count(where(c(&Foo::text) == "touch")) << endl; diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index f620135e7..a4638a8f7 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -721,6 +721,8 @@ namespace sqlite_orm { struct collate_t { internal::collate_argument argument; + collate_t() : collate_t(internal::collate_argument::binary) {} + collate_t(internal::collate_argument argument_): argument(argument_) {} operator std::string() const { @@ -1931,6 +1933,8 @@ namespace sqlite_orm { struct where_t { C c; + where_t() = default; + operator std::string () const { return "WHERE"; } @@ -2733,7 +2737,7 @@ namespace sqlite_orm { struct join_iterator { template - void operator()(L) { + void operator()(const L &) { //.. } }; @@ -2742,7 +2746,7 @@ namespace sqlite_orm { struct join_iterator<> { template - void operator()(L) { + void operator()(const L &) { //.. } }; @@ -2751,10 +2755,8 @@ namespace sqlite_orm { struct join_iterator : public join_iterator{ using super = join_iterator; - H h; - template - void operator()(L l) { + void operator()(const L &l) { this->super::operator()(l); } @@ -2763,12 +2765,11 @@ namespace sqlite_orm { template struct join_iterator, Tail...> : public join_iterator{ using super = join_iterator; - - conditions::cross_join_t h; + using join_type = conditions::cross_join_t; template - void operator()(L l) { - l(h); + void operator()(const L &l) { + l(*this); this->super::operator()(l); } }; @@ -2776,12 +2777,11 @@ namespace sqlite_orm { template struct join_iterator, Tail...> : public join_iterator{ using super = join_iterator; - - conditions::natural_join_t h; + using join_type = conditions::natural_join_t; template - void operator()(L l) { - l(h); + void operator()(const L &l) { + l(*this); this->super::operator()(l); } }; @@ -2789,12 +2789,11 @@ namespace sqlite_orm { template struct join_iterator, Tail...> : public join_iterator { using super = join_iterator; - - conditions::left_join_t h; + using join_type = conditions::left_join_t; template - void operator()(L l) { - l(h); + void operator()(const L &l) { + l(*this); this->super::operator()(l); } }; @@ -2802,12 +2801,11 @@ namespace sqlite_orm { template struct join_iterator, Tail...> : public join_iterator { using super = join_iterator; - - conditions::join_t h; + using join_type = conditions::join_t; template - void operator()(L l) { - l(h); + void operator()(const L &l) { + l(*this); this->super::operator()(l); } }; @@ -2815,12 +2813,11 @@ namespace sqlite_orm { template struct join_iterator, Tail...> : public join_iterator { using super = join_iterator; - - conditions::left_outer_join_t h; + using join_type = conditions::left_outer_join_t; template - void operator()(L l) { - l(h); + void operator()(const L &l) { + l(*this); this->super::operator()(l); } }; @@ -2828,12 +2825,11 @@ namespace sqlite_orm { template struct join_iterator, Tail...> : public join_iterator { using super = join_iterator; - - conditions::inner_join_t h; + using join_type = conditions::inner_join_t; template - void operator()(L l) { - l(h); + void operator()(const L &l) { + l(*this); this->super::operator()(l); } }; From 348ad1a9cea4decc44a7b3b96af34260aa5f0568 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Mon, 3 Jun 2019 00:16:32 +0300 Subject: [PATCH 103/232] fixed join iteration --- dev/storage.h | 2 +- include/sqlite_orm/sqlite_orm.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/storage.h b/dev/storage.h index 1540cc834..fb1d420cb 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -796,7 +796,7 @@ namespace sqlite_orm { } auto tableNamesSet = this->parse_table_names(sel.col); internal::join_iterator()([&tableNamesSet, this](const auto &c){ - using original_join_type = typename std::decay::type::type; + using original_join_type = typename std::decay::type::join_type::type; using cross_join_type = typename internal::mapped_type_proxy::type; auto crossJoinedTableName = this->impl.template find_table_name(); auto tableAliasString = alias_extractor::get(); diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index a4638a8f7..ad2f267d0 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -7717,7 +7717,7 @@ namespace sqlite_orm { } auto tableNamesSet = this->parse_table_names(sel.col); internal::join_iterator()([&tableNamesSet, this](const auto &c){ - using original_join_type = typename std::decay::type::type; + using original_join_type = typename std::decay::type::join_type::type; using cross_join_type = typename internal::mapped_type_proxy::type; auto crossJoinedTableName = this->impl.template find_table_name(); auto tableAliasString = alias_extractor::get(); From a480fd131b7209f1a2d486516aa6e857d4fa6bd9 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Mon, 3 Jun 2019 18:03:51 +0300 Subject: [PATCH 104/232] fixed other conditions and added unit tests for them --- dev/ast_iterator.h | 43 ++++++++++++++ dev/storage.h | 2 +- include/sqlite_orm/sqlite_orm.h | 45 ++++++++++++++- tests/tests.cpp | 99 +++++++++++++++++++++++++++++++++ 4 files changed, 187 insertions(+), 2 deletions(-) diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index eac1b1a6a..711caccb3 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -164,5 +164,48 @@ namespace sqlite_orm { iterate_ast(hav.t, l); } }; + + template + struct ast_iterator, void> { + using node_type = conditions::cast_t; + + template + void operator()(const node_type &c, const L &l) const { + iterate_ast(c.expression, l); + } + }; + + template + struct ast_iterator, void> { + using node_type = conditions::exists_t; + + template + void operator()(const node_type &e, const L &l) const { + iterate_ast(e.t, l); + } + }; + + /*template + struct ast_iterator, void> { + using node_type = conditions::like_t; + + template + void operator()(const node_type &lk, const L &l) const { + iterate_ast(lk.a, l); + iterate_ast(lk.t, l); + } + };*/ + + template + struct ast_iterator, void> { + using node_type = conditions::between_t; + + template + void operator()(const node_type &b, const L &l) const { + iterate_ast(b.expr, l); + iterate_ast(b.b1, l); + iterate_ast(b.b2, l); + } + }; } } diff --git a/dev/storage.h b/dev/storage.h index fb1d420cb..368d78c0a 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -949,7 +949,7 @@ namespace sqlite_orm { std::string process_where(const conditions::between_t &bw) { std::stringstream ss; auto expr = this->string_from_expression(bw.expr, false, false, true); - ss << expr << " " << static_cast(bw) << " " << this->string_from_expression(bw.b1, false, false, true) << " AND " << this->string_from_expression(bw.b2, false, false) << " "; + ss << expr << " " << static_cast(bw) << " " << this->string_from_expression(bw.b1, false, false, true) << " AND " << this->string_from_expression(bw.b2, false, false, true) << " "; return ss.str(); } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index ad2f267d0..4afde2d03 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -6908,6 +6908,49 @@ namespace sqlite_orm { iterate_ast(hav.t, l); } }; + + template + struct ast_iterator, void> { + using node_type = conditions::cast_t; + + template + void operator()(const node_type &c, const L &l) const { + iterate_ast(c.expression, l); + } + }; + + template + struct ast_iterator, void> { + using node_type = conditions::exists_t; + + template + void operator()(const node_type &e, const L &l) const { + iterate_ast(e.t, l); + } + }; + + /*template + struct ast_iterator, void> { + using node_type = conditions::like_t; + + template + void operator()(const node_type &lk, const L &l) const { + iterate_ast(lk.a, l); + iterate_ast(lk.t, l); + } + };*/ + + template + struct ast_iterator, void> { + using node_type = conditions::between_t; + + template + void operator()(const node_type &b, const L &l) const { + iterate_ast(b.expr, l); + iterate_ast(b.b1, l); + iterate_ast(b.b2, l); + } + }; } } @@ -7870,7 +7913,7 @@ namespace sqlite_orm { std::string process_where(const conditions::between_t &bw) { std::stringstream ss; auto expr = this->string_from_expression(bw.expr, false, false, true); - ss << expr << " " << static_cast(bw) << " " << this->string_from_expression(bw.b1, false, false, true) << " AND " << this->string_from_expression(bw.b2, false, false) << " "; + ss << expr << " " << static_cast(bw) << " " << this->string_from_expression(bw.b1, false, false, true) << " AND " << this->string_from_expression(bw.b2, false, false, true) << " "; return ss.str(); } diff --git a/tests/tests.cpp b/tests/tests.cpp index 2b821414b..23fd0df38 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -13,6 +13,93 @@ using namespace sqlite_orm; using std::cout; using std::endl; +void testBetween() { + cout << __func__ << endl; + + struct Object { + int id = 0; + }; + + auto storage = make_storage("", + make_table("objects", + make_column("id", &Object::id, autoincrement(), primary_key()))); + storage.sync_schema(); + + storage.insert(Object{}); + storage.insert(Object{}); + storage.insert(Object{}); + storage.insert(Object{}); + storage.insert(Object{}); + + auto allObjects = storage.get_all(); + auto rows = storage.select(&Object::id, where(between(&Object::id, 1, 3))); + assert(rows.size() == 3); +} + +void testLike() { + cout << __func__ << endl; + + struct User { + int id = 0; + std::string name; + }; + + auto storage = make_storage("", + make_table("users", + make_column("id", &User::id, autoincrement(), primary_key()), + make_column("name", &User::name))); + storage.sync_schema(); + + storage.insert(User{0, "Sia"}); + storage.insert(User{0, "Stark"}); + storage.insert(User{0, "Index"}); + + auto whereCondition = where(like(&User::name, "S%")); + auto users = storage.get_all(whereCondition); + assert(users.size() == 2); + + auto rows = storage.select(&User::id, whereCondition); + assert(rows.size() == 2); +} + +void testExists() { + cout << __func__ << endl; + struct User { + int id = 0; + std::string name; + }; + + struct Visit { + int id = 0; + int userId = 0; + time_t time = 0; + }; + + auto storage = make_storage("", + make_table("users", + make_column("id", &User::id, primary_key()), + make_column("name", &User::name)), + make_table("visits", + make_column("id", &Visit::id, primary_key()), + make_column("userId", &Visit::userId), + make_column("time", &Visit::time), + foreign_key(&Visit::userId).references(&User::id))); + storage.sync_schema(); + + storage.replace(User{1, "Daddy Yankee"}); + storage.replace(User{2, "Don Omar"}); + + storage.replace(Visit{1, 1, 100000}); + storage.replace(Visit{2, 1, 100001}); + storage.replace(Visit{3, 1, 100002}); + storage.replace(Visit{4, 1, 200000}); + + storage.replace(Visit{5, 2, 100000}); + + auto rows = storage.select(&User::id, where(exists(select(&Visit::id, where(c(&Visit::time) == 200000 and eq(&Visit::userId, &User::id)))))); + assert(!rows.empty() == 1); +} + void testIsNull() { struct User { int id = 0; @@ -100,6 +187,12 @@ void testCast() { assert(std::get<0>(row) == 10); assert(std::get<1>(row) == 14); } + { + auto rows = storage.select(cast(5)); + assert(rows.size() == 1); + auto &row = rows.front(); + assert(row == "5"); + } } void testSimpleQuery() { @@ -2638,4 +2731,10 @@ int main(int, char **) { testIsNull(); testRemoveAll(); + + testExists(); + + testLike(); + + testBetween(); } From 2e1cb5920ebbfc3f729f2cb44b5bd29e172ae252 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Mon, 3 Jun 2019 23:41:49 +0300 Subject: [PATCH 105/232] fixed like and added negated_condition specialization of ast_iterator --- dev/ast_iterator.h | 24 ++++++++++++++++++++++-- dev/storage.h | 4 ++-- include/sqlite_orm/sqlite_orm.h | 28 ++++++++++++++++++++++++---- tests/tests.cpp | 28 +++++++++++++++++++++++----- 4 files changed, 71 insertions(+), 13 deletions(-) diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index 711caccb3..ddddac5f0 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -185,7 +185,7 @@ namespace sqlite_orm { } }; - /*template + template struct ast_iterator, void> { using node_type = conditions::like_t; @@ -194,7 +194,7 @@ namespace sqlite_orm { iterate_ast(lk.a, l); iterate_ast(lk.t, l); } - };*/ + }; template struct ast_iterator, void> { @@ -207,5 +207,25 @@ namespace sqlite_orm { iterate_ast(b.b2, l); } }; + + template + struct ast_iterator, void> { + using node_type = conditions::named_collate; + + template + void operator()(const node_type &col, const L &l) const { + iterate_ast(col.expr, l); + } + }; + + template + struct ast_iterator, void> { + using node_type = conditions::negated_condition_t; + + template + void operator()(const node_type &neg, const L &l) const { + iterate_ast(neg.c, l); + } + }; } } diff --git a/dev/storage.h b/dev/storage.h index 368d78c0a..6c0f8412e 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -360,7 +360,7 @@ namespace sqlite_orm { std::string string_from_expression(const char *t, bool /*noTableName*/, bool escape, bool ignoreBindable = false) { std::stringstream ss; - if(ignoreBindable){ + if(!ignoreBindable){ std::string text = t; if(escape){ text = this->escape(text); @@ -1360,7 +1360,7 @@ namespace sqlite_orm { std::vector setPairs; set.for_each([this, &setPairs](auto &asgn){ std::stringstream sss; - sss << this->string_from_expression(asgn.l, true, false) << " = " << this->string_from_expression(asgn.r, false, false) << " "; + sss << this->string_from_expression(asgn.l, true, false, true) << " = " << this->string_from_expression(asgn.r, false, false, true) << " "; setPairs.push_back(sss.str()); }); auto setPairsCount = setPairs.size(); diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 4afde2d03..dccbb84af 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -6929,7 +6929,7 @@ namespace sqlite_orm { } }; - /*template + template struct ast_iterator, void> { using node_type = conditions::like_t; @@ -6938,7 +6938,7 @@ namespace sqlite_orm { iterate_ast(lk.a, l); iterate_ast(lk.t, l); } - };*/ + }; template struct ast_iterator, void> { @@ -6951,6 +6951,26 @@ namespace sqlite_orm { iterate_ast(b.b2, l); } }; + + template + struct ast_iterator, void> { + using node_type = conditions::named_collate; + + template + void operator()(const node_type &col, const L &l) const { + iterate_ast(col.expr, l); + } + }; + + template + struct ast_iterator, void> { + using node_type = conditions::negated_condition_t; + + template + void operator()(const node_type &neg, const L &l) const { + iterate_ast(neg.c, l); + } + }; } } @@ -7324,7 +7344,7 @@ namespace sqlite_orm { std::string string_from_expression(const char *t, bool /*noTableName*/, bool escape, bool ignoreBindable = false) { std::stringstream ss; - if(ignoreBindable){ + if(!ignoreBindable){ std::string text = t; if(escape){ text = this->escape(text); @@ -8324,7 +8344,7 @@ namespace sqlite_orm { std::vector setPairs; set.for_each([this, &setPairs](auto &asgn){ std::stringstream sss; - sss << this->string_from_expression(asgn.l, true, false) << " = " << this->string_from_expression(asgn.r, false, false) << " "; + sss << this->string_from_expression(asgn.l, true, false, true) << " = " << this->string_from_expression(asgn.r, false, false, true) << " "; setPairs.push_back(sss.str()); }); auto setPairsCount = setPairs.size(); diff --git a/tests/tests.cpp b/tests/tests.cpp index 23fd0df38..624be3a4f 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -13,6 +13,25 @@ using namespace sqlite_orm; using std::cout; using std::endl; +void testNot() { + cout << __func__ << endl; + + struct Object { + int id = 0; + }; + + auto storage = make_storage("", + make_table("objects", + make_column("id", &Object::id, primary_key()))); + storage.sync_schema(); + + storage.replace(Object{2}); + + auto rows = storage.select(&Object::id, where(not is_equal(&Object::id, 1))); + assert(rows.size() == 1); + assert(rows.front() == 2); +} + void testBetween() { cout << __func__ << endl; @@ -882,11 +901,8 @@ void testCustomCollate() { auto storage = make_storage("custom_collate.sqlite", make_table("items", - make_column("id", - &Item::id, - primary_key()), - make_column("name", - &Item::name))); + make_column("id", &Item::id, primary_key()), + make_column("name", &Item::name))); // storage.open_forever(); storage.sync_schema(); storage.remove_all(); @@ -2737,4 +2753,6 @@ int main(int, char **) { testLike(); testBetween(); + + testNot(); } From a833f52131a2b38051ff8a444688622872674082 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Mon, 3 Jun 2019 23:52:25 +0300 Subject: [PATCH 106/232] removed unused code --- dev/tuple_helper.h | 20 -------------------- include/sqlite_orm/sqlite_orm.h | 20 -------------------- tests/tests.cpp | 1 - 3 files changed, 41 deletions(-) diff --git a/dev/tuple_helper.h b/dev/tuple_helper.h index e0b3e4dee..a4a947935 100644 --- a/dev/tuple_helper.h +++ b/dev/tuple_helper.h @@ -67,25 +67,5 @@ namespace sqlite_orm { void tuple_for_each(const std::tuple& t, F&& f){ tuple_for_each_impl(std::forward(f), t, std::index_sequence_for{}); } - - // got it from here https://stackoverflow.com/questions/10626856/how-to-split-a-tuple - - template - auto head(std::tuple t) - { - return std::get<0>(t); - } - - template - auto tail_impl(std::index_sequence , std::tuple t) - { - return std::make_tuple(std::get(t)...); - } - - template - auto tail(std::tuple t) - { - return tail_impl(std::make_index_sequence() , t); - } } } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index dccbb84af..368bb10fe 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -256,26 +256,6 @@ namespace sqlite_orm { void tuple_for_each(const std::tuple& t, F&& f){ tuple_for_each_impl(std::forward(f), t, std::index_sequence_for{}); } - - // got it from here https://stackoverflow.com/questions/10626856/how-to-split-a-tuple - - template - auto head(std::tuple t) - { - return std::get<0>(t); - } - - template - auto tail_impl(std::index_sequence , std::tuple t) - { - return std::make_tuple(std::get(t)...); - } - - template - auto tail(std::tuple t) - { - return tail_impl(std::make_index_sequence() , t); - } } } #pragma once diff --git a/tests/tests.cpp b/tests/tests.cpp index 624be3a4f..f3739d3b4 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -2644,7 +2644,6 @@ void testWhere() { assert(users3.size() == 0); auto users4 = storage.get_all(where(true and c(&User::id) == 1)); -// cout << "users4.size() = " << users4.size() << endl; assert(users4.size() == 1); assert(users4.front().id == 1); From d005f516fff1b828030b372eec16a6e5dffc17d4 Mon Sep 17 00:00:00 2001 From: Yevgeniy Zakharov Date: Wed, 5 Jun 2019 12:19:00 +0300 Subject: [PATCH 107/232] Update README.md --- README.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 258f0c8e3..4af8ee605 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ SQLite ORM light header only library for modern C++ * **COLLATE support** * **Limits setting/getting support** -`sqlite_orm` library allows to create easy data model mappings to your database schema. It is built to manage (CRUD) objects with a single column with primary key and without it. It also allows you to specify table names and column names explicitly no matter how your classes actually named. Take a look at example: +`sqlite_orm` library allows to create easy data model mappings to your database schema. It is built to manage (CRUD) objects with a primary key and without it. It also allows you to specify table names and column names explicitly no matter how your classes actually named. Take a look at example: ```c++ @@ -72,7 +72,7 @@ So we have database with predefined schema like `CREATE TABLE user_types (id integer primary key autoincrement, name text not null DEFAULT 'name_placeholder')` -Now we tell `sqlite_orm` library about schema and provide database filename. We create `storage` service object that has CRUD interface. Also we create every table and every column. All code is intuitive and minimalistic. +Now we tell `sqlite_orm` library about our schema and provide database filename. We create `storage` service object that has CRUD interface. Also we create every table and every column. All code is intuitive and minimalistic. ```c++ @@ -90,15 +90,15 @@ auto storage = make_storage("db.sqlite", make_column("name", &UserType::name, default_value("name_placeholder")))); ``` -Too easy isn't it? You do not have to specify mapped type explicitly - it is deduced from your member pointers you pass during making a column (for example: `&User::id`). To create a column you have to pass two arguments at least: its name in the table and your mapped class member pointer. You can also add extra arguments to tell your storage about column's constraints like ~~`not_null`~~ (deduced from type), `primary_key`, `autoincrement`, `default_value` or `unique`(order isn't important). - -If your datamodel classes have private or protected members to map to sqlite then you can make a storage with setter and getter functions. More info in the [example](https://github.com/fnc12/sqlite_orm/blob/master/examples/private_class_members.cpp). +Too easy isn't it? You do not have to specify mapped type explicitly - it is deduced from your member pointers you pass during making a column (for example: `&User::id`). To create a column you have to pass two arguments at least: its name in the table and your mapped class member pointer. You can also add extra arguments to tell your storage about column's constraints like `primary_key`, `autoincrement`, `default_value` or `unique`(order isn't important; `not_null` is deduced from type automatically). More details about making storage can be found in [tutorial](https://github.com/fnc12/sqlite_orm/wiki/Making-storage). +If your datamodel classes have private or protected members to map to sqlite then you can make a storage with setter and getter functions. More info in the [example](https://github.com/fnc12/sqlite_orm/blob/master/examples/private_class_members.cpp). + # CRUD -Let's create and insert new `User` into database. First we need to create a `User` object with any id and call `insert` function. It will return id of just created user or throw exception if something goes wrong. +Let's create and insert new `User` into our database. First we need to create a `User` object with any id and call `insert` function. It will return id of just created user or throw exception if something goes wrong. ```c++ User user{-1, "Jonh", "Doe", 664416000, std::make_unique("url_to_heaven"), 3 }; @@ -113,6 +113,8 @@ secondUser.id = insertedId; ``` +Note: if we need to insert new user with specified id call `storage.replace(user);` instead of `insert`. + Next let's get our user by id. ```c++ @@ -377,7 +379,7 @@ for(auto &user : whereNameLike) { } ``` -Looks like magic but it works very simple. Cute function `c` (column) takes a class pointer and returns a special expression middle object that can be used with operators overloaded in `::sqlite_orm` namespace. Operator overloads act just like functions +Looks like magic but it works very simple. Cute function `c` (column) takes a class member pointer and returns a special expression middle object that can be used with operators overloaded in `::sqlite_orm` namespace. Operator overloads act just like functions * is_equal * is_not_equal @@ -388,7 +390,7 @@ Looks like magic but it works very simple. Cute function `c` (column) takes a cl * is_null * is_not_null -that simulate binary comparison operator so they take 2 arguments: left hand side and right hand side. Arguments may be either member pointer of mapped class or any other expression (core function or literal). Binary comparison functions map arguments to text to be passed to sqlite engine to process query. Member pointers are being mapped to column names and literals to literals (numbers to raw numbers and string to quoted strings). Next `where` function places brackets around condition and adds "WHERE" keyword before condition text. Next resulted string appends to query string and is being processed further. +that simulate binary comparison operator so they take 2 arguments: left hand side and right hand side. Arguments may be either member pointer of mapped class or any other expression (core/aggregate function, literal or subexpression). Binary comparison functions map arguments to text to be passed to sqlite engine to process query. Member pointers are being mapped to column names and literals/variables/constants to '?' and then are bound automatically. Next `where` function places brackets around condition and adds "WHERE" keyword before condition text. Next resulted string appends to a query string and is being processed further. If you omit `where` function in `get_all` it will return all objects from a table: @@ -672,7 +674,7 @@ storage.transaction([&] () mutable { It will print a number of deleted users (rows). But if you call `changes` without a transaction and your database is located in file not in RAM the result will be 0 always cause `sqlite_orm` opens and closes connection every time you call a function without a transaction. -Also a `transaction` function returns `true` if transaction is commited and `false` if it is rollbacked. It can be useful if your next moves depend on transaction result: +Also a `transaction` function returns `true` if transaction is commited and `false` if it is rollbacked. It can be useful if your next actions depend on transaction result: ```c++ auto commited = storage.transaction([&] () mutable { From 8fe4466c3aa59ea833e42ce87076d967dee1827e Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 13 Jun 2019 20:34:28 +0300 Subject: [PATCH 108/232] refactored columnt_t to a simple tuple --- dev/ast_iterator.h | 5 +-- dev/select_constraints.h | 33 +++--------------- dev/storage.h | 23 +++++++------ include/sqlite_orm/sqlite_orm.h | 61 ++++++++++++--------------------- 4 files changed, 42 insertions(+), 80 deletions(-) diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index ddddac5f0..75d4a9810 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -82,9 +82,10 @@ namespace sqlite_orm { template void operator()(const node_type &cols, const L &l) const { - cols.for_each([&l](auto &col){ + using columns_tuple = typename std::decay::type::columns_type; + tuple_helper::iterator::value - 1, Args...>()(cols.columns, [&l](auto &col){ iterate_ast(col, l); - }); + }, false); } }; diff --git a/dev/select_constraints.h b/dev/select_constraints.h index aec4583d2..779c2be7d 100644 --- a/dev/select_constraints.h +++ b/dev/select_constraints.h @@ -63,35 +63,12 @@ namespace sqlite_orm { template struct columns_t { - bool distinct = false; - - template - void for_each(L) const { - //.. - } - - int count() const { - return 0; - } - }; - - template - struct columns_t : public columns_t { - T m; + using columns_type = std::tuple; - columns_t(decltype(m) m_, Args&& ...args): super(std::forward(args)...), m(m_) {} - - template - void for_each(L l) const { - l(this->m); - this->super::for_each(l); - } + columns_type columns; + bool distinct = false; - int count() const { - return 1 + this->super::count(); - } - private: - using super = columns_t; + static constexpr const int count = std::tuple_size::value; }; template @@ -270,7 +247,7 @@ namespace sqlite_orm { template internal::columns_t columns(Args&& ...args) { - return {std::forward(args)...}; + return {std::make_tuple(std::forward(args)...)}; } /** diff --git a/dev/storage.h b/dev/storage.h index 6c0f8412e..055016d29 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -759,15 +759,16 @@ namespace sqlite_orm { template std::vector get_column_names(const internal::columns_t &cols) { std::vector columnNames; - columnNames.reserve(static_cast(cols.count())); - cols.for_each([&columnNames, this](auto &m) { + columnNames.reserve(static_cast(cols.count)); + using columns_tuple = typename std::decay::type::columns_type; + tuple_helper::iterator::value - 1, Args...>()(cols.columns, [&columnNames, this](auto &m){ auto columnName = this->string_from_expression(m, false, false, true); if(columnName.length()){ columnNames.push_back(columnName); }else{ throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); } - }); + }, false); return columnNames; } @@ -1716,10 +1717,11 @@ namespace sqlite_orm { template std::set> parse_table_names(const internal::columns_t &cols) { std::set> res; - cols.for_each([&res, this](auto &m){ + using columns_tuple = typename std::decay::type::columns_type; + tuple_helper::iterator::value - 1, Args...>()(cols.columns, [&res, this](auto &m){ auto tableName = this->parse_table_name(m); res.insert(tableName.begin(), tableName.end()); - }); + }, false); return res; } @@ -2315,14 +2317,15 @@ namespace sqlite_orm { ss << "INSERT INTO '" << impl.table.name << "' "; std::vector columnNames; columnNames.reserve(colsCount); - cols.for_each([&columnNames, this](auto &m) { + using columns_tuple = typename std::decay::type::columns_type; + tuple_helper::iterator::value - 1, Cols...>()(cols.columns, [&columnNames, this](auto &m){ auto columnName = this->string_from_expression(m, true, false); - if(columnName.length()){ + if(!columnName.empty()){ columnNames.push_back(columnName); }else{ throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); } - }); + }, false); ss << "("; for(size_t i = 0; i < columnNames.size(); ++i){ ss << columnNames[i]; @@ -2348,12 +2351,12 @@ namespace sqlite_orm { if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; - cols.for_each([&o, &index, &stmt, &impl] (auto &m) { + tuple_helper::iterator::value - 1, Cols...>()(cols.columns, [&o, &index, &stmt, &impl] (auto &m) { using column_type = typename std::decay::type; using field_type = typename column_result_t::type; const field_type *value = impl.table.template get_object_field_pointer(o, m); statement_binder().bind(stmt, index++, *value); - }); + }, false); if (sqlite3_step(stmt) == SQLITE_DONE) { return int(sqlite3_last_insert_rowid(connection->get_db())); }else{ diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 368bb10fe..c8e1a8fb2 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -3508,35 +3508,12 @@ namespace sqlite_orm { template struct columns_t { - bool distinct = false; - - template - void for_each(L) const { - //.. - } + using columns_type = std::tuple; - int count() const { - return 0; - } - }; - - template - struct columns_t : public columns_t { - T m; - - columns_t(decltype(m) m_, Args&& ...args): super(std::forward(args)...), m(m_) {} - - template - void for_each(L l) const { - l(this->m); - this->super::for_each(l); - } + columns_type columns; + bool distinct = false; - int count() const { - return 1 + this->super::count(); - } - private: - using super = columns_t; + static constexpr const int count = std::tuple_size::value; }; template @@ -3715,7 +3692,7 @@ namespace sqlite_orm { template internal::columns_t columns(Args&& ...args) { - return {std::forward(args)...}; + return {std::make_tuple(std::forward(args)...)}; } /** @@ -6806,9 +6783,10 @@ namespace sqlite_orm { template void operator()(const node_type &cols, const L &l) const { - cols.for_each([&l](auto &col){ + using columns_tuple = typename std::decay::type::columns_type; + tuple_helper::iterator::value - 1, Args...>()(cols.columns, [&l](auto &col){ iterate_ast(col, l); - }); + }, false); } }; @@ -7723,15 +7701,16 @@ namespace sqlite_orm { template std::vector get_column_names(const internal::columns_t &cols) { std::vector columnNames; - columnNames.reserve(static_cast(cols.count())); - cols.for_each([&columnNames, this](auto &m) { + columnNames.reserve(static_cast(cols.count)); + using columns_tuple = typename std::decay::type::columns_type; + tuple_helper::iterator::value - 1, Args...>()(cols.columns, [&columnNames, this](auto &m){ auto columnName = this->string_from_expression(m, false, false, true); if(columnName.length()){ columnNames.push_back(columnName); }else{ throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); } - }); + }, false); return columnNames; } @@ -8680,10 +8659,11 @@ namespace sqlite_orm { template std::set> parse_table_names(const internal::columns_t &cols) { std::set> res; - cols.for_each([&res, this](auto &m){ + using columns_tuple = typename std::decay::type::columns_type; + tuple_helper::iterator::value - 1, Args...>()(cols.columns, [&res, this](auto &m){ auto tableName = this->parse_table_name(m); res.insert(tableName.begin(), tableName.end()); - }); + }, false); return res; } @@ -9279,14 +9259,15 @@ namespace sqlite_orm { ss << "INSERT INTO '" << impl.table.name << "' "; std::vector columnNames; columnNames.reserve(colsCount); - cols.for_each([&columnNames, this](auto &m) { + using columns_tuple = typename std::decay::type::columns_type; + tuple_helper::iterator::value - 1, Cols...>()(cols.columns, [&columnNames, this](auto &m){ auto columnName = this->string_from_expression(m, true, false); - if(columnName.length()){ + if(!columnName.empty()){ columnNames.push_back(columnName); }else{ throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); } - }); + }, false); ss << "("; for(size_t i = 0; i < columnNames.size(); ++i){ ss << columnNames[i]; @@ -9312,12 +9293,12 @@ namespace sqlite_orm { if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; - cols.for_each([&o, &index, &stmt, &impl] (auto &m) { + tuple_helper::iterator::value - 1, Cols...>()(cols.columns, [&o, &index, &stmt, &impl] (auto &m) { using column_type = typename std::decay::type; using field_type = typename column_result_t::type; const field_type *value = impl.table.template get_object_field_pointer(o, m); statement_binder().bind(stmt, index++, *value); - }); + }, false); if (sqlite3_step(stmt) == SQLITE_DONE) { return int(sqlite3_last_insert_rowid(connection->get_db())); }else{ From 2605aaf04fdad5cb856be157917af1fca7ccb831 Mon Sep 17 00:00:00 2001 From: Yevgeniy Zakharov Date: Fri, 14 Jun 2019 08:37:04 +0300 Subject: [PATCH 109/232] Update TODO.md --- TODO.md | 1 - 1 file changed, 1 deletion(-) diff --git a/TODO.md b/TODO.md index cc57a0d47..bcd1f170c 100644 --- a/TODO.md +++ b/TODO.md @@ -5,7 +5,6 @@ * `FOREIGN KEY` - sync_schema fk comparison and ability of two tables to have fk to each other * rest of core functions(https://sqlite.org/lang_corefunc.html) * `CASE` -* asterisk in raw select: `SELECT rowid, * FROM table` * `ATTACH` * blob incremental I/O https://sqlite.org/c3ref/blob_open.html * reusing of prepared statements - useful for query optimisation From ef5481c5a82518f0b6951d137550ce580083e8a7 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sun, 16 Jun 2019 15:15:08 +0300 Subject: [PATCH 110/232] refactored default value --- dev/column.h | 2 +- dev/tuple_helper.h | 4 ++++ include/sqlite_orm/sqlite_orm.h | 6 +++++- tests/tests.cpp | 10 ++++++++-- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/dev/column.h b/dev/column.h index 6921a209e..a4beb7e9f 100644 --- a/dev/column.h +++ b/dev/column.h @@ -94,7 +94,7 @@ namespace sqlite_orm { */ std::unique_ptr default_value() { std::unique_ptr res; - tuple_helper::iterator::value - 1, Op...>()(constraints, [&res](auto &v){ + tuple_helper::tuple_for_each(constraints, [&res](auto &v){ auto dft = internal::default_value_extractor()(v); if(dft){ res = std::move(dft); diff --git a/dev/tuple_helper.h b/dev/tuple_helper.h index a4a947935..b9ef2b4f7 100644 --- a/dev/tuple_helper.h +++ b/dev/tuple_helper.h @@ -68,4 +68,8 @@ namespace sqlite_orm { tuple_for_each_impl(std::forward(f), t, std::index_sequence_for{}); } } + + namespace internal { + + } } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index c8e1a8fb2..71aef5ea0 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -257,6 +257,10 @@ namespace sqlite_orm { tuple_for_each_impl(std::forward(f), t, std::index_sequence_for{}); } } + + namespace internal { + + } } #pragma once @@ -1188,7 +1192,7 @@ namespace sqlite_orm { */ std::unique_ptr default_value() { std::unique_ptr res; - tuple_helper::iterator::value - 1, Op...>()(constraints, [&res](auto &v){ + tuple_helper::tuple_for_each(constraints, [&res](auto &v){ auto dft = internal::default_value_extractor()(v); if(dft){ res = std::move(dft); diff --git a/tests/tests.cpp b/tests/tests.cpp index f3739d3b4..634947bf3 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -2268,15 +2268,21 @@ void testDefaultValue() { make_column("Age", &User::age))); storage1.sync_schema(); storage1.remove_all(); - + + auto emailColumn = make_column("Email", &User::email, default_value("example@email.com")); + auto storage2 = make_storage("test_db.sqlite", make_table("User", make_column("Id", &User::userId, primary_key()), make_column("Name", &User::name), make_column("Age", &User::age), - make_column("Email", &User::email, default_value("example@email.com")))); + emailColumn)); storage2.sync_schema(); storage2.insert(User{0, "Tom", 15, ""}); + + auto emailDefault = emailColumn.default_value(); + assert(emailDefault); + assert(*emailDefault == "example@email.com"); } // after #18 From 32b5d6b7fd1e13c54cc82a9d9481b7432b25d52a Mon Sep 17 00:00:00 2001 From: fnc12 Date: Mon, 17 Jun 2019 10:09:43 +0300 Subject: [PATCH 111/232] added iterate_tuple function --- dev/column.h | 2 +- dev/storage.h | 15 +++++---- dev/table.h | 6 ++-- dev/tuple_helper.h | 16 +++------ include/sqlite_orm/sqlite_orm.h | 32 ++++++++++-------- tests/tests.cpp | 57 +++++++++++++++++++++++++++++++-- 6 files changed, 90 insertions(+), 38 deletions(-) diff --git a/dev/column.h b/dev/column.h index a4beb7e9f..c9468b38a 100644 --- a/dev/column.h +++ b/dev/column.h @@ -94,7 +94,7 @@ namespace sqlite_orm { */ std::unique_ptr default_value() { std::unique_ptr res; - tuple_helper::tuple_for_each(constraints, [&res](auto &v){ + iterate_tuple(constraints, [&res](auto &v){ auto dft = internal::default_value_extractor()(v); if(dft){ res = std::move(dft); diff --git a/dev/storage.h b/dev/storage.h index 055016d29..96e47ba36 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -149,7 +149,7 @@ namespace sqlite_orm { columnNames.reserve(std::tuple_size::value); tuple_helper::iterator::value - 1, Cs...>()(fk.columns, [&columnNames, this](auto &c){ columnNames.push_back(this->impl.column_name(c)); - }); + }, false); for(size_t i = 0; i < columnNames.size(); ++i) { ss << columnNames[i]; if(i < columnNames.size() - 1) { @@ -219,7 +219,7 @@ namespace sqlite_orm { ss << "CREATE TABLE '" << tableName << "' ( "; auto columnsCount = impl->table.columns_count; auto index = 0; - impl->table.for_each_column_with_constraints([columnsCount, &index, &ss, this] (auto c) { + impl->table.for_each_column_with_constraints([columnsCount, &index, &ss, this] (auto &c) { ss << this->serialize_column_schema(c); if(index < columnsCount - 1) { ss << ", "; @@ -685,7 +685,7 @@ namespace sqlite_orm { using tuple_t = decltype(f.args); std::vector args; args.reserve(std::tuple_size::value); - tuple_helper::tuple_for_each(f.args, [&args, this, noTableName, escape, ignoreBindable](auto &v){ + iterate_tuple(f.args, [&args, this, noTableName, escape, ignoreBindable](auto &v){ auto expression = this->string_from_expression(v, noTableName, escape, ignoreBindable); args.emplace_back(std::move(expression)); }); @@ -1257,7 +1257,7 @@ namespace sqlite_orm { tuple_helper::iterator()(idsTuple, [stmt, &index](auto &v){ using field_type = typename std::decay::type; statement_binder().bind(stmt, index++, v); - }); + }, false); if (sqlite3_step(stmt) == SQLITE_DONE) { // done.. }else{ @@ -2384,7 +2384,7 @@ namespace sqlite_orm { std::vector columnNames; auto compositeKeyColumnNames = impl.table.composite_key_columns_names(); - impl.table.for_each_column([&impl, &columnNames, &compositeKeyColumnNames] (auto c) { + impl.table.for_each_column([&impl, &columnNames, &compositeKeyColumnNames] (auto &c) { if(impl.table._without_rowid || !c.template has>()) { auto it = std::find(compositeKeyColumnNames.begin(), compositeKeyColumnNames.end(), @@ -2401,10 +2401,11 @@ namespace sqlite_orm { for(size_t i = 0; i < columnNamesCount; ++i) { ss << "\"" << columnNames[i] << "\""; if(i < columnNamesCount - 1) { - ss << ", "; + ss << ","; }else{ - ss << ") "; + ss << ")"; } + ss << " "; } }else{ ss << "DEFAULT "; diff --git a/dev/table.h b/dev/table.h index 208e14dcb..d872436c3 100644 --- a/dev/table.h +++ b/dev/table.h @@ -105,7 +105,7 @@ namespace sqlite_orm { std::vector composite_key_columns_names() { std::vector res; - this->impl.for_each_primary_key([this, &res](auto c){ + this->impl.for_each_primary_key([this, &res](auto &c){ res = this->composite_key_columns_names(c); }); return res; @@ -123,13 +123,13 @@ namespace sqlite_orm { } template - std::vector composite_key_columns_names(constraints::primary_key_t pk) { + std::vector composite_key_columns_names(const constraints::primary_key_t &pk) { std::vector res; using pk_columns_tuple = decltype(pk.columns); res.reserve(std::tuple_size::value); tuple_helper::iterator::value - 1, Args...>()(pk.columns, [this, &res](auto &v){ res.push_back(this->find_column_name(v)); - }); + }, false); return res; } diff --git a/dev/tuple_helper.h b/dev/tuple_helper.h index b9ef2b4f7..4fb01b371 100644 --- a/dev/tuple_helper.h +++ b/dev/tuple_helper.h @@ -56,20 +56,14 @@ namespace sqlite_orm { //.. } }; - - template - void tuple_for_each_impl(F&& f, const T& t, std::index_sequence){ - int _[] = { (f(std::get(t)), int{}) ... }; - (void)_; - } - - template - void tuple_for_each(const std::tuple& t, F&& f){ - tuple_for_each_impl(std::forward(f), t, std::index_sequence_for{}); - } } namespace internal { + template + void iterate_tuple(const std::tuple &t, const L &l) { + using tuple_type = std::tuple; + tuple_helper::iterator::value - 1, Args...>()(t, l, false); + } } } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 71aef5ea0..97f464621 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -246,7 +246,7 @@ namespace sqlite_orm { } }; - template + /*template void tuple_for_each_impl(F&& f, const T& t, std::index_sequence){ int _[] = { (f(std::get(t)), int{}) ... }; (void)_; @@ -255,11 +255,16 @@ namespace sqlite_orm { template void tuple_for_each(const std::tuple& t, F&& f){ tuple_for_each_impl(std::forward(f), t, std::index_sequence_for{}); - } + }*/ } namespace internal { + template + void iterate_tuple(const std::tuple &t, const L &l) { + using tuple_type = std::tuple; + tuple_helper::iterator::value - 1, Args...>()(t, l, false); + } } } #pragma once @@ -1192,7 +1197,7 @@ namespace sqlite_orm { */ std::unique_ptr default_value() { std::unique_ptr res; - tuple_helper::tuple_for_each(constraints, [&res](auto &v){ + iterate_tuple(constraints, [&res](auto &v){ auto dft = internal::default_value_extractor()(v); if(dft){ res = std::move(dft); @@ -5345,7 +5350,7 @@ namespace sqlite_orm { std::vector composite_key_columns_names() { std::vector res; - this->impl.for_each_primary_key([this, &res](auto c){ + this->impl.for_each_primary_key([this, &res](auto &c){ res = this->composite_key_columns_names(c); }); return res; @@ -5363,13 +5368,13 @@ namespace sqlite_orm { } template - std::vector composite_key_columns_names(constraints::primary_key_t pk) { + std::vector composite_key_columns_names(const constraints::primary_key_t &pk) { std::vector res; using pk_columns_tuple = decltype(pk.columns); res.reserve(std::tuple_size::value); tuple_helper::iterator::value - 1, Args...>()(pk.columns, [this, &res](auto &v){ res.push_back(this->find_column_name(v)); - }); + }, false); return res; } @@ -7095,7 +7100,7 @@ namespace sqlite_orm { columnNames.reserve(std::tuple_size::value); tuple_helper::iterator::value - 1, Cs...>()(fk.columns, [&columnNames, this](auto &c){ columnNames.push_back(this->impl.column_name(c)); - }); + }, false); for(size_t i = 0; i < columnNames.size(); ++i) { ss << columnNames[i]; if(i < columnNames.size() - 1) { @@ -7165,7 +7170,7 @@ namespace sqlite_orm { ss << "CREATE TABLE '" << tableName << "' ( "; auto columnsCount = impl->table.columns_count; auto index = 0; - impl->table.for_each_column_with_constraints([columnsCount, &index, &ss, this] (auto c) { + impl->table.for_each_column_with_constraints([columnsCount, &index, &ss, this] (auto &c) { ss << this->serialize_column_schema(c); if(index < columnsCount - 1) { ss << ", "; @@ -7631,7 +7636,7 @@ namespace sqlite_orm { using tuple_t = decltype(f.args); std::vector args; args.reserve(std::tuple_size::value); - tuple_helper::tuple_for_each(f.args, [&args, this, noTableName, escape, ignoreBindable](auto &v){ + iterate_tuple(f.args, [&args, this, noTableName, escape, ignoreBindable](auto &v){ auto expression = this->string_from_expression(v, noTableName, escape, ignoreBindable); args.emplace_back(std::move(expression)); }); @@ -8203,7 +8208,7 @@ namespace sqlite_orm { tuple_helper::iterator()(idsTuple, [stmt, &index](auto &v){ using field_type = typename std::decay::type; statement_binder().bind(stmt, index++, v); - }); + }, false); if (sqlite3_step(stmt) == SQLITE_DONE) { // done.. }else{ @@ -9330,7 +9335,7 @@ namespace sqlite_orm { std::vector columnNames; auto compositeKeyColumnNames = impl.table.composite_key_columns_names(); - impl.table.for_each_column([&impl, &columnNames, &compositeKeyColumnNames] (auto c) { + impl.table.for_each_column([&impl, &columnNames, &compositeKeyColumnNames] (auto &c) { if(impl.table._without_rowid || !c.template has>()) { auto it = std::find(compositeKeyColumnNames.begin(), compositeKeyColumnNames.end(), @@ -9347,10 +9352,11 @@ namespace sqlite_orm { for(size_t i = 0; i < columnNamesCount; ++i) { ss << "\"" << columnNames[i] << "\""; if(i < columnNamesCount - 1) { - ss << ", "; + ss << ","; }else{ - ss << ") "; + ss << ")"; } + ss << " "; } }else{ ss << "DEFAULT "; diff --git a/tests/tests.cpp b/tests/tests.cpp index 634947bf3..3b0e64a87 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -13,6 +13,55 @@ using namespace sqlite_orm; using std::cout; using std::endl; +void testCompositeKeyColumnsNames() { + cout << __func__ << endl; + + struct User { + int id = 0; + std::string name; + std::string info; + }; + + { + auto table = make_table("t", + make_column("id", &User::id), + make_column("name", &User::name), + make_column("info", &User::info), + primary_key(&User::id, &User::name)); + auto compositeKeyColumnsNames = table.composite_key_columns_names(); + std::vector expected = {"id", "name"}; + assert(std::equal(compositeKeyColumnsNames.begin(), compositeKeyColumnsNames.end(), expected.begin())); + } + { + auto table = make_table("t", + make_column("id", &User::id), + make_column("name", &User::name), + make_column("info", &User::info), + primary_key(&User::name, &User::id)); + auto compositeKeyColumnsNames = table.composite_key_columns_names(); + std::vector expected = {"name", "id"}; + assert(std::equal(compositeKeyColumnsNames.begin(), compositeKeyColumnsNames.end(), expected.begin())); + } + { + auto table = make_table("t", + make_column("id", &User::id), + make_column("name", &User::name), + make_column("info", &User::info), + primary_key(&User::name, &User::id, &User::info)); + auto compositeKeyColumnsNames = table.composite_key_columns_names(); + std::vector expected = {"name", "id", "info"}; + assert(std::equal(compositeKeyColumnsNames.begin(), compositeKeyColumnsNames.end(), expected.begin())); + } + { + auto table = make_table("t", + make_column("id", &User::id), + make_column("name", &User::name), + make_column("info", &User::info)); + auto compositeKeyColumnsNames = table.composite_key_columns_names(); + assert(compositeKeyColumnsNames.empty()); + } +} + void testNot() { cout << __func__ << endl; @@ -2297,7 +2346,7 @@ void testCompositeKey() { }; auto recordsTableName = "records"; - auto storage = make_storage("compisite_key.db", + auto storage = make_storage("", make_table(recordsTableName, make_column("year", &Record::year), make_column("month", &Record::month), @@ -2307,7 +2356,7 @@ void testCompositeKey() { storage.sync_schema(); assert(storage.sync_schema()[recordsTableName] == sqlite_orm::sync_schema_result::already_in_sync); - auto storage2 = make_storage("compisite_key2.db", + auto storage2 = make_storage("", make_table(recordsTableName, make_column("year", &Record::year), make_column("month", &Record::month), @@ -2316,7 +2365,7 @@ void testCompositeKey() { storage2.sync_schema(); assert(storage2.sync_schema()[recordsTableName] == sqlite_orm::sync_schema_result::already_in_sync); - auto storage3 = make_storage("compisite_key3.db", + auto storage3 = make_storage("", make_table(recordsTableName, make_column("year", &Record::year), make_column("month", &Record::month), @@ -2760,4 +2809,6 @@ int main(int, char **) { testBetween(); testNot(); + + testCompositeKeyColumnsNames(); } From 426eac55a09f6f8e62b1be0bec96f10037e51994 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Mon, 17 Jun 2019 17:10:35 +0300 Subject: [PATCH 112/232] refactored non reverse iterations --- dev/ast_iterator.h | 8 ++-- dev/storage.h | 46 +++++++++++----------- dev/table.h | 4 +- include/sqlite_orm/sqlite_orm.h | 69 ++++++++++++++------------------- 4 files changed, 58 insertions(+), 69 deletions(-) diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index 75d4a9810..8b8851a68 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -83,9 +83,9 @@ namespace sqlite_orm { template void operator()(const node_type &cols, const L &l) const { using columns_tuple = typename std::decay::type::columns_type; - tuple_helper::iterator::value - 1, Args...>()(cols.columns, [&l](auto &col){ + iterate_tuple(cols.columns, [&l](auto &col){ iterate_ast(col, l); - }, false); + }); } }; @@ -150,9 +150,9 @@ namespace sqlite_orm { template void operator()(const node_type &tuple, const L &l) const { - tuple_helper::iterator::value - 1, Args...>()(tuple, [&l](auto &v){ + iterate_tuple(tuple, [&l](auto &v){ iterate_ast(v, l); - }, false); + }); } }; diff --git a/dev/storage.h b/dev/storage.h index 96e47ba36..792ba1a70 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -147,9 +147,9 @@ namespace sqlite_orm { ss << static_cast(fk) << " ("; std::vector columnNames; columnNames.reserve(std::tuple_size::value); - tuple_helper::iterator::value - 1, Cs...>()(fk.columns, [&columnNames, this](auto &c){ + iterate_tuple(fk.columns, [&columnNames, this](auto &c){ columnNames.push_back(this->impl.column_name(c)); - }, false); + }); for(size_t i = 0; i < columnNames.size(); ++i) { ss << columnNames[i]; if(i < columnNames.size() - 1) { @@ -640,7 +640,7 @@ namespace sqlite_orm { std::stringstream ss; ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); using tuple_t = std::tuple; - tuple_helper::iterator::value - 1, Args...>()(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ + iterate_tuple(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ ss << ", " << this->string_from_expression(v, noTableName, escape, ignoreBindable); }); ss << ") "; @@ -652,9 +652,9 @@ namespace sqlite_orm { std::stringstream ss; ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); using tuple_t = std::tuple; - tuple_helper::iterator::value - 1, Args...>()(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ + iterate_tuple(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ ss << ", " << this->string_from_expression(v, noTableName, escape, ignoreBindable); - }, false); + }); ss << ") "; return ss.str(); } @@ -664,9 +664,9 @@ namespace sqlite_orm { std::stringstream ss; ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); using tuple_t = std::tuple; - tuple_helper::iterator::value - 1, Args...>()(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ + iterate_tuple(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ ss << ", " << this->string_from_expression(v, noTableName, escape, ignoreBindable); - }, false); + }); ss << ") "; return ss.str(); } @@ -761,14 +761,14 @@ namespace sqlite_orm { std::vector columnNames; columnNames.reserve(static_cast(cols.count)); using columns_tuple = typename std::decay::type::columns_type; - tuple_helper::iterator::value - 1, Args...>()(cols.columns, [&columnNames, this](auto &m){ + iterate_tuple(cols.columns, [&columnNames, this](auto &m){ auto columnName = this->string_from_expression(m, false, false, true); if(columnName.length()){ columnNames.push_back(columnName); }else{ throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); } - }, false); + }); return columnNames; } @@ -820,9 +820,9 @@ namespace sqlite_orm { } } using tuple_t = typename std::decay::type::conditions_type; - tuple_helper::iterator::value - 1, Args...>()(sel.conditions, [&ss, this](auto &v){ + iterate_tuple(sel.conditions, [&ss, this](auto &v){ this->process_single_condition(ss, v); - }, false); + }); if(!is_base_of_template::value){ if(!sel.highest_level){ ss << ") "; @@ -1107,9 +1107,9 @@ namespace sqlite_orm { template void process_conditions(std::stringstream &ss, const std::tuple &args) { using argsType = typename std::decay::type; - tuple_helper::iterator::value - 1, Args...>()(args, [this, &ss](auto &v){ + iterate_tuple(args, [this, &ss](auto &v){ this->process_single_condition(ss, v); - }, false); + }); } void on_open_internal(sqlite3 *db) { @@ -1254,10 +1254,10 @@ namespace sqlite_orm { auto index = 1; auto idsTuple = std::make_tuple(std::forward(ids)...); constexpr const auto idsCount = std::tuple_size::value; - tuple_helper::iterator()(idsTuple, [stmt, &index](auto &v){ + iterate_tuple(idsTuple, [stmt, &index](auto &v){ using field_type = typename std::decay::type; statement_binder().bind(stmt, index++, v); - }, false); + }); if (sqlite3_step(stmt) == SQLITE_DONE) { // done.. }else{ @@ -1503,7 +1503,7 @@ namespace sqlite_orm { std::set> parse_table_name(const core_functions::date_t &f) { auto res = this->parse_table_name(f.timestring); using tuple_t = decltype(f.modifiers); - tuple_helper::iterator::value - 1, Args...>()(f.modifiers, [&res, this](auto &v){ + iterate_tuple(f.modifiers, [&res, this](auto &v){ auto tableNames = this->parse_table_name(v); res.insert(tableNames.begin(), tableNames.end()); }); @@ -1514,7 +1514,7 @@ namespace sqlite_orm { std::set> parse_table_name(const core_functions::datetime_t &f) { auto res = this->parse_table_name(f.timestring); using tuple_t = decltype(f.modifiers); - tuple_helper::iterator::value - 1, Args...>()(f.modifiers, [&res, this](auto &v){ + iterate_tuple(f.modifiers, [&res, this](auto &v){ auto tableNames = this->parse_table_name(v); res.insert(tableNames.begin(), tableNames.end()); }); @@ -1718,10 +1718,10 @@ namespace sqlite_orm { std::set> parse_table_names(const internal::columns_t &cols) { std::set> res; using columns_tuple = typename std::decay::type::columns_type; - tuple_helper::iterator::value - 1, Args...>()(cols.columns, [&res, this](auto &m){ + iterate_tuple(cols.columns, [&res, this](auto &m){ auto tableName = this->parse_table_name(m); res.insert(tableName.begin(), tableName.end()); - }, false); + }); return res; } @@ -2318,14 +2318,14 @@ namespace sqlite_orm { std::vector columnNames; columnNames.reserve(colsCount); using columns_tuple = typename std::decay::type::columns_type; - tuple_helper::iterator::value - 1, Cols...>()(cols.columns, [&columnNames, this](auto &m){ + iterate_tuple(cols.columns, [&columnNames, this](auto &m){ auto columnName = this->string_from_expression(m, true, false); if(!columnName.empty()){ columnNames.push_back(columnName); }else{ throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); } - }, false); + }); ss << "("; for(size_t i = 0; i < columnNames.size(); ++i){ ss << columnNames[i]; @@ -2351,12 +2351,12 @@ namespace sqlite_orm { if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; - tuple_helper::iterator::value - 1, Cols...>()(cols.columns, [&o, &index, &stmt, &impl] (auto &m) { + iterate_tuple(cols.columns, [&o, &index, &stmt, &impl] (auto &m) { using column_type = typename std::decay::type; using field_type = typename column_result_t::type; const field_type *value = impl.table.template get_object_field_pointer(o, m); statement_binder().bind(stmt, index++, *value); - }, false); + }); if (sqlite3_step(stmt) == SQLITE_DONE) { return int(sqlite3_last_insert_rowid(connection->get_db())); }else{ diff --git a/dev/table.h b/dev/table.h index d872436c3..795f92fff 100644 --- a/dev/table.h +++ b/dev/table.h @@ -127,9 +127,9 @@ namespace sqlite_orm { std::vector res; using pk_columns_tuple = decltype(pk.columns); res.reserve(std::tuple_size::value); - tuple_helper::iterator::value - 1, Args...>()(pk.columns, [this, &res](auto &v){ + iterate_tuple(pk.columns, [this, &res](auto &v){ res.push_back(this->find_column_name(v)); - }, false); + }); return res; } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 97f464621..a195c1ebf 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -245,17 +245,6 @@ namespace sqlite_orm { //.. } }; - - /*template - void tuple_for_each_impl(F&& f, const T& t, std::index_sequence){ - int _[] = { (f(std::get(t)), int{}) ... }; - (void)_; - } - - template - void tuple_for_each(const std::tuple& t, F&& f){ - tuple_for_each_impl(std::forward(f), t, std::index_sequence_for{}); - }*/ } namespace internal { @@ -5372,9 +5361,9 @@ namespace sqlite_orm { std::vector res; using pk_columns_tuple = decltype(pk.columns); res.reserve(std::tuple_size::value); - tuple_helper::iterator::value - 1, Args...>()(pk.columns, [this, &res](auto &v){ + iterate_tuple(pk.columns, [this, &res](auto &v){ res.push_back(this->find_column_name(v)); - }, false); + }); return res; } @@ -6793,9 +6782,9 @@ namespace sqlite_orm { template void operator()(const node_type &cols, const L &l) const { using columns_tuple = typename std::decay::type::columns_type; - tuple_helper::iterator::value - 1, Args...>()(cols.columns, [&l](auto &col){ + iterate_tuple(cols.columns, [&l](auto &col){ iterate_ast(col, l); - }, false); + }); } }; @@ -6860,9 +6849,9 @@ namespace sqlite_orm { template void operator()(const node_type &tuple, const L &l) const { - tuple_helper::iterator::value - 1, Args...>()(tuple, [&l](auto &v){ + iterate_tuple(tuple, [&l](auto &v){ iterate_ast(v, l); - }, false); + }); } }; @@ -7098,9 +7087,9 @@ namespace sqlite_orm { ss << static_cast(fk) << " ("; std::vector columnNames; columnNames.reserve(std::tuple_size::value); - tuple_helper::iterator::value - 1, Cs...>()(fk.columns, [&columnNames, this](auto &c){ + iterate_tuple(fk.columns, [&columnNames, this](auto &c){ columnNames.push_back(this->impl.column_name(c)); - }, false); + }); for(size_t i = 0; i < columnNames.size(); ++i) { ss << columnNames[i]; if(i < columnNames.size() - 1) { @@ -7591,7 +7580,7 @@ namespace sqlite_orm { std::stringstream ss; ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); using tuple_t = std::tuple; - tuple_helper::iterator::value - 1, Args...>()(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ + iterate_tuple(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ ss << ", " << this->string_from_expression(v, noTableName, escape, ignoreBindable); }); ss << ") "; @@ -7603,9 +7592,9 @@ namespace sqlite_orm { std::stringstream ss; ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); using tuple_t = std::tuple; - tuple_helper::iterator::value - 1, Args...>()(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ + iterate_tuple(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ ss << ", " << this->string_from_expression(v, noTableName, escape, ignoreBindable); - }, false); + }); ss << ") "; return ss.str(); } @@ -7615,9 +7604,9 @@ namespace sqlite_orm { std::stringstream ss; ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); using tuple_t = std::tuple; - tuple_helper::iterator::value - 1, Args...>()(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ + iterate_tuple(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ ss << ", " << this->string_from_expression(v, noTableName, escape, ignoreBindable); - }, false); + }); ss << ") "; return ss.str(); } @@ -7712,14 +7701,14 @@ namespace sqlite_orm { std::vector columnNames; columnNames.reserve(static_cast(cols.count)); using columns_tuple = typename std::decay::type::columns_type; - tuple_helper::iterator::value - 1, Args...>()(cols.columns, [&columnNames, this](auto &m){ + iterate_tuple(cols.columns, [&columnNames, this](auto &m){ auto columnName = this->string_from_expression(m, false, false, true); if(columnName.length()){ columnNames.push_back(columnName); }else{ throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); } - }, false); + }); return columnNames; } @@ -7771,9 +7760,9 @@ namespace sqlite_orm { } } using tuple_t = typename std::decay::type::conditions_type; - tuple_helper::iterator::value - 1, Args...>()(sel.conditions, [&ss, this](auto &v){ + iterate_tuple(sel.conditions, [&ss, this](auto &v){ this->process_single_condition(ss, v); - }, false); + }); if(!is_base_of_template::value){ if(!sel.highest_level){ ss << ") "; @@ -8058,9 +8047,9 @@ namespace sqlite_orm { template void process_conditions(std::stringstream &ss, const std::tuple &args) { using argsType = typename std::decay::type; - tuple_helper::iterator::value - 1, Args...>()(args, [this, &ss](auto &v){ + iterate_tuple(args, [this, &ss](auto &v){ this->process_single_condition(ss, v); - }, false); + }); } void on_open_internal(sqlite3 *db) { @@ -8205,10 +8194,10 @@ namespace sqlite_orm { auto index = 1; auto idsTuple = std::make_tuple(std::forward(ids)...); constexpr const auto idsCount = std::tuple_size::value; - tuple_helper::iterator()(idsTuple, [stmt, &index](auto &v){ + iterate_tuple(idsTuple, [stmt, &index](auto &v){ using field_type = typename std::decay::type; statement_binder().bind(stmt, index++, v); - }, false); + }); if (sqlite3_step(stmt) == SQLITE_DONE) { // done.. }else{ @@ -8454,7 +8443,7 @@ namespace sqlite_orm { std::set> parse_table_name(const core_functions::date_t &f) { auto res = this->parse_table_name(f.timestring); using tuple_t = decltype(f.modifiers); - tuple_helper::iterator::value - 1, Args...>()(f.modifiers, [&res, this](auto &v){ + iterate_tuple(f.modifiers, [&res, this](auto &v){ auto tableNames = this->parse_table_name(v); res.insert(tableNames.begin(), tableNames.end()); }); @@ -8465,7 +8454,7 @@ namespace sqlite_orm { std::set> parse_table_name(const core_functions::datetime_t &f) { auto res = this->parse_table_name(f.timestring); using tuple_t = decltype(f.modifiers); - tuple_helper::iterator::value - 1, Args...>()(f.modifiers, [&res, this](auto &v){ + iterate_tuple(f.modifiers, [&res, this](auto &v){ auto tableNames = this->parse_table_name(v); res.insert(tableNames.begin(), tableNames.end()); }); @@ -8669,10 +8658,10 @@ namespace sqlite_orm { std::set> parse_table_names(const internal::columns_t &cols) { std::set> res; using columns_tuple = typename std::decay::type::columns_type; - tuple_helper::iterator::value - 1, Args...>()(cols.columns, [&res, this](auto &m){ + iterate_tuple(cols.columns, [&res, this](auto &m){ auto tableName = this->parse_table_name(m); res.insert(tableName.begin(), tableName.end()); - }, false); + }); return res; } @@ -9269,14 +9258,14 @@ namespace sqlite_orm { std::vector columnNames; columnNames.reserve(colsCount); using columns_tuple = typename std::decay::type::columns_type; - tuple_helper::iterator::value - 1, Cols...>()(cols.columns, [&columnNames, this](auto &m){ + iterate_tuple(cols.columns, [&columnNames, this](auto &m){ auto columnName = this->string_from_expression(m, true, false); if(!columnName.empty()){ columnNames.push_back(columnName); }else{ throw std::system_error(std::make_error_code(orm_error_code::column_not_found)); } - }, false); + }); ss << "("; for(size_t i = 0; i < columnNames.size(); ++i){ ss << columnNames[i]; @@ -9302,12 +9291,12 @@ namespace sqlite_orm { if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; - tuple_helper::iterator::value - 1, Cols...>()(cols.columns, [&o, &index, &stmt, &impl] (auto &m) { + iterate_tuple(cols.columns, [&o, &index, &stmt, &impl] (auto &m) { using column_type = typename std::decay::type; using field_type = typename column_result_t::type; const field_type *value = impl.table.template get_object_field_pointer(o, m); statement_binder().bind(stmt, index++, *value); - }, false); + }); if (sqlite3_step(stmt) == SQLITE_DONE) { return int(sqlite3_last_insert_rowid(connection->get_db())); }else{ From 51cd4ea5e213b08d15b241550e4669058422449e Mon Sep 17 00:00:00 2001 From: fnc12 Date: Wed, 19 Jun 2019 10:17:53 +0300 Subject: [PATCH 113/232] fixed abs binding --- dev/ast_iterator.h | 31 ++++++++++ dev/column_result.h | 5 ++ dev/core_functions.h | 38 +++++++++--- dev/storage.h | 29 +++++++-- examples/core_functions.cpp | 3 + include/sqlite_orm/sqlite_orm.h | 104 +++++++++++++++++++++++++++----- tests/tests.cpp | 23 +++++++ 7 files changed, 203 insertions(+), 30 deletions(-) diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index 8b8851a68..5c08243c3 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -6,6 +6,7 @@ #include "select_constraints.h" #include "operators.h" #include "tuple_helper.h" +#include "core_functions.h" namespace sqlite_orm { @@ -228,5 +229,35 @@ namespace sqlite_orm { iterate_ast(neg.c, l); } }; + + template + struct ast_iterator, void> { + using node_type = core_functions::coalesce_t; + + template + void operator()(const node_type &c, const L &l) const { + iterate_ast(c.args, l); + } + }; + + template + struct ast_iterator, void> { + using node_type = core_functions::length_t; + + template + void operator()(const node_type &length, const L &l) const { + iterate_ast(length.arg, l); + } + }; + + template + struct ast_iterator, void> { + using node_type = core_functions::abs_t; + + template + void operator()(const node_type &a, const L &l) const { + iterate_ast(a.arg, l); + } + }; } } diff --git a/dev/column_result.h b/dev/column_result.h index 047d46844..fe6ffaf8c 100644 --- a/dev/column_result.h +++ b/dev/column_result.h @@ -306,5 +306,10 @@ namespace sqlite_orm { struct column_result_t, void> { using type = T; }; + + template + struct column_result_t, void> { + using type = R; + }; } } diff --git a/dev/core_functions.h b/dev/core_functions.h index ce1e3d9f9..35557860b 100644 --- a/dev/core_functions.h +++ b/dev/core_functions.h @@ -21,11 +21,11 @@ namespace sqlite_orm { */ template struct length_t : public core_function_t { - T t; + using arg_type = T; - length_t() = default; + arg_type arg; - length_t(T t_): t(t_) {} + length_t(arg_type arg_) : arg(std::move(arg_)) {} operator std::string() const { return "LENGTH"; @@ -37,11 +37,11 @@ namespace sqlite_orm { */ template struct abs_t : public core_function_t { - T t; + using arg_type = T; - abs_t() = default; + arg_type arg; - abs_t(T t_): t(t_) {} + abs_t(arg_type arg_): arg(std::move(arg_)) {} operator std::string() const { return "ABS"; @@ -219,6 +219,21 @@ namespace sqlite_orm { }; #endif + + template + struct coalesce_t : core_function_t { + using return_type = R; + using args_type = std::tuple; + + args_type args; + + coalesce_t(args_type args_) : args(std::move(args_)) {} + + operator std::string() const { + return "COALESCE"; + } + }; + template struct date_t : core_function_t { using modifiers_type = std::tuple; @@ -349,6 +364,11 @@ namespace sqlite_orm { #endif + template + core_functions::coalesce_t coalesce(Args&& ...args) { + return {std::make_tuple(std::forward(args)...)}; + } + template> Res trim(X x) { return Res(x); @@ -385,14 +405,12 @@ namespace sqlite_orm { template core_functions::length_t length(T t) { - using result_type = core_functions::length_t; - return result_type(t); + return {t}; } template core_functions::abs_t abs(T t) { - using result_type = core_functions::abs_t; - return result_type(t); + return {t}; } template> diff --git a/dev/storage.h b/dev/storage.h index 792ba1a70..7b30ddde7 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -328,6 +328,26 @@ namespace sqlite_orm { return T::get(); } + template + std::string string_from_expression(const core_functions::coalesce_t &c, bool noTableName, bool escape, bool ignoreBindable = false) { + std::stringstream ss; + ss << static_cast(c) << "("; + std::vector args; + using args_type = typename std::decay::type::args_type; + args.reserve(std::tuple_size::value); + iterate_tuple(c.args, [&args, this, noTableName, escape, ignoreBindable](auto &v){ + args.push_back(this->string_from_expression(v, noTableName, escape, ignoreBindable)); + }); + for(size_t i = 0; i < args.size(); ++i){ + ss << args[i]; + if(i < args.size() - 1){ + ss << ", "; + } + } + ss << ") "; + return ss.str(); + } + template std::string string_from_expression(const as_t &als, bool noTableName, bool escape, bool ignoreBindable = false) { auto tableAliasString = alias_extractor::get(); @@ -630,7 +650,7 @@ namespace sqlite_orm { template std::string string_from_expression(const core_functions::length_t &len, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(len.t, noTableName, escape, ignoreBindable); + auto expr = this->string_from_expression(len.arg, noTableName, escape, ignoreBindable); ss << static_cast(len) << "(" << expr << ") "; return ss.str(); } @@ -723,7 +743,7 @@ namespace sqlite_orm { template std::string string_from_expression(const core_functions::abs_t &a, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(a.t, noTableName, escape, ignoreBindable); + auto expr = this->string_from_expression(a.arg, noTableName, escape, ignoreBindable); ss << static_cast(a) << "(" << expr << ") "; return ss.str(); } @@ -1253,7 +1273,6 @@ namespace sqlite_orm { statement_finalizer finalizer{stmt}; auto index = 1; auto idsTuple = std::make_tuple(std::forward(ids)...); - constexpr const auto idsCount = std::tuple_size::value; iterate_tuple(idsTuple, [stmt, &index](auto &v){ using field_type = typename std::decay::type; statement_binder().bind(stmt, index++, v); @@ -1496,7 +1515,7 @@ namespace sqlite_orm { template std::set> parse_table_name(const core_functions::length_t &len) { - return this->parse_table_name(len.t); + return this->parse_table_name(len.arg); } template @@ -1591,7 +1610,7 @@ namespace sqlite_orm { template std::set> parse_table_name(const core_functions::abs_t &a) { - return this->parse_table_name(a.t); + return this->parse_table_name(a.arg); } template diff --git a/examples/core_functions.cpp b/examples/core_functions.cpp index 2f2f56988..c7afd4a7b 100644 --- a/examples/core_functions.cpp +++ b/examples/core_functions.cpp @@ -213,5 +213,8 @@ int main(int, char **argv) { // SELECT rtrim('totn6372', '0123456789'); cout << "rtrim('totn6372', '0123456789') = *" << storage.select(rtrim("totn6372", "0123456789")).front() << "*" << endl; + // SELECT COALESCE(10,20); + cout << "COALESCE(10,20) = " << storage.select(coalesce(10, 20)).front() << endl; + return 0; } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index a195c1ebf..c88aac394 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -2838,11 +2838,11 @@ namespace sqlite_orm { */ template struct length_t : public core_function_t { - T t; + using arg_type = T; - length_t() = default; + arg_type arg; - length_t(T t_): t(t_) {} + length_t(arg_type arg_) : arg(std::move(arg_)) {} operator std::string() const { return "LENGTH"; @@ -2854,11 +2854,11 @@ namespace sqlite_orm { */ template struct abs_t : public core_function_t { - T t; + using arg_type = T; - abs_t() = default; + arg_type arg; - abs_t(T t_): t(t_) {} + abs_t(arg_type arg_): arg(std::move(arg_)) {} operator std::string() const { return "ABS"; @@ -3036,6 +3036,21 @@ namespace sqlite_orm { }; #endif + + template + struct coalesce_t : core_function_t { + using return_type = R; + using args_type = std::tuple; + + args_type args; + + coalesce_t(args_type args_) : args(std::move(args_)) {} + + operator std::string() const { + return "COALESCE"; + } + }; + template struct date_t : core_function_t { using modifiers_type = std::tuple; @@ -3166,6 +3181,11 @@ namespace sqlite_orm { #endif + template + core_functions::coalesce_t coalesce(Args&& ...args) { + return {std::make_tuple(std::forward(args)...)}; + } + template> Res trim(X x) { return Res(x); @@ -3202,14 +3222,12 @@ namespace sqlite_orm { template core_functions::length_t length(T t) { - using result_type = core_functions::length_t; - return result_type(t); + return {t}; } template core_functions::abs_t abs(T t) { - using result_type = core_functions::abs_t; - return result_type(t); + return {t}; } template> @@ -5062,6 +5080,11 @@ namespace sqlite_orm { struct column_result_t, void> { using type = T; }; + + template + struct column_result_t, void> { + using type = R; + }; } } #pragma once @@ -6705,6 +6728,8 @@ namespace sqlite_orm { // #include "tuple_helper.h" +// #include "core_functions.h" + namespace sqlite_orm { @@ -6927,6 +6952,36 @@ namespace sqlite_orm { iterate_ast(neg.c, l); } }; + + template + struct ast_iterator, void> { + using node_type = core_functions::coalesce_t; + + template + void operator()(const node_type &c, const L &l) const { + iterate_ast(c.args, l); + } + }; + + template + struct ast_iterator, void> { + using node_type = core_functions::length_t; + + template + void operator()(const node_type &length, const L &l) const { + iterate_ast(length.arg, l); + } + }; + + template + struct ast_iterator, void> { + using node_type = core_functions::abs_t; + + template + void operator()(const node_type &a, const L &l) const { + iterate_ast(a.arg, l); + } + }; } } @@ -7268,6 +7323,26 @@ namespace sqlite_orm { return T::get(); } + template + std::string string_from_expression(const core_functions::coalesce_t &c, bool noTableName, bool escape, bool ignoreBindable = false) { + std::stringstream ss; + ss << static_cast(c) << "("; + std::vector args; + using args_type = typename std::decay::type::args_type; + args.reserve(std::tuple_size::value); + iterate_tuple(c.args, [&args, this, noTableName, escape, ignoreBindable](auto &v){ + args.push_back(this->string_from_expression(v, noTableName, escape, ignoreBindable)); + }); + for(size_t i = 0; i < args.size(); ++i){ + ss << args[i]; + if(i < args.size() - 1){ + ss << ", "; + } + } + ss << ") "; + return ss.str(); + } + template std::string string_from_expression(const as_t &als, bool noTableName, bool escape, bool ignoreBindable = false) { auto tableAliasString = alias_extractor::get(); @@ -7570,7 +7645,7 @@ namespace sqlite_orm { template std::string string_from_expression(const core_functions::length_t &len, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(len.t, noTableName, escape, ignoreBindable); + auto expr = this->string_from_expression(len.arg, noTableName, escape, ignoreBindable); ss << static_cast(len) << "(" << expr << ") "; return ss.str(); } @@ -7663,7 +7738,7 @@ namespace sqlite_orm { template std::string string_from_expression(const core_functions::abs_t &a, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(a.t, noTableName, escape, ignoreBindable); + auto expr = this->string_from_expression(a.arg, noTableName, escape, ignoreBindable); ss << static_cast(a) << "(" << expr << ") "; return ss.str(); } @@ -8193,7 +8268,6 @@ namespace sqlite_orm { statement_finalizer finalizer{stmt}; auto index = 1; auto idsTuple = std::make_tuple(std::forward(ids)...); - constexpr const auto idsCount = std::tuple_size::value; iterate_tuple(idsTuple, [stmt, &index](auto &v){ using field_type = typename std::decay::type; statement_binder().bind(stmt, index++, v); @@ -8436,7 +8510,7 @@ namespace sqlite_orm { template std::set> parse_table_name(const core_functions::length_t &len) { - return this->parse_table_name(len.t); + return this->parse_table_name(len.arg); } template @@ -8531,7 +8605,7 @@ namespace sqlite_orm { template std::set> parse_table_name(const core_functions::abs_t &a) { - return this->parse_table_name(a.t); + return this->parse_table_name(a.arg); } template diff --git a/tests/tests.cpp b/tests/tests.cpp index 3b0e64a87..382b29bef 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -13,6 +13,25 @@ using namespace sqlite_orm; using std::cout; using std::endl; +void testLength() { + cout << __func__ << endl; + + auto storage = make_storage({}); + auto rows = storage.select(length("ototo")); + assert(!rows.empty()); + assert(rows.front() == 5); +} + +void testAbs() { + cout << __func__ << endl; + + auto storage = make_storage({}); + auto rows = storage.select(sqlite_orm::abs(-10)); + assert(!rows.empty()); + assert(rows.front()); + assert(*rows.front() == 10); +} + void testCompositeKeyColumnsNames() { cout << __func__ << endl; @@ -2811,4 +2830,8 @@ int main(int, char **) { testNot(); testCompositeKeyColumnsNames(); + + testLength(); + + testAbs(); } From 12441ba47a891d6df986f79f9fee699d66d8555d Mon Sep 17 00:00:00 2001 From: fnc12 Date: Wed, 19 Jun 2019 10:49:52 +0300 Subject: [PATCH 114/232] added string from expression for std::nullptr_t --- dev/operators.h | 4 ++++ dev/storage.h | 4 ++++ include/sqlite_orm/sqlite_orm.h | 8 ++++++++ tests/tests.cpp | 27 +++++++++++++++++++++++++++ 4 files changed, 43 insertions(+) diff --git a/dev/operators.h b/dev/operators.h index aab06f453..98ffb5f77 100644 --- a/dev/operators.h +++ b/dev/operators.h @@ -122,6 +122,10 @@ namespace sqlite_orm { assign_t operator=(R r) const { return {this->t, std::move(r)}; } + + assign_t operator=(std::nullptr_t) const { + return {this->t, nullptr}; + } }; } diff --git a/dev/storage.h b/dev/storage.h index 792ba1a70..0f125c9ae 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -323,6 +323,10 @@ namespace sqlite_orm { } } + std::string string_from_expression(std::nullptr_t, bool /*noTableName*/, bool /*escape*/, bool /*ignoreBindable*/ = false) { + return "NULL"; + } + template std::string string_from_expression(const alias_holder &, bool /*noTableName*/, bool /*escape*/, bool /*ignoreBindable*/ = false) { return T::get(); diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index a195c1ebf..145b8f8e5 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -1028,6 +1028,10 @@ namespace sqlite_orm { assign_t operator=(R r) const { return {this->t, std::move(r)}; } + + assign_t operator=(std::nullptr_t) const { + return {this->t, nullptr}; + } }; } @@ -7263,6 +7267,10 @@ namespace sqlite_orm { } } + std::string string_from_expression(std::nullptr_t, bool /*noTableName*/, bool /*escape*/, bool /*ignoreBindable*/ = false) { + return "NULL"; + } + template std::string string_from_expression(const alias_holder &, bool /*noTableName*/, bool /*escape*/, bool /*ignoreBindable*/ = false) { return T::get(); diff --git a/tests/tests.cpp b/tests/tests.cpp index 3b0e64a87..2f1dbc580 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -13,6 +13,31 @@ using namespace sqlite_orm; using std::cout; using std::endl; +void testSetNull() { + cout << __func__ << endl; + + struct User { + int id = 0; + std::unique_ptr name; + }; + + auto storage = make_storage({}, + make_table("users", + make_column("id", &User::id, primary_key()), + make_column("name", &User::name))); + storage.sync_schema(); + + storage.replace(User{1, std::make_unique("Ototo")}); + assert(storage.count() == 1); + +// storage.update_all(set(c(&User::name) = nullptr)); + storage.update_all(set(assign(&User::name, nullptr))); + + auto rows = storage.get_all(); + assert(rows.size() == 1); + assert(!rows.front().name); +} + void testCompositeKeyColumnsNames() { cout << __func__ << endl; @@ -2811,4 +2836,6 @@ int main(int, char **) { testNot(); testCompositeKeyColumnsNames(); + + testSetNull(); } From 8b63bc910f458d5c22cb5ea1d4543bfb4a0b06fc Mon Sep 17 00:00:00 2001 From: Yevgeniy Zakharov Date: Wed, 19 Jun 2019 17:46:50 +0300 Subject: [PATCH 115/232] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4af8ee605..1bd1e320f 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,8 @@ SQLite ORM light header only library for modern C++ # Status | Branch | Travis | Appveyor | Coverity Scan | codecov.io | Website | | :----- | :----- | :------- | :------------ | :--------- | :------ | -| [`master`](https://github.com/fcn12/sqlite_orm/tree/master) | [![Build Status](https://travis-ci.org/fnc12/sqlite_orm.svg?branch=master)](https://travis-ci.org/fcn12/sqlite_orm) | [![Build status](https://ci.appveyor.com/api/projects/status/github/fnc12/sqlite_orm?branch=master&svg=true)](https://ci.appveyor.com/project/fnc12/sqlite-orm/history) | | | [![Website](https://img.shields.io/badge/official-website-brightgreen.svg)](https://github.com/fcn12/sqlite_orm/) | -| [`dev`](https://github.com/fcn12/sqlite_orm/tree/dev) | [![Build Status](https://travis-ci.org/fnc12/sqlite_orm.svg?branch=dev)](https://travis-ci.org/fcn12/sqlite_orm) | [![Build status](https://ci.appveyor.com/api/projects/status/github/fnc12/sqlite_orm?branch=dev&svg=true)](https://ci.appveyor.com/project/fnc12/sqlite-orm/history) | | | [![Website](https://img.shields.io/badge/official-website-brightgreen.svg)](https://github.com/fnc12/sqlite_orm/tree/dev) | +| [`master`](https://github.com/fnc12/sqlite_orm/tree/master) | [![Build Status](https://travis-ci.org/fnc12/sqlite_orm.svg?branch=master)](https://travis-ci.org/fnc12/sqlite_orm) | [![Build status](https://ci.appveyor.com/api/projects/status/github/fnc12/sqlite_orm?branch=master&svg=true)](https://ci.appveyor.com/project/fnc12/sqlite-orm/history) | | | [![Website](https://img.shields.io/badge/official-website-brightgreen.svg)](https://github.com/fnc12/sqlite_orm/) | +| [`dev`](https://github.com/fnc12/sqlite_orm/tree/dev) | [![Build Status](https://travis-ci.org/fnc12/sqlite_orm.svg?branch=dev)](https://travis-ci.org/fnc12/sqlite_orm) | [![Build status](https://ci.appveyor.com/api/projects/status/github/fnc12/sqlite_orm?branch=dev&svg=true)](https://ci.appveyor.com/project/fnc12/sqlite-orm/history) | | | [![Website](https://img.shields.io/badge/official-website-brightgreen.svg)](https://github.com/fnc12/sqlite_orm/tree/dev) | # Advantages From 37979bf1ef22434b63d89f408e2575e32fe419da Mon Sep 17 00:00:00 2001 From: Yevgeniy Zakharov Date: Wed, 19 Jun 2019 17:47:31 +0300 Subject: [PATCH 116/232] Removed os x gcc until it is fixed in vcpkg --- .travis.yml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7a375735a..a958d35fc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -58,18 +58,6 @@ matrix: - CXX=/usr/local/opt/llvm/bin/clang++ - VCPKG_ALLOW_APPLE_CLANG=1 - SQLITE_ORM_OMITS_CODECVT=ON - - name: "osx gcc" - addons: - homebrew: - packages: - - gcc6 - compiler: gcc - os: osx - osx_image: xcode10.1 - env: - - CC=gcc-6 - - CXX=g++-6 - - SQLITE_ORM_OMITS_CODECVT=OFF before_install: # coveralls test coverage: From a700926d6509430c831d0cab249ea94332e1d62a Mon Sep 17 00:00:00 2001 From: Yevgeniy Zakharov Date: Wed, 19 Jun 2019 18:07:06 +0300 Subject: [PATCH 117/232] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1bd1e320f..005fce6ea 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,8 @@ SQLite ORM light header only library for modern C++ # Status -| Branch | Travis | Appveyor | Coverity Scan | codecov.io | Website | -| :----- | :----- | :------- | :------------ | :--------- | :------ | +| Branch | Travis | Appveyor | +| :----- | :----- | :------- | | [`master`](https://github.com/fnc12/sqlite_orm/tree/master) | [![Build Status](https://travis-ci.org/fnc12/sqlite_orm.svg?branch=master)](https://travis-ci.org/fnc12/sqlite_orm) | [![Build status](https://ci.appveyor.com/api/projects/status/github/fnc12/sqlite_orm?branch=master&svg=true)](https://ci.appveyor.com/project/fnc12/sqlite-orm/history) | | | [![Website](https://img.shields.io/badge/official-website-brightgreen.svg)](https://github.com/fnc12/sqlite_orm/) | | [`dev`](https://github.com/fnc12/sqlite_orm/tree/dev) | [![Build Status](https://travis-ci.org/fnc12/sqlite_orm.svg?branch=dev)](https://travis-ci.org/fnc12/sqlite_orm) | [![Build status](https://ci.appveyor.com/api/projects/status/github/fnc12/sqlite_orm?branch=dev&svg=true)](https://ci.appveyor.com/project/fnc12/sqlite-orm/history) | | | [![Website](https://img.shields.io/badge/official-website-brightgreen.svg)](https://github.com/fnc12/sqlite_orm/tree/dev) | From d725d5e01158dce682c7f7114c391e6b0ab2d328 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Wed, 19 Jun 2019 18:41:53 +0300 Subject: [PATCH 118/232] fixed null binding --- dev/statement_binder.h | 6 +++--- dev/storage.h | 14 +++++++++----- include/sqlite_orm/sqlite_orm.h | 20 ++++++++++++-------- tests/tests.cpp | 29 ++++++++++++++++++++++++----- 4 files changed, 48 insertions(+), 21 deletions(-) diff --git a/dev/statement_binder.h b/dev/statement_binder.h index e2925d89f..6354c5948 100644 --- a/dev/statement_binder.h +++ b/dev/statement_binder.h @@ -82,9 +82,9 @@ namespace sqlite_orm { /** * Specialization for std::nullptr_t. */ - template - struct statement_binder::value>> { - int bind(sqlite3_stmt *stmt, int index, const V &) { + template<> + struct statement_binder { + int bind(sqlite3_stmt *stmt, int index, const std::nullptr_t &) { return sqlite3_bind_null(stmt, index); } }; diff --git a/dev/storage.h b/dev/storage.h index 0f125c9ae..891d4b93d 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -323,8 +323,12 @@ namespace sqlite_orm { } } - std::string string_from_expression(std::nullptr_t, bool /*noTableName*/, bool /*escape*/, bool /*ignoreBindable*/ = false) { - return "NULL"; + std::string string_from_expression(std::nullptr_t, bool /*noTableName*/, bool /*escape*/, bool ignoreBindable = false) { + if(ignoreBindable){ + return "?"; + }else{ + return "NULL"; + } } template @@ -339,12 +343,12 @@ namespace sqlite_orm { } template - std::string string_from_expression(const alias_column_t &als, bool noTableName, bool escape, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const alias_column_t &als, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; if(!noTableName){ ss << "'" << T::get() << "'."; } - ss << this->string_from_expression(als.column, true, escape); + ss << this->string_from_expression(als.column, true, escape, ignoreBindable); return ss.str(); } @@ -2323,7 +2327,7 @@ namespace sqlite_orm { columnNames.reserve(colsCount); using columns_tuple = typename std::decay::type::columns_type; iterate_tuple(cols.columns, [&columnNames, this](auto &m){ - auto columnName = this->string_from_expression(m, true, false); + auto columnName = this->string_from_expression(m, true, false, true); if(!columnName.empty()){ columnNames.push_back(columnName); }else{ diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 145b8f8e5..a4e055c37 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -4005,9 +4005,9 @@ namespace sqlite_orm { /** * Specialization for std::nullptr_t. */ - template - struct statement_binder::value>> { - int bind(sqlite3_stmt *stmt, int index, const V &) { + template<> + struct statement_binder { + int bind(sqlite3_stmt *stmt, int index, const std::nullptr_t &) { return sqlite3_bind_null(stmt, index); } }; @@ -7267,8 +7267,12 @@ namespace sqlite_orm { } } - std::string string_from_expression(std::nullptr_t, bool /*noTableName*/, bool /*escape*/, bool /*ignoreBindable*/ = false) { - return "NULL"; + std::string string_from_expression(std::nullptr_t, bool /*noTableName*/, bool /*escape*/, bool ignoreBindable = false) { + if(ignoreBindable){ + return "?"; + }else{ + return "NULL"; + } } template @@ -7283,12 +7287,12 @@ namespace sqlite_orm { } template - std::string string_from_expression(const alias_column_t &als, bool noTableName, bool escape, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(const alias_column_t &als, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; if(!noTableName){ ss << "'" << T::get() << "'."; } - ss << this->string_from_expression(als.column, true, escape); + ss << this->string_from_expression(als.column, true, escape, ignoreBindable); return ss.str(); } @@ -9267,7 +9271,7 @@ namespace sqlite_orm { columnNames.reserve(colsCount); using columns_tuple = typename std::decay::type::columns_type; iterate_tuple(cols.columns, [&columnNames, this](auto &m){ - auto columnName = this->string_from_expression(m, true, false); + auto columnName = this->string_from_expression(m, true, false, true); if(!columnName.empty()){ columnNames.push_back(columnName); }else{ diff --git a/tests/tests.cpp b/tests/tests.cpp index 2f1dbc580..ff504dac3 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -30,12 +30,31 @@ void testSetNull() { storage.replace(User{1, std::make_unique("Ototo")}); assert(storage.count() == 1); -// storage.update_all(set(c(&User::name) = nullptr)); + { + auto rows = storage.get_all(); + assert(rows.size() == 1); + assert(rows.front().name); + } storage.update_all(set(assign(&User::name, nullptr))); - - auto rows = storage.get_all(); - assert(rows.size() == 1); - assert(!rows.front().name); + { + auto rows = storage.get_all(); + assert(rows.size() == 1); + assert(!rows.front().name); + } + storage.update_all(set(assign(&User::name, "ototo"))); + { + auto rows = storage.get_all(); + assert(rows.size() == 1); + assert(rows.front().name); + assert(*rows.front().name == "ototo"); + } + storage.update_all(set(assign(&User::name, nullptr)), + where(is_equal(&User::id, 1))); + { + auto rows = storage.get_all(); + assert(rows.size() == 1); + assert(!rows.front().name); + } } void testCompositeKeyColumnsNames() { From aceae3c05de576388608fc530fc8031ef11d7e2a Mon Sep 17 00:00:00 2001 From: fnc12 Date: Wed, 19 Jun 2019 18:50:59 +0300 Subject: [PATCH 119/232] fixed lower core function --- dev/ast_iterator.h | 10 ++++++++++ dev/core_functions.h | 12 ++++++------ dev/storage.h | 4 ++-- include/sqlite_orm/sqlite_orm.h | 26 ++++++++++++++++++-------- tests/tests.cpp | 11 +++++++++++ 5 files changed, 47 insertions(+), 16 deletions(-) diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index 5c08243c3..863c91f0a 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -259,5 +259,15 @@ namespace sqlite_orm { iterate_ast(a.arg, l); } }; + + template + struct ast_iterator, void> { + using node_type = core_functions::lower_t; + + template + void operator()(const node_type &low, const L &l) const { + iterate_ast(low.arg, l); + } + }; } } diff --git a/dev/core_functions.h b/dev/core_functions.h index 35557860b..efc882214 100644 --- a/dev/core_functions.h +++ b/dev/core_functions.h @@ -53,11 +53,11 @@ namespace sqlite_orm { */ template struct lower_t : public core_function_t { - T t; + using arg_type = T; - lower_t() = default; + arg_type arg; - lower_t(T t_): t(t_) {} + lower_t(arg_type arg_): arg(std::move(arg_)) {} operator std::string() const { return "LOWER"; @@ -413,9 +413,9 @@ namespace sqlite_orm { return {t}; } - template> - Res lower(T t) { - return Res(t); + template + core_functions::lower_t lower(T t) { + return {t}; } template> diff --git a/dev/storage.h b/dev/storage.h index 7b30ddde7..8187df657 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -735,7 +735,7 @@ namespace sqlite_orm { template std::string string_from_expression(const core_functions::lower_t &a, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(a.t, noTableName, escape, ignoreBindable); + auto expr = this->string_from_expression(a.arg, noTableName, escape, ignoreBindable); ss << static_cast(a) << "(" << expr << ") "; return ss.str(); } @@ -1605,7 +1605,7 @@ namespace sqlite_orm { template std::set> parse_table_name(const core_functions::lower_t &a) { - return this->parse_table_name(a.t); + return this->parse_table_name(a.arg); } template diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index c88aac394..27d64ddf2 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -2870,11 +2870,11 @@ namespace sqlite_orm { */ template struct lower_t : public core_function_t { - T t; + using arg_type = T; - lower_t() = default; + arg_type arg; - lower_t(T t_): t(t_) {} + lower_t(arg_type arg_): arg(std::move(arg_)) {} operator std::string() const { return "LOWER"; @@ -3230,9 +3230,9 @@ namespace sqlite_orm { return {t}; } - template> - Res lower(T t) { - return Res(t); + template + core_functions::lower_t lower(T t) { + return {t}; } template> @@ -6982,6 +6982,16 @@ namespace sqlite_orm { iterate_ast(a.arg, l); } }; + + template + struct ast_iterator, void> { + using node_type = core_functions::lower_t; + + template + void operator()(const node_type &low, const L &l) const { + iterate_ast(low.arg, l); + } + }; } } @@ -7730,7 +7740,7 @@ namespace sqlite_orm { template std::string string_from_expression(const core_functions::lower_t &a, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(a.t, noTableName, escape, ignoreBindable); + auto expr = this->string_from_expression(a.arg, noTableName, escape, ignoreBindable); ss << static_cast(a) << "(" << expr << ") "; return ss.str(); } @@ -8600,7 +8610,7 @@ namespace sqlite_orm { template std::set> parse_table_name(const core_functions::lower_t &a) { - return this->parse_table_name(a.t); + return this->parse_table_name(a.arg); } template diff --git a/tests/tests.cpp b/tests/tests.cpp index 382b29bef..3e7d620b0 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -13,6 +13,15 @@ using namespace sqlite_orm; using std::cout; using std::endl; +void testLower() { + cout << __func__ << endl; + + auto storage = make_storage({}); + auto rows = storage.select(lower("OTOTO")); + assert(!rows.empty()); + assert(rows.front() == "ototo"); +} + void testLength() { cout << __func__ << endl; @@ -2834,4 +2843,6 @@ int main(int, char **) { testLength(); testAbs(); + + testLower(); } From dfba31bae53906083748aa0858482466bc693cc4 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Wed, 19 Jun 2019 21:29:28 +0300 Subject: [PATCH 120/232] fixed upper --- dev/ast_iterator.h | 10 ++++++++++ dev/core_functions.h | 12 ++++++------ dev/storage.h | 4 ++-- include/sqlite_orm/sqlite_orm.h | 26 ++++++++++++++++++-------- tests/tests.cpp | 11 +++++++++++ 5 files changed, 47 insertions(+), 16 deletions(-) diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index 863c91f0a..27931ebe2 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -269,5 +269,15 @@ namespace sqlite_orm { iterate_ast(low.arg, l); } }; + + template + struct ast_iterator, void> { + using node_type = core_functions::upper_t; + + template + void operator()(const node_type &u, const L &l) const { + iterate_ast(u.arg, l); + } + }; } } diff --git a/dev/core_functions.h b/dev/core_functions.h index efc882214..f94e2a0e8 100644 --- a/dev/core_functions.h +++ b/dev/core_functions.h @@ -69,11 +69,11 @@ namespace sqlite_orm { */ template struct upper_t : public core_function_t { - T t; + using arg_type = T; - upper_t() = default; + arg_type arg; - upper_t(T t_): t(t_) {} + upper_t(arg_type arg_): arg(std::move(arg_)) {} operator std::string() const { return "UPPER"; @@ -418,9 +418,9 @@ namespace sqlite_orm { return {t}; } - template> - Res upper(T t) { - return Res(t); + template + core_functions::upper_t upper(T t) { + return {t}; } template< diff --git a/dev/storage.h b/dev/storage.h index 8187df657..ca6909a80 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -727,7 +727,7 @@ namespace sqlite_orm { template std::string string_from_expression(const core_functions::upper_t &a, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(a.t, noTableName, escape, ignoreBindable); + auto expr = this->string_from_expression(a.arg, noTableName, escape, ignoreBindable); ss << static_cast(a) << "(" << expr << ") "; return ss.str(); } @@ -1600,7 +1600,7 @@ namespace sqlite_orm { template std::set> parse_table_name(const core_functions::upper_t &a) { - return this->parse_table_name(a.t); + return this->parse_table_name(a.arg); } template diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 27d64ddf2..55a0fd4d8 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -2886,11 +2886,11 @@ namespace sqlite_orm { */ template struct upper_t : public core_function_t { - T t; + using arg_type = T; - upper_t() = default; + arg_type arg; - upper_t(T t_): t(t_) {} + upper_t(arg_type arg_): arg(std::move(arg_)) {} operator std::string() const { return "UPPER"; @@ -3235,9 +3235,9 @@ namespace sqlite_orm { return {t}; } - template> - Res upper(T t) { - return Res(t); + template + core_functions::upper_t upper(T t) { + return {t}; } template< @@ -6992,6 +6992,16 @@ namespace sqlite_orm { iterate_ast(low.arg, l); } }; + + template + struct ast_iterator, void> { + using node_type = core_functions::upper_t; + + template + void operator()(const node_type &u, const L &l) const { + iterate_ast(u.arg, l); + } + }; } } @@ -7732,7 +7742,7 @@ namespace sqlite_orm { template std::string string_from_expression(const core_functions::upper_t &a, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(a.t, noTableName, escape, ignoreBindable); + auto expr = this->string_from_expression(a.arg, noTableName, escape, ignoreBindable); ss << static_cast(a) << "(" << expr << ") "; return ss.str(); } @@ -8605,7 +8615,7 @@ namespace sqlite_orm { template std::set> parse_table_name(const core_functions::upper_t &a) { - return this->parse_table_name(a.t); + return this->parse_table_name(a.arg); } template diff --git a/tests/tests.cpp b/tests/tests.cpp index 3e7d620b0..8dd97407e 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -13,6 +13,15 @@ using namespace sqlite_orm; using std::cout; using std::endl; +void testUpper() { + cout << __func__ << endl; + + auto storage = make_storage({}); + auto rows = storage.select(upper("ototo")); + assert(!rows.empty()); + assert(rows.front() == "OTOTO"); +} + void testLower() { cout << __func__ << endl; @@ -2845,4 +2854,6 @@ int main(int, char **) { testAbs(); testLower(); + + testUpper(); } From 42e7144f6a18c0d3956213644cdd9c0e6a08e1a4 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Wed, 19 Jun 2019 23:20:23 +0300 Subject: [PATCH 121/232] added on_open copy and unit test for it --- dev/storage.h | 2 +- include/sqlite_orm/sqlite_orm.h | 1 + tests/tests.cpp | 20 ++++++++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/dev/storage.h b/dev/storage.h index 891d4b93d..f72a70b6a 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -85,6 +85,7 @@ namespace sqlite_orm { } storage_t(const storage_t &other): + on_open(other.on_open), filename(other.filename), impl(other.impl), currentTransaction(other.currentTransaction), @@ -1261,7 +1262,6 @@ namespace sqlite_orm { statement_finalizer finalizer{stmt}; auto index = 1; auto idsTuple = std::make_tuple(std::forward(ids)...); - constexpr const auto idsCount = std::tuple_size::value; iterate_tuple(idsTuple, [stmt, &index](auto &v){ using field_type = typename std::decay::type; statement_binder().bind(stmt, index++, v); diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index a4e055c37..8aef8e3cd 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -7029,6 +7029,7 @@ namespace sqlite_orm { } storage_t(const storage_t &other): + on_open(other.on_open), filename(other.filename), impl(other.impl), currentTransaction(other.currentTransaction), diff --git a/tests/tests.cpp b/tests/tests.cpp index ff504dac3..79f98a829 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -13,6 +13,24 @@ using namespace sqlite_orm; using std::cout; using std::endl; +void testStorageCopy() { + cout << __func__ << endl; + int calledCount = 0; + + auto storage = make_storage({}); + storage.on_open = [&calledCount](sqlite3 *){ + ++calledCount; + }; + storage.on_open(nullptr); + assert(calledCount == 1); + + auto storageCopy = storage; + assert(storageCopy.on_open); + + storageCopy.on_open(nullptr); + assert(calledCount == 2); +} + void testSetNull() { cout << __func__ << endl; @@ -2857,4 +2875,6 @@ int main(int, char **) { testCompositeKeyColumnsNames(); testSetNull(); + + testStorageCopy(); } From e20ac9317c36862728ae58f100823f8987bc8383 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 20 Jun 2019 12:12:22 +0300 Subject: [PATCH 122/232] added exception throw on binding errors --- dev/statement_binder.h | 8 +- dev/storage.h | 115 +++++++++++++++++++---------- dev/view.h | 4 +- examples/enum_binding.cpp | 2 + include/sqlite_orm/sqlite_orm.h | 127 +++++++++++++++++++++----------- 5 files changed, 172 insertions(+), 84 deletions(-) diff --git a/dev/statement_binder.h b/dev/statement_binder.h index 6354c5948..45ddbbf4a 100644 --- a/dev/statement_binder.h +++ b/dev/statement_binder.h @@ -139,8 +139,8 @@ namespace sqlite_orm { using conditional_binder_base::conditional_binder_base; - void operator()(const T &t) const { - statement_binder().bind(this->stmt, this->index++, t); + int operator()(const T &t) const { + return statement_binder().bind(this->stmt, this->index++, t); } }; @@ -148,8 +148,8 @@ namespace sqlite_orm { struct conditional_binder : conditional_binder_base { using conditional_binder_base::conditional_binder_base; - void operator()(const T &t) const { - //.. + int operator()(const T &) const { + return SQLITE_OK; } }; } diff --git a/dev/storage.h b/dev/storage.h index 891d4b93d..3c71ef9e3 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -304,7 +304,7 @@ namespace sqlite_orm { }else{ auto needQuotes = std::is_base_of>::value; std::stringstream ss; - if(needQuotes && ignoreBindable){ + if(needQuotes && !ignoreBindable){ ss << "'"; } if(!ignoreBindable){ @@ -316,7 +316,7 @@ namespace sqlite_orm { }else{ ss << "? "; } - if(needQuotes && ignoreBindable){ + if(needQuotes && !ignoreBindable){ ss << "'"; } return ss.str(); @@ -381,7 +381,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(F O::*m, bool noTableName, bool escape, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(F O::*m, bool noTableName, bool /*escape*/, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!noTableName){ ss << "'" << this->impl.template find_table_name() << "'."; @@ -784,7 +784,7 @@ namespace sqlite_orm { * Takes select_t object and returns SELECT query string */ template - std::string string_from_expression(const internal::select_t &sel, bool /*noTableName*/, bool /*escape*/, bool ignoreBindable) { + std::string string_from_expression(const internal::select_t &sel, bool /*noTableName*/, bool /*escape*/, bool /*ignoreBindable*/) { std::stringstream ss; if(!is_base_of_template::value){ if(!sel.highest_level){ @@ -1216,13 +1216,16 @@ namespace sqlite_orm { this->process_conditions(ss, argsTuple); auto query = ss.str(); sqlite3_stmt *stmt; - if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { + auto db = connection->get_db(); + if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; - iterate_ast(argsTuple, [stmt, &index](auto &node){ + iterate_ast(argsTuple, [stmt, &index, db](auto &node){ using node_type = typename std::decay::type; conditional_binder> binder{stmt, index}; - binder(node); + if(SQLITE_OK != binder(node)){ + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); + } }); if (sqlite3_step(stmt) == SQLITE_DONE) { // done.. @@ -1264,7 +1267,9 @@ namespace sqlite_orm { constexpr const auto idsCount = std::tuple_size::value; iterate_tuple(idsTuple, [stmt, &index](auto &v){ using field_type = typename std::decay::type; - statement_binder().bind(stmt, index++, v); + if(SQLITE_OK != statement_binder().bind(stmt, index++, v)){ + throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + } }); if (sqlite3_step(stmt) == SQLITE_DONE) { // done.. @@ -1326,7 +1331,9 @@ namespace sqlite_orm { }else{ value = &((o).*(c.getter))(); } - statement_binder().bind(stmt, index++, *value); + if(SQLITE_OK != statement_binder().bind(stmt, index++, *value)){ + throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + } } }); impl.table.for_each_column([&o, stmt, &index] (auto &c) { @@ -1338,7 +1345,9 @@ namespace sqlite_orm { }else{ value = &((o).*(c.getter))(); } - statement_binder().bind(stmt, index++, *value); + if(SQLITE_OK != statement_binder().bind(stmt, index++, *value)){ + throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + } } }); if (sqlite3_step(stmt) == SQLITE_DONE) { @@ -1383,20 +1392,25 @@ namespace sqlite_orm { this->process_conditions(ss, whereArgsTuple); auto query = ss.str(); sqlite3_stmt *stmt; - if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { + auto db = connection->get_db(); + if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; - set.for_each([&index, stmt](auto &setArg){ - iterate_ast(setArg, [&index, stmt](auto &node){ + set.for_each([&index, stmt, db](auto &setArg){ + iterate_ast(setArg, [&index, stmt, db](auto &node){ using node_type = typename std::decay::type; conditional_binder> binder{stmt, index}; - binder(node); + if(SQLITE_OK != binder(node)){ + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); + } }); }); - iterate_ast(whereArgsTuple, [stmt, &index](auto &node){ + iterate_ast(whereArgsTuple, [stmt, &index, db](auto &node){ using node_type = typename std::decay::type; conditional_binder> binder{stmt, index}; - binder(node); + if(SQLITE_OK != binder(node)){ + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); + } }); if (sqlite3_step(stmt) == SQLITE_DONE) { // done.. @@ -1694,7 +1708,7 @@ namespace sqlite_orm { } } - std::set> parse_table_name(const aggregate_functions::count_asterisk_without_type &c) { + std::set> parse_table_name(const aggregate_functions::count_asterisk_without_type &) { return {}; } @@ -1766,13 +1780,16 @@ namespace sqlite_orm { auto argsTuple = std::make_tuple(std::forward(args)...); auto &impl = this->generate_select_asterisk(&query, argsTuple); sqlite3_stmt *stmt; - if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { + auto db = connection->get_db(); + if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; - iterate_ast(argsTuple, [stmt, &index](auto &node){ + iterate_ast(argsTuple, [stmt, &index, db](auto &node){ using node_type = typename std::decay::type; conditional_binder> binder{stmt, index}; - binder(node); + if(SQLITE_OK != binder(node)){ + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); + } }); int stepRes; do{ @@ -1849,7 +1866,9 @@ namespace sqlite_orm { constexpr const auto idsCount = std::tuple_size::value; tuple_helper::iterator()(idsTuple, [stmt, &index](auto &v){ using field_type = typename std::decay::type; - statement_binder().bind(stmt, index++, v); + if(SQLITE_OK != statement_binder().bind(stmt, index++, v)){ + throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + } }); auto stepRes = sqlite3_step(stmt); switch(stepRes){ @@ -1923,7 +1942,9 @@ namespace sqlite_orm { constexpr const auto idsCount = std::tuple_size::value; tuple_helper::iterator()(idsTuple, [stmt, &index](auto &v){ using field_type = typename std::decay::type; - statement_binder().bind(stmt, index++, v); + if(SQLITE_OK != statement_binder().bind(stmt, index++, v)){ + throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + } }); auto stepRes = sqlite3_step(stmt); switch(stepRes){ @@ -2144,13 +2165,16 @@ namespace sqlite_orm { auto query = this->string_from_expression(sel, false, false, true); auto connection = this->get_or_create_connection(); sqlite3_stmt *stmt; - if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { + auto db = connection->get_db(); + if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; - iterate_ast(sel, [stmt, &index](auto &node){ + iterate_ast(sel, [stmt, &index, db](auto &node){ using node_type = typename std::decay::type; conditional_binder> binder{stmt, index}; - binder(node); + if(SQLITE_OK != binder(node)){ + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); + } }); std::vector res; int stepRes; @@ -2224,11 +2248,15 @@ namespace sqlite_orm { using column_type = typename std::decay::type; using field_type = typename column_type::field_type; if(c.member_pointer){ - statement_binder().bind(stmt, index++, o.*c.member_pointer); + if(SQLITE_OK != statement_binder().bind(stmt, index++, o.*c.member_pointer)){ + throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + } }else{ using getter_type = typename column_type::getter_type; field_value_holder valueHolder{((o).*(c.getter))()}; - statement_binder().bind(stmt, index++, valueHolder.value); + if(SQLITE_OK != statement_binder().bind(stmt, index++, valueHolder.value)){ + throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + } } }); if (sqlite3_step(stmt) == SQLITE_DONE) { @@ -2296,11 +2324,15 @@ namespace sqlite_orm { using column_type = typename std::decay::type; using field_type = typename column_type::field_type; if(c.member_pointer){ - statement_binder().bind(stmt, index++, o.*c.member_pointer); + if(SQLITE_OK != statement_binder().bind(stmt, index++, o.*c.member_pointer)){ + throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + } }else{ using getter_type = typename column_type::getter_type; field_value_holder valueHolder{((o).*(c.getter))()}; - statement_binder().bind(stmt, index++, valueHolder.value); + if(SQLITE_OK != statement_binder().bind(stmt, index++, valueHolder.value)){ + throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + } } }); } @@ -2363,7 +2395,9 @@ namespace sqlite_orm { using column_type = typename std::decay::type; using field_type = typename column_result_t::type; const field_type *value = impl.table.template get_object_field_pointer(o, m); - statement_binder().bind(stmt, index++, *value); + if(SQLITE_OK != statement_binder().bind(stmt, index++, *value)){ + throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + } }); if (sqlite3_step(stmt) == SQLITE_DONE) { return int(sqlite3_last_insert_rowid(connection->get_db())); @@ -2432,10 +2466,11 @@ namespace sqlite_orm { } auto query = ss.str(); sqlite3_stmt *stmt; - if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { + auto db = connection->get_db(); + if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; - impl.table.for_each_column([&o, &index, &stmt, &impl, &compositeKeyColumnNames] (auto c) { + impl.table.for_each_column([&o, &index, &stmt, &impl, &compositeKeyColumnNames, db] (auto c) { if(impl.table._without_rowid || !c.template has>()){ auto it = std::find(compositeKeyColumnNames.begin(), compositeKeyColumnNames.end(), @@ -2443,11 +2478,15 @@ namespace sqlite_orm { if(it == compositeKeyColumnNames.end()){ using field_type = typename decltype(c)::field_type; if(c.member_pointer){ - statement_binder().bind(stmt, index++, o.*c.member_pointer); + if(SQLITE_OK != statement_binder().bind(stmt, index++, o.*c.member_pointer)){ + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); + } }else{ using getter_type = typename decltype(c)::getter_type; field_value_holder valueHolder{((o).*(c.getter))()}; - statement_binder().bind(stmt, index++, valueHolder.value); + if(SQLITE_OK != statement_binder().bind(stmt, index++, valueHolder.value)){ + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); + } } } } @@ -2455,10 +2494,10 @@ namespace sqlite_orm { if (sqlite3_step(stmt) == SQLITE_DONE) { res = int(sqlite3_last_insert_rowid(connection->get_db())); }else{ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } }else { - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } return res; } @@ -2530,7 +2569,9 @@ namespace sqlite_orm { }else{ value = &((o).*(c.getter))(); } - statement_binder().bind(stmt, index++, *value); + if(SQLITE_OK != statement_binder().bind(stmt, index++, *value)){ + throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + } } }); } diff --git a/dev/view.h b/dev/view.h index d7d467e6c..d9d1937ae 100644 --- a/dev/view.h +++ b/dev/view.h @@ -56,7 +56,9 @@ namespace sqlite_orm { iterate_ast(this->args, [&index, stmt](auto &node){ using node_type = typename std::decay::type; conditional_binder> binder{stmt, index}; - binder(node); + if(SQLITE_OK != binder(node)){ + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); + } }); return {stmt, *this}; }else{ diff --git a/examples/enum_binding.cpp b/examples/enum_binding.cpp index ad094da23..ba4796199 100644 --- a/examples/enum_binding.cpp +++ b/examples/enum_binding.cpp @@ -157,12 +157,14 @@ int main(int/* argc*/, char **/*argv*/) { // get all male superheros (2 expected) auto males = storage.get_all(where(c(&SuperHero::gender) == Gender::Male)); cout << "males = " << males.size() << endl; + assert(males.size() == 2); for(auto &superHero : males) { cout << storage.dump(superHero) << endl; } // get all female superheros (1 expected) auto females = storage.get_all(where(c(&SuperHero::gender) == Gender::Female)); + assert(females.size() == 1); cout << "females = " << females.size() << endl; for(auto &superHero : females) { cout << storage.dump(superHero) << endl; diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index a4e055c37..3b0967ed4 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -4062,8 +4062,8 @@ namespace sqlite_orm { using conditional_binder_base::conditional_binder_base; - void operator()(const T &t) const { - statement_binder().bind(this->stmt, this->index++, t); + int operator()(const T &t) const { + return statement_binder().bind(this->stmt, this->index++, t); } }; @@ -4071,8 +4071,8 @@ namespace sqlite_orm { struct conditional_binder : conditional_binder_base { using conditional_binder_base::conditional_binder_base; - void operator()(const T &t) const { - //.. + int operator()(const T &) const { + return SQLITE_OK; } }; } @@ -6977,7 +6977,9 @@ namespace sqlite_orm { iterate_ast(this->args, [&index, stmt](auto &node){ using node_type = typename std::decay::type; conditional_binder> binder{stmt, index}; - binder(node); + if(SQLITE_OK != binder(node)){ + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); + } }); return {stmt, *this}; }else{ @@ -7248,7 +7250,7 @@ namespace sqlite_orm { }else{ auto needQuotes = std::is_base_of>::value; std::stringstream ss; - if(needQuotes && ignoreBindable){ + if(needQuotes && !ignoreBindable){ ss << "'"; } if(!ignoreBindable){ @@ -7260,7 +7262,7 @@ namespace sqlite_orm { }else{ ss << "? "; } - if(needQuotes && ignoreBindable){ + if(needQuotes && !ignoreBindable){ ss << "'"; } return ss.str(); @@ -7325,7 +7327,7 @@ namespace sqlite_orm { } template - std::string string_from_expression(F O::*m, bool noTableName, bool escape, bool /*ignoreBindable*/ = false) { + std::string string_from_expression(F O::*m, bool noTableName, bool /*escape*/, bool /*ignoreBindable*/ = false) { std::stringstream ss; if(!noTableName){ ss << "'" << this->impl.template find_table_name() << "'."; @@ -7728,7 +7730,7 @@ namespace sqlite_orm { * Takes select_t object and returns SELECT query string */ template - std::string string_from_expression(const internal::select_t &sel, bool /*noTableName*/, bool /*escape*/, bool ignoreBindable) { + std::string string_from_expression(const internal::select_t &sel, bool /*noTableName*/, bool /*escape*/, bool /*ignoreBindable*/) { std::stringstream ss; if(!is_base_of_template::value){ if(!sel.highest_level){ @@ -8160,13 +8162,16 @@ namespace sqlite_orm { this->process_conditions(ss, argsTuple); auto query = ss.str(); sqlite3_stmt *stmt; - if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { + auto db = connection->get_db(); + if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; - iterate_ast(argsTuple, [stmt, &index](auto &node){ + iterate_ast(argsTuple, [stmt, &index, db](auto &node){ using node_type = typename std::decay::type; conditional_binder> binder{stmt, index}; - binder(node); + if(SQLITE_OK != binder(node)){ + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); + } }); if (sqlite3_step(stmt) == SQLITE_DONE) { // done.. @@ -8208,7 +8213,9 @@ namespace sqlite_orm { constexpr const auto idsCount = std::tuple_size::value; iterate_tuple(idsTuple, [stmt, &index](auto &v){ using field_type = typename std::decay::type; - statement_binder().bind(stmt, index++, v); + if(SQLITE_OK != statement_binder().bind(stmt, index++, v)){ + throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + } }); if (sqlite3_step(stmt) == SQLITE_DONE) { // done.. @@ -8270,7 +8277,9 @@ namespace sqlite_orm { }else{ value = &((o).*(c.getter))(); } - statement_binder().bind(stmt, index++, *value); + if(SQLITE_OK != statement_binder().bind(stmt, index++, *value)){ + throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + } } }); impl.table.for_each_column([&o, stmt, &index] (auto &c) { @@ -8282,7 +8291,9 @@ namespace sqlite_orm { }else{ value = &((o).*(c.getter))(); } - statement_binder().bind(stmt, index++, *value); + if(SQLITE_OK != statement_binder().bind(stmt, index++, *value)){ + throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + } } }); if (sqlite3_step(stmt) == SQLITE_DONE) { @@ -8327,20 +8338,25 @@ namespace sqlite_orm { this->process_conditions(ss, whereArgsTuple); auto query = ss.str(); sqlite3_stmt *stmt; - if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { + auto db = connection->get_db(); + if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; - set.for_each([&index, stmt](auto &setArg){ - iterate_ast(setArg, [&index, stmt](auto &node){ + set.for_each([&index, stmt, db](auto &setArg){ + iterate_ast(setArg, [&index, stmt, db](auto &node){ using node_type = typename std::decay::type; conditional_binder> binder{stmt, index}; - binder(node); + if(SQLITE_OK != binder(node)){ + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); + } }); }); - iterate_ast(whereArgsTuple, [stmt, &index](auto &node){ + iterate_ast(whereArgsTuple, [stmt, &index, db](auto &node){ using node_type = typename std::decay::type; conditional_binder> binder{stmt, index}; - binder(node); + if(SQLITE_OK != binder(node)){ + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); + } }); if (sqlite3_step(stmt) == SQLITE_DONE) { // done.. @@ -8638,7 +8654,7 @@ namespace sqlite_orm { } } - std::set> parse_table_name(const aggregate_functions::count_asterisk_without_type &c) { + std::set> parse_table_name(const aggregate_functions::count_asterisk_without_type &) { return {}; } @@ -8710,13 +8726,16 @@ namespace sqlite_orm { auto argsTuple = std::make_tuple(std::forward(args)...); auto &impl = this->generate_select_asterisk(&query, argsTuple); sqlite3_stmt *stmt; - if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { + auto db = connection->get_db(); + if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; - iterate_ast(argsTuple, [stmt, &index](auto &node){ + iterate_ast(argsTuple, [stmt, &index, db](auto &node){ using node_type = typename std::decay::type; conditional_binder> binder{stmt, index}; - binder(node); + if(SQLITE_OK != binder(node)){ + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); + } }); int stepRes; do{ @@ -8793,7 +8812,9 @@ namespace sqlite_orm { constexpr const auto idsCount = std::tuple_size::value; tuple_helper::iterator()(idsTuple, [stmt, &index](auto &v){ using field_type = typename std::decay::type; - statement_binder().bind(stmt, index++, v); + if(SQLITE_OK != statement_binder().bind(stmt, index++, v)){ + throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + } }); auto stepRes = sqlite3_step(stmt); switch(stepRes){ @@ -8867,7 +8888,9 @@ namespace sqlite_orm { constexpr const auto idsCount = std::tuple_size::value; tuple_helper::iterator()(idsTuple, [stmt, &index](auto &v){ using field_type = typename std::decay::type; - statement_binder().bind(stmt, index++, v); + if(SQLITE_OK != statement_binder().bind(stmt, index++, v)){ + throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + } }); auto stepRes = sqlite3_step(stmt); switch(stepRes){ @@ -9088,13 +9111,16 @@ namespace sqlite_orm { auto query = this->string_from_expression(sel, false, false, true); auto connection = this->get_or_create_connection(); sqlite3_stmt *stmt; - if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { + auto db = connection->get_db(); + if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; - iterate_ast(sel, [stmt, &index](auto &node){ + iterate_ast(sel, [stmt, &index, db](auto &node){ using node_type = typename std::decay::type; conditional_binder> binder{stmt, index}; - binder(node); + if(SQLITE_OK != binder(node)){ + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); + } }); std::vector res; int stepRes; @@ -9168,11 +9194,15 @@ namespace sqlite_orm { using column_type = typename std::decay::type; using field_type = typename column_type::field_type; if(c.member_pointer){ - statement_binder().bind(stmt, index++, o.*c.member_pointer); + if(SQLITE_OK != statement_binder().bind(stmt, index++, o.*c.member_pointer)){ + throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + } }else{ using getter_type = typename column_type::getter_type; field_value_holder valueHolder{((o).*(c.getter))()}; - statement_binder().bind(stmt, index++, valueHolder.value); + if(SQLITE_OK != statement_binder().bind(stmt, index++, valueHolder.value)){ + throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + } } }); if (sqlite3_step(stmt) == SQLITE_DONE) { @@ -9240,11 +9270,15 @@ namespace sqlite_orm { using column_type = typename std::decay::type; using field_type = typename column_type::field_type; if(c.member_pointer){ - statement_binder().bind(stmt, index++, o.*c.member_pointer); + if(SQLITE_OK != statement_binder().bind(stmt, index++, o.*c.member_pointer)){ + throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + } }else{ using getter_type = typename column_type::getter_type; field_value_holder valueHolder{((o).*(c.getter))()}; - statement_binder().bind(stmt, index++, valueHolder.value); + if(SQLITE_OK != statement_binder().bind(stmt, index++, valueHolder.value)){ + throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + } } }); } @@ -9307,7 +9341,9 @@ namespace sqlite_orm { using column_type = typename std::decay::type; using field_type = typename column_result_t::type; const field_type *value = impl.table.template get_object_field_pointer(o, m); - statement_binder().bind(stmt, index++, *value); + if(SQLITE_OK != statement_binder().bind(stmt, index++, *value)){ + throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + } }); if (sqlite3_step(stmt) == SQLITE_DONE) { return int(sqlite3_last_insert_rowid(connection->get_db())); @@ -9376,10 +9412,11 @@ namespace sqlite_orm { } auto query = ss.str(); sqlite3_stmt *stmt; - if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { + auto db = connection->get_db(); + if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; - impl.table.for_each_column([&o, &index, &stmt, &impl, &compositeKeyColumnNames] (auto c) { + impl.table.for_each_column([&o, &index, &stmt, &impl, &compositeKeyColumnNames, db] (auto c) { if(impl.table._without_rowid || !c.template has>()){ auto it = std::find(compositeKeyColumnNames.begin(), compositeKeyColumnNames.end(), @@ -9387,11 +9424,15 @@ namespace sqlite_orm { if(it == compositeKeyColumnNames.end()){ using field_type = typename decltype(c)::field_type; if(c.member_pointer){ - statement_binder().bind(stmt, index++, o.*c.member_pointer); + if(SQLITE_OK != statement_binder().bind(stmt, index++, o.*c.member_pointer)){ + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); + } }else{ using getter_type = typename decltype(c)::getter_type; field_value_holder valueHolder{((o).*(c.getter))()}; - statement_binder().bind(stmt, index++, valueHolder.value); + if(SQLITE_OK != statement_binder().bind(stmt, index++, valueHolder.value)){ + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); + } } } } @@ -9399,10 +9440,10 @@ namespace sqlite_orm { if (sqlite3_step(stmt) == SQLITE_DONE) { res = int(sqlite3_last_insert_rowid(connection->get_db())); }else{ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } }else { - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } return res; } @@ -9474,7 +9515,9 @@ namespace sqlite_orm { }else{ value = &((o).*(c.getter))(); } - statement_binder().bind(stmt, index++, *value); + if(SQLITE_OK != statement_binder().bind(stmt, index++, *value)){ + throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + } } }); } From 1aa682ed48f4d60cbdd47efb3cfc0e78fe215420 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 20 Jun 2019 14:49:05 +0300 Subject: [PATCH 123/232] fixed tests compilation --- dev/storage.h | 81 +++++++++++++++++--------------- dev/view.h | 2 +- include/sqlite_orm/sqlite_orm.h | 83 ++++++++++++++++++--------------- 3 files changed, 90 insertions(+), 76 deletions(-) diff --git a/dev/storage.h b/dev/storage.h index 3c71ef9e3..954b2a379 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -1260,24 +1260,24 @@ namespace sqlite_orm { } auto query = ss.str(); sqlite3_stmt *stmt; - if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { + auto db = connection->get_db(); + if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; auto idsTuple = std::make_tuple(std::forward(ids)...); - constexpr const auto idsCount = std::tuple_size::value; - iterate_tuple(idsTuple, [stmt, &index](auto &v){ + iterate_tuple(idsTuple, [stmt, &index, db](auto &v){ using field_type = typename std::decay::type; if(SQLITE_OK != statement_binder().bind(stmt, index++, v)){ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } }); if (sqlite3_step(stmt) == SQLITE_DONE) { // done.. }else{ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } }else{ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } } @@ -1319,10 +1319,11 @@ namespace sqlite_orm { } auto query = ss.str(); sqlite3_stmt *stmt; - if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { + auto db = connection->get_db(); + if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; - impl.table.for_each_column([&o, stmt, &index] (auto &c) { + impl.table.for_each_column([&o, stmt, &index, db] (auto &c) { if(!c.template has>()) { using field_type = typename std::decay::type::field_type; const field_type *value = nullptr; @@ -1332,11 +1333,11 @@ namespace sqlite_orm { value = &((o).*(c.getter))(); } if(SQLITE_OK != statement_binder().bind(stmt, index++, *value)){ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } } }); - impl.table.for_each_column([&o, stmt, &index] (auto &c) { + impl.table.for_each_column([&o, stmt, &index, db] (auto &c) { if(c.template has>()) { using field_type = typename std::decay::type::field_type; const field_type *value = nullptr; @@ -1346,7 +1347,7 @@ namespace sqlite_orm { value = &((o).*(c.getter))(); } if(SQLITE_OK != statement_binder().bind(stmt, index++, *value)){ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } } }); @@ -1859,15 +1860,16 @@ namespace sqlite_orm { } auto query = ss.str(); sqlite3_stmt *stmt; - if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { + auto db = connection->get_db(); + if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; auto idsTuple = std::make_tuple(std::forward(ids)...); constexpr const auto idsCount = std::tuple_size::value; - tuple_helper::iterator()(idsTuple, [stmt, &index](auto &v){ + tuple_helper::iterator()(idsTuple, [stmt, &index, db](auto &v){ using field_type = typename std::decay::type; if(SQLITE_OK != statement_binder().bind(stmt, index++, v)){ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } }); auto stepRes = sqlite3_step(stmt); @@ -1935,15 +1937,16 @@ namespace sqlite_orm { } auto query = ss.str(); sqlite3_stmt *stmt; - if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { + auto db = connection->get_db(); + if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; auto idsTuple = std::make_tuple(std::forward(ids)...); constexpr const auto idsCount = std::tuple_size::value; - tuple_helper::iterator()(idsTuple, [stmt, &index](auto &v){ + tuple_helper::iterator()(idsTuple, [stmt, &index, db](auto &v){ using field_type = typename std::decay::type; if(SQLITE_OK != statement_binder().bind(stmt, index++, v)){ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } }); auto stepRes = sqlite3_step(stmt); @@ -2241,21 +2244,22 @@ namespace sqlite_orm { } auto query = ss.str(); sqlite3_stmt *stmt; - if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { + auto db = connection->get_db(); + if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; - impl.table.for_each_column([&o, &index, &stmt] (auto &c) { + impl.table.for_each_column([&o, &index, &stmt, db] (auto &c) { using column_type = typename std::decay::type; using field_type = typename column_type::field_type; if(c.member_pointer){ if(SQLITE_OK != statement_binder().bind(stmt, index++, o.*c.member_pointer)){ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } }else{ using getter_type = typename column_type::getter_type; field_value_holder valueHolder{((o).*(c.getter))()}; if(SQLITE_OK != statement_binder().bind(stmt, index++, valueHolder.value)){ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } } }); @@ -2315,23 +2319,24 @@ namespace sqlite_orm { } auto query = ss.str(); sqlite3_stmt *stmt; - if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { + auto db = connection->get_db(); + if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; for(auto it = from; it != to; ++it) { auto &o = *it; - impl.table.for_each_column([&o, &index, &stmt] (auto &c) { + impl.table.for_each_column([&o, &index, &stmt, db] (auto &c) { using column_type = typename std::decay::type; using field_type = typename column_type::field_type; if(c.member_pointer){ if(SQLITE_OK != statement_binder().bind(stmt, index++, o.*c.member_pointer)){ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } }else{ using getter_type = typename column_type::getter_type; field_value_holder valueHolder{((o).*(c.getter))()}; if(SQLITE_OK != statement_binder().bind(stmt, index++, valueHolder.value)){ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } } }); @@ -2339,10 +2344,10 @@ namespace sqlite_orm { if (sqlite3_step(stmt) == SQLITE_DONE) { //.. }else{ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } }else { - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } } @@ -2388,24 +2393,25 @@ namespace sqlite_orm { } auto query = ss.str(); sqlite3_stmt *stmt; - if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { + auto db = connection->get_db(); + if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; - iterate_tuple(cols.columns, [&o, &index, &stmt, &impl] (auto &m) { + iterate_tuple(cols.columns, [&o, &index, &stmt, &impl, db] (auto &m) { using column_type = typename std::decay::type; using field_type = typename column_result_t::type; const field_type *value = impl.table.template get_object_field_pointer(o, m); if(SQLITE_OK != statement_binder().bind(stmt, index++, *value)){ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } }); if (sqlite3_step(stmt) == SQLITE_DONE) { return int(sqlite3_last_insert_rowid(connection->get_db())); }else{ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } }else { - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } } @@ -2555,12 +2561,13 @@ namespace sqlite_orm { } auto query = ss.str(); sqlite3_stmt *stmt; - if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { + auto db = connection->get_db(); + if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; for(auto it = from; it != to; ++it) { auto &o = *it; - impl.table.for_each_column([&o, &index, &stmt] (auto c) { + impl.table.for_each_column([&o, &index, &stmt, db] (auto c) { if(!c.template has>()){ typedef typename decltype(c)::field_type field_type; const field_type *value = nullptr; @@ -2570,7 +2577,7 @@ namespace sqlite_orm { value = &((o).*(c.getter))(); } if(SQLITE_OK != statement_binder().bind(stmt, index++, *value)){ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } } }); @@ -2578,10 +2585,10 @@ namespace sqlite_orm { if (sqlite3_step(stmt) == SQLITE_DONE) { //.. }else{ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } }else { - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } } diff --git a/dev/view.h b/dev/view.h index d9d1937ae..0ff81f03c 100644 --- a/dev/view.h +++ b/dev/view.h @@ -53,7 +53,7 @@ namespace sqlite_orm { auto ret = sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr); if(ret == SQLITE_OK){ auto index = 1; - iterate_ast(this->args, [&index, stmt](auto &node){ + iterate_ast(this->args, [&index, stmt, db](auto &node){ using node_type = typename std::decay::type; conditional_binder> binder{stmt, index}; if(SQLITE_OK != binder(node)){ diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 3b0967ed4..c33fa17ec 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -6974,7 +6974,7 @@ namespace sqlite_orm { auto ret = sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr); if(ret == SQLITE_OK){ auto index = 1; - iterate_ast(this->args, [&index, stmt](auto &node){ + iterate_ast(this->args, [&index, stmt, db](auto &node){ using node_type = typename std::decay::type; conditional_binder> binder{stmt, index}; if(SQLITE_OK != binder(node)){ @@ -8206,24 +8206,24 @@ namespace sqlite_orm { } auto query = ss.str(); sqlite3_stmt *stmt; - if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { + auto db = connection->get_db(); + if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; auto idsTuple = std::make_tuple(std::forward(ids)...); - constexpr const auto idsCount = std::tuple_size::value; - iterate_tuple(idsTuple, [stmt, &index](auto &v){ + iterate_tuple(idsTuple, [stmt, &index, db](auto &v){ using field_type = typename std::decay::type; if(SQLITE_OK != statement_binder().bind(stmt, index++, v)){ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } }); if (sqlite3_step(stmt) == SQLITE_DONE) { // done.. }else{ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } }else{ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } } @@ -8265,10 +8265,11 @@ namespace sqlite_orm { } auto query = ss.str(); sqlite3_stmt *stmt; - if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { + auto db = connection->get_db(); + if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; - impl.table.for_each_column([&o, stmt, &index] (auto &c) { + impl.table.for_each_column([&o, stmt, &index, db] (auto &c) { if(!c.template has>()) { using field_type = typename std::decay::type::field_type; const field_type *value = nullptr; @@ -8278,11 +8279,11 @@ namespace sqlite_orm { value = &((o).*(c.getter))(); } if(SQLITE_OK != statement_binder().bind(stmt, index++, *value)){ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } } }); - impl.table.for_each_column([&o, stmt, &index] (auto &c) { + impl.table.for_each_column([&o, stmt, &index, db] (auto &c) { if(c.template has>()) { using field_type = typename std::decay::type::field_type; const field_type *value = nullptr; @@ -8292,7 +8293,7 @@ namespace sqlite_orm { value = &((o).*(c.getter))(); } if(SQLITE_OK != statement_binder().bind(stmt, index++, *value)){ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } } }); @@ -8805,15 +8806,16 @@ namespace sqlite_orm { } auto query = ss.str(); sqlite3_stmt *stmt; - if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { + auto db = connection->get_db(); + if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; auto idsTuple = std::make_tuple(std::forward(ids)...); constexpr const auto idsCount = std::tuple_size::value; - tuple_helper::iterator()(idsTuple, [stmt, &index](auto &v){ + tuple_helper::iterator()(idsTuple, [stmt, &index, db](auto &v){ using field_type = typename std::decay::type; if(SQLITE_OK != statement_binder().bind(stmt, index++, v)){ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } }); auto stepRes = sqlite3_step(stmt); @@ -8881,15 +8883,16 @@ namespace sqlite_orm { } auto query = ss.str(); sqlite3_stmt *stmt; - if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { + auto db = connection->get_db(); + if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; auto idsTuple = std::make_tuple(std::forward(ids)...); constexpr const auto idsCount = std::tuple_size::value; - tuple_helper::iterator()(idsTuple, [stmt, &index](auto &v){ + tuple_helper::iterator()(idsTuple, [stmt, &index, db](auto &v){ using field_type = typename std::decay::type; if(SQLITE_OK != statement_binder().bind(stmt, index++, v)){ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } }); auto stepRes = sqlite3_step(stmt); @@ -9187,21 +9190,22 @@ namespace sqlite_orm { } auto query = ss.str(); sqlite3_stmt *stmt; - if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { + auto db = connection->get_db(); + if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; - impl.table.for_each_column([&o, &index, &stmt] (auto &c) { + impl.table.for_each_column([&o, &index, &stmt, db] (auto &c) { using column_type = typename std::decay::type; using field_type = typename column_type::field_type; if(c.member_pointer){ if(SQLITE_OK != statement_binder().bind(stmt, index++, o.*c.member_pointer)){ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } }else{ using getter_type = typename column_type::getter_type; field_value_holder valueHolder{((o).*(c.getter))()}; if(SQLITE_OK != statement_binder().bind(stmt, index++, valueHolder.value)){ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } } }); @@ -9261,23 +9265,24 @@ namespace sqlite_orm { } auto query = ss.str(); sqlite3_stmt *stmt; - if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { + auto db = connection->get_db(); + if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; for(auto it = from; it != to; ++it) { auto &o = *it; - impl.table.for_each_column([&o, &index, &stmt] (auto &c) { + impl.table.for_each_column([&o, &index, &stmt, db] (auto &c) { using column_type = typename std::decay::type; using field_type = typename column_type::field_type; if(c.member_pointer){ if(SQLITE_OK != statement_binder().bind(stmt, index++, o.*c.member_pointer)){ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } }else{ using getter_type = typename column_type::getter_type; field_value_holder valueHolder{((o).*(c.getter))()}; if(SQLITE_OK != statement_binder().bind(stmt, index++, valueHolder.value)){ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } } }); @@ -9285,10 +9290,10 @@ namespace sqlite_orm { if (sqlite3_step(stmt) == SQLITE_DONE) { //.. }else{ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } }else { - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } } @@ -9334,24 +9339,25 @@ namespace sqlite_orm { } auto query = ss.str(); sqlite3_stmt *stmt; - if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { + auto db = connection->get_db(); + if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; - iterate_tuple(cols.columns, [&o, &index, &stmt, &impl] (auto &m) { + iterate_tuple(cols.columns, [&o, &index, &stmt, &impl, db] (auto &m) { using column_type = typename std::decay::type; using field_type = typename column_result_t::type; const field_type *value = impl.table.template get_object_field_pointer(o, m); if(SQLITE_OK != statement_binder().bind(stmt, index++, *value)){ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } }); if (sqlite3_step(stmt) == SQLITE_DONE) { return int(sqlite3_last_insert_rowid(connection->get_db())); }else{ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } }else { - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } } @@ -9501,12 +9507,13 @@ namespace sqlite_orm { } auto query = ss.str(); sqlite3_stmt *stmt; - if (sqlite3_prepare_v2(connection->get_db(), query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { + auto db = connection->get_db(); + if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, nullptr) == SQLITE_OK) { statement_finalizer finalizer{stmt}; auto index = 1; for(auto it = from; it != to; ++it) { auto &o = *it; - impl.table.for_each_column([&o, &index, &stmt] (auto c) { + impl.table.for_each_column([&o, &index, &stmt, db] (auto c) { if(!c.template has>()){ typedef typename decltype(c)::field_type field_type; const field_type *value = nullptr; @@ -9516,7 +9523,7 @@ namespace sqlite_orm { value = &((o).*(c.getter))(); } if(SQLITE_OK != statement_binder().bind(stmt, index++, *value)){ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } } }); @@ -9524,10 +9531,10 @@ namespace sqlite_orm { if (sqlite3_step(stmt) == SQLITE_DONE) { //.. }else{ - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } }else { - throw std::system_error(std::error_code(sqlite3_errcode(connection->get_db()), get_sqlite_error_category())); + throw std::system_error(std::error_code(sqlite3_errcode(db), get_sqlite_error_category())); } } From a348f093b06fc3c015e0799063a336c0d4f49c6e Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 20 Jun 2019 15:17:18 +0300 Subject: [PATCH 124/232] added cassert include --- examples/enum_binding.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/enum_binding.cpp b/examples/enum_binding.cpp index ba4796199..ec2c65245 100644 --- a/examples/enum_binding.cpp +++ b/examples/enum_binding.cpp @@ -3,6 +3,7 @@ #include #include +#include using std::cout; using std::endl; From 27f14d1da3aeace9b7d0e00083eb669d0b16d333 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Thu, 20 Jun 2019 21:36:14 +0300 Subject: [PATCH 125/232] refactored rtrim --- dev/ast_iterator.h | 33 ++++++++- dev/core_functions.h | 71 +++++++++--------- dev/storage.h | 19 ++--- dev/table.h | 2 +- include/sqlite_orm/sqlite_orm.h | 125 +++++++++++++++++++------------- tests/tests.cpp | 33 +++++++++ 6 files changed, 181 insertions(+), 102 deletions(-) diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index b6026ae67..37c301fc6 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -83,7 +83,6 @@ namespace sqlite_orm { template void operator()(const node_type &cols, const L &l) const { - using columns_tuple = typename std::decay::type::columns_type; iterate_tuple(cols.columns, [&l](auto &col){ iterate_ast(col, l); }); @@ -301,5 +300,37 @@ namespace sqlite_orm { }); } }; + + template + struct ast_iterator, void> { + using node_type = core_functions::ltrim_single_t; + + template + void operator()(const node_type &f, const L &l) const { + iterate_ast(f.arg, l); + } + }; + + template + struct ast_iterator, void> { + using node_type = core_functions::ltrim_double_t; + + template + void operator()(const node_type &f, const L &l) const { + iterate_tuple(f.args, [&l](auto &v){ + iterate_ast(v, l); + }); + } + }; + + template + struct ast_iterator, void> { + using node_type = core_functions::rtrim_single_t; + + template + void operator()(const node_type &f, const L &l) const { + iterate_ast(f.arg, l); + } + }; } } diff --git a/dev/core_functions.h b/dev/core_functions.h index 92745f7fd..8b082d4a0 100644 --- a/dev/core_functions.h +++ b/dev/core_functions.h @@ -117,39 +117,42 @@ namespace sqlite_orm { args_type args; - trim_double_t(X &&x, Y &&y): args(x, y) {} + trim_double_t(X x, Y y): args(std::forward(x), std::forward(y)) {} + }; + + struct ltrim_string { + operator std::string() const { + return "LTRIM"; + } }; /** * LTRIM(X) function https://sqlite.org/lang_corefunc.html#ltrim */ template - struct ltrim_single_t : public core_function_t { - X x; + struct ltrim_single_t : public core_function_t, ltrim_string { + using arg_type = X; - ltrim_single_t() = default; - - ltrim_single_t(X x_): x(x_) {} + arg_type arg; - operator std::string() const { - return "LTRIM"; - } + ltrim_single_t(arg_type &&arg_): arg(std::move(arg_)) {} }; /** * LTRIM(X,Y) function https://sqlite.org/lang_corefunc.html#ltrim */ template - struct ltrim_double_t : public core_function_t { - X x; - Y y; - - ltrim_double_t() = default; + struct ltrim_double_t : public core_function_t, ltrim_string { + using args_type = std::tuple; - ltrim_double_t(X x_, Y y_): x(x_), y(y_) {} + args_type args; + ltrim_double_t(X x, Y y): args(std::forward(x), std::forward(y)) {} + }; + + struct rtrim_string { operator std::string() const { - return static_cast(ltrim_single_t(0)); + return "RTRIM"; } }; @@ -157,33 +160,25 @@ namespace sqlite_orm { * RTRIM(X) function https://sqlite.org/lang_corefunc.html#rtrim */ template - struct rtrim_single_t : public core_function_t { - X x; + struct rtrim_single_t : public core_function_t, rtrim_string { + using arg_type = X; - rtrim_single_t() = default; - - rtrim_single_t(X x_): x(x_) {} + arg_type arg; - operator std::string() const { - return "RTRIM"; - } + rtrim_single_t(arg_type &&arg_): arg(std::move(arg_)) {} }; /** * RTRIM(X,Y) function https://sqlite.org/lang_corefunc.html#rtrim */ template - struct rtrim_double_t : public core_function_t { + struct rtrim_double_t : public core_function_t, rtrim_string { X x; Y y; rtrim_double_t() = default; rtrim_double_t(X x_, Y y_): x(x_), y(y_) {} - - operator std::string() const { - return static_cast(rtrim_single_t(0)); - } }; @@ -376,19 +371,19 @@ namespace sqlite_orm { return {std::move(x), std::move(y)}; } - template> - Res ltrim(X x) { - return Res(x); + template + core_functions::ltrim_single_t ltrim(X &&x) { + return {std::move(x)}; } - template> - Res ltrim(X x, Y y) { - return Res(x, y); + template + core_functions::ltrim_double_t ltrim(X &&x, Y &&y) { + return {std::move(x), std::move(y)}; } - template> - Res rtrim(X x) { - return Res(x); + template + core_functions::rtrim_single_t rtrim(X &&x) { + return {std::move(x)}; } template> diff --git a/dev/storage.h b/dev/storage.h index 8225ef0ae..37fe08025 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -611,7 +611,7 @@ namespace sqlite_orm { template std::string string_from_expression(const core_functions::rtrim_single_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); + auto expr = this->string_from_expression(f.arg, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } @@ -619,8 +619,8 @@ namespace sqlite_orm { template std::string string_from_expression(const core_functions::ltrim_double_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); - auto expr2 = this->string_from_expression(f.y, noTableName, escape, ignoreBindable); + auto expr = this->string_from_expression(std::get<0>(f.args), noTableName, escape, ignoreBindable); + auto expr2 = this->string_from_expression(std::get<1>(f.args), noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ", " << expr2 << ") "; return ss.str(); } @@ -628,7 +628,7 @@ namespace sqlite_orm { template std::string string_from_expression(const core_functions::ltrim_single_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); + auto expr = this->string_from_expression(f.arg, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } @@ -668,7 +668,6 @@ namespace sqlite_orm { std::string string_from_expression(const core_functions::datetime_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); - using tuple_t = std::tuple; iterate_tuple(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ ss << ", " << this->string_from_expression(v, noTableName, escape, ignoreBindable); }); @@ -680,7 +679,6 @@ namespace sqlite_orm { std::string string_from_expression(const core_functions::date_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); - using tuple_t = std::tuple; iterate_tuple(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ ss << ", " << this->string_from_expression(v, noTableName, escape, ignoreBindable); }); @@ -692,7 +690,6 @@ namespace sqlite_orm { std::string string_from_expression(const core_functions::julianday_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); - using tuple_t = std::tuple; iterate_tuple(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ ss << ", " << this->string_from_expression(v, noTableName, escape, ignoreBindable); }); @@ -1580,7 +1577,7 @@ namespace sqlite_orm { template std::set> parse_table_name(const core_functions::rtrim_single_t &f) { - return this->parse_table_name(f.x); + return this->parse_table_name(f.arg); } template @@ -1593,13 +1590,13 @@ namespace sqlite_orm { template std::set> parse_table_name(const core_functions::ltrim_single_t &f) { - return this->parse_table_name(f.x); + return this->parse_table_name(f.arg); } template std::set> parse_table_name(const core_functions::ltrim_double_t &f) { - auto res = this->parse_table_name(f.x); - auto res2 = this->parse_table_name(f.y); + auto res = this->parse_table_name(std::get<0>(f.args)); + auto res2 = this->parse_table_name(std::get<1>(f.args)); res.insert(res2.begin(), res2.end()); return res; } diff --git a/dev/table.h b/dev/table.h index 795f92fff..265f51a50 100644 --- a/dev/table.h +++ b/dev/table.h @@ -59,7 +59,7 @@ namespace sqlite_orm { template const F* get_object_field_pointer(const object_type &obj, C c) { const F *res = nullptr; - this->for_each_column_with_field_type([&res, &c, &obj, this](auto &col){ + this->for_each_column_with_field_type([&res, &c, &obj](auto &col){ using namespace static_magic; using column_type = typename std::remove_reference::type; using member_pointer_t = typename column_type::member_pointer_t; diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 609a8db09..bd83131bf 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -2938,39 +2938,42 @@ namespace sqlite_orm { args_type args; - trim_double_t(X &&x, Y &&y): args(x, y) {} + trim_double_t(X x, Y y): args(std::forward(x), std::forward(y)) {} + }; + + struct ltrim_string { + operator std::string() const { + return "LTRIM"; + } }; /** * LTRIM(X) function https://sqlite.org/lang_corefunc.html#ltrim */ template - struct ltrim_single_t : public core_function_t { - X x; - - ltrim_single_t() = default; + struct ltrim_single_t : public core_function_t, ltrim_string { + using arg_type = X; - ltrim_single_t(X x_): x(x_) {} + arg_type arg; - operator std::string() const { - return "LTRIM"; - } + ltrim_single_t(arg_type &&arg_): arg(std::move(arg_)) {} }; /** * LTRIM(X,Y) function https://sqlite.org/lang_corefunc.html#ltrim */ template - struct ltrim_double_t : public core_function_t { - X x; - Y y; - - ltrim_double_t() = default; + struct ltrim_double_t : public core_function_t, ltrim_string { + using args_type = std::tuple; - ltrim_double_t(X x_, Y y_): x(x_), y(y_) {} + args_type args; + ltrim_double_t(X x, Y y): args(std::forward(x), std::forward(y)) {} + }; + + struct rtrim_string { operator std::string() const { - return static_cast(ltrim_single_t(0)); + return "RTRIM"; } }; @@ -2978,33 +2981,25 @@ namespace sqlite_orm { * RTRIM(X) function https://sqlite.org/lang_corefunc.html#rtrim */ template - struct rtrim_single_t : public core_function_t { - X x; - - rtrim_single_t() = default; + struct rtrim_single_t : public core_function_t, rtrim_string { + using arg_type = X; - rtrim_single_t(X x_): x(x_) {} + arg_type arg; - operator std::string() const { - return "RTRIM"; - } + rtrim_single_t(arg_type &&arg_): arg(std::move(arg_)) {} }; /** * RTRIM(X,Y) function https://sqlite.org/lang_corefunc.html#rtrim */ template - struct rtrim_double_t : public core_function_t { + struct rtrim_double_t : public core_function_t, rtrim_string { X x; Y y; rtrim_double_t() = default; rtrim_double_t(X x_, Y y_): x(x_), y(y_) {} - - operator std::string() const { - return static_cast(rtrim_single_t(0)); - } }; @@ -3197,19 +3192,19 @@ namespace sqlite_orm { return {std::move(x), std::move(y)}; } - template> - Res ltrim(X x) { - return Res(x); + template + core_functions::ltrim_single_t ltrim(X &&x) { + return {std::move(x)}; } - template> - Res ltrim(X x, Y y) { - return Res(x, y); + template + core_functions::ltrim_double_t ltrim(X &&x, Y &&y) { + return {std::move(x), std::move(y)}; } - template> - Res rtrim(X x) { - return Res(x); + template + core_functions::rtrim_single_t rtrim(X &&x) { + return {std::move(x)}; } template> @@ -5317,7 +5312,7 @@ namespace sqlite_orm { template const F* get_object_field_pointer(const object_type &obj, C c) { const F *res = nullptr; - this->for_each_column_with_field_type([&res, &c, &obj, this](auto &col){ + this->for_each_column_with_field_type([&res, &c, &obj](auto &col){ using namespace static_magic; using column_type = typename std::remove_reference::type; using member_pointer_t = typename column_type::member_pointer_t; @@ -6807,7 +6802,6 @@ namespace sqlite_orm { template void operator()(const node_type &cols, const L &l) const { - using columns_tuple = typename std::decay::type::columns_type; iterate_tuple(cols.columns, [&l](auto &col){ iterate_ast(col, l); }); @@ -7025,6 +7019,38 @@ namespace sqlite_orm { }); } }; + + template + struct ast_iterator, void> { + using node_type = core_functions::ltrim_single_t; + + template + void operator()(const node_type &f, const L &l) const { + iterate_ast(f.arg, l); + } + }; + + template + struct ast_iterator, void> { + using node_type = core_functions::ltrim_double_t; + + template + void operator()(const node_type &f, const L &l) const { + iterate_tuple(f.args, [&l](auto &v){ + iterate_ast(v, l); + }); + } + }; + + template + struct ast_iterator, void> { + using node_type = core_functions::rtrim_single_t; + + template + void operator()(const node_type &f, const L &l) const { + iterate_ast(f.arg, l); + } + }; } } @@ -7651,7 +7677,7 @@ namespace sqlite_orm { template std::string string_from_expression(const core_functions::rtrim_single_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); + auto expr = this->string_from_expression(f.arg, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } @@ -7659,8 +7685,8 @@ namespace sqlite_orm { template std::string string_from_expression(const core_functions::ltrim_double_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); - auto expr2 = this->string_from_expression(f.y, noTableName, escape, ignoreBindable); + auto expr = this->string_from_expression(std::get<0>(f.args), noTableName, escape, ignoreBindable); + auto expr2 = this->string_from_expression(std::get<1>(f.args), noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ", " << expr2 << ") "; return ss.str(); } @@ -7668,7 +7694,7 @@ namespace sqlite_orm { template std::string string_from_expression(const core_functions::ltrim_single_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); + auto expr = this->string_from_expression(f.arg, noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ") "; return ss.str(); } @@ -7708,7 +7734,6 @@ namespace sqlite_orm { std::string string_from_expression(const core_functions::datetime_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); - using tuple_t = std::tuple; iterate_tuple(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ ss << ", " << this->string_from_expression(v, noTableName, escape, ignoreBindable); }); @@ -7720,7 +7745,6 @@ namespace sqlite_orm { std::string string_from_expression(const core_functions::date_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); - using tuple_t = std::tuple; iterate_tuple(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ ss << ", " << this->string_from_expression(v, noTableName, escape, ignoreBindable); }); @@ -7732,7 +7756,6 @@ namespace sqlite_orm { std::string string_from_expression(const core_functions::julianday_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); - using tuple_t = std::tuple; iterate_tuple(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ ss << ", " << this->string_from_expression(v, noTableName, escape, ignoreBindable); }); @@ -8620,7 +8643,7 @@ namespace sqlite_orm { template std::set> parse_table_name(const core_functions::rtrim_single_t &f) { - return this->parse_table_name(f.x); + return this->parse_table_name(f.arg); } template @@ -8633,13 +8656,13 @@ namespace sqlite_orm { template std::set> parse_table_name(const core_functions::ltrim_single_t &f) { - return this->parse_table_name(f.x); + return this->parse_table_name(f.arg); } template std::set> parse_table_name(const core_functions::ltrim_double_t &f) { - auto res = this->parse_table_name(f.x); - auto res2 = this->parse_table_name(f.y); + auto res = this->parse_table_name(std::get<0>(f.args)); + auto res2 = this->parse_table_name(std::get<1>(f.args)); res.insert(res2.begin(), res2.end()); return res; } diff --git a/tests/tests.cpp b/tests/tests.cpp index cfe8253a2..74f653bb5 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -13,6 +13,33 @@ using namespace sqlite_orm; using std::cout; using std::endl; +void testRtrim() { + cout << __func__ << endl; + + auto storage = make_storage({}); + auto rows = storage.select(rtrim("ototo ")); + assert(rows.size() == 1); + assert(rows.front() == "ototo"); +} + +void testLtrimDouble() { + cout << __func__ << endl; + + auto storage = make_storage({}); + auto rows = storage.select(ltrim(" ototo", " ")); + assert(rows.size() == 1); + assert(rows.front() == "ototo"); +} + +void testLtrim() { + cout << __func__ << endl; + + auto storage = make_storage({}); + auto rows = storage.select(ltrim(" ototo")); + assert(rows.size() == 1); + assert(rows.front() == "ototo"); +} + void testTrimDouble() { cout << __func__ << endl; @@ -2944,4 +2971,10 @@ int main(int, char **) { testStorageCopy(); testTrimDouble(); + + testLtrim(); + + testLtrimDouble(); + + testRtrim(); } From c4c98081c479099ac3cae549a1a60710e10c4276 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Fri, 21 Jun 2019 08:42:02 +0300 Subject: [PATCH 126/232] fixed rtrim double --- dev/ast_iterator.h | 12 ++++++++++++ dev/core_functions.h | 13 ++++++------- dev/storage.h | 9 ++++----- include/sqlite_orm/sqlite_orm.h | 34 +++++++++++++++++++++------------ tests/tests.cpp | 22 ++++++--------------- 5 files changed, 50 insertions(+), 40 deletions(-) diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index 37c301fc6..f7ec9af08 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -332,5 +332,17 @@ namespace sqlite_orm { iterate_ast(f.arg, l); } }; + + template + struct ast_iterator, void> { + using node_type = core_functions::rtrim_double_t; + + template + void operator()(const node_type &f, const L &l) const { + iterate_tuple(f.args, [&l](auto &v){ + iterate_ast(v, l); + }); + } + }; } } diff --git a/dev/core_functions.h b/dev/core_functions.h index 8b082d4a0..5f7c22be3 100644 --- a/dev/core_functions.h +++ b/dev/core_functions.h @@ -173,12 +173,11 @@ namespace sqlite_orm { */ template struct rtrim_double_t : public core_function_t, rtrim_string { - X x; - Y y; + using args_type = std::tuple; - rtrim_double_t() = default; + args_type args; - rtrim_double_t(X x_, Y y_): x(x_), y(y_) {} + rtrim_double_t(X x, Y y): args(std::forward(x), std::forward(y)) {} }; @@ -386,9 +385,9 @@ namespace sqlite_orm { return {std::move(x)}; } - template> - Res rtrim(X x, Y y) { - return Res(x, y); + template + core_functions::rtrim_double_t rtrim(X &&x, Y &&y) { + return {std::move(x), std::move(y)}; } inline core_functions::changes_t changes() { diff --git a/dev/storage.h b/dev/storage.h index 37fe08025..3aceca9b7 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -602,8 +602,8 @@ namespace sqlite_orm { template std::string string_from_expression(const core_functions::rtrim_double_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); - auto expr2 = this->string_from_expression(f.y, noTableName, escape, ignoreBindable); + auto expr = this->string_from_expression(std::get<0>(f.args), noTableName, escape, ignoreBindable); + auto expr2 = this->string_from_expression(std::get<1>(f.args), noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ", " << expr2 << ") "; return ss.str(); } @@ -1582,8 +1582,8 @@ namespace sqlite_orm { template std::set> parse_table_name(const core_functions::rtrim_double_t &f) { - auto res = this->parse_table_name(f.x); - auto res2 = this->parse_table_name(f.y); + auto res = this->parse_table_name(std::get<0>(f.args)); + auto res2 = this->parse_table_name(std::get<1>(f.args)); res.insert(res2.begin(), res2.end()); return res; } @@ -2380,7 +2380,6 @@ namespace sqlite_orm { ss << "INSERT INTO '" << impl.table.name << "' "; std::vector columnNames; columnNames.reserve(colsCount); - using columns_tuple = typename std::decay::type::columns_type; iterate_tuple(cols.columns, [&columnNames, this](auto &m){ auto columnName = this->string_from_expression(m, true, false, true); if(!columnName.empty()){ diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index bd83131bf..65160fd43 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -2994,12 +2994,11 @@ namespace sqlite_orm { */ template struct rtrim_double_t : public core_function_t, rtrim_string { - X x; - Y y; + using args_type = std::tuple; - rtrim_double_t() = default; + args_type args; - rtrim_double_t(X x_, Y y_): x(x_), y(y_) {} + rtrim_double_t(X x, Y y): args(std::forward(x), std::forward(y)) {} }; @@ -3207,9 +3206,9 @@ namespace sqlite_orm { return {std::move(x)}; } - template> - Res rtrim(X x, Y y) { - return Res(x, y); + template + core_functions::rtrim_double_t rtrim(X &&x, Y &&y) { + return {std::move(x), std::move(y)}; } inline core_functions::changes_t changes() { @@ -7051,6 +7050,18 @@ namespace sqlite_orm { iterate_ast(f.arg, l); } }; + + template + struct ast_iterator, void> { + using node_type = core_functions::rtrim_double_t; + + template + void operator()(const node_type &f, const L &l) const { + iterate_tuple(f.args, [&l](auto &v){ + iterate_ast(v, l); + }); + } + }; } } @@ -7668,8 +7679,8 @@ namespace sqlite_orm { template std::string string_from_expression(const core_functions::rtrim_double_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto expr = this->string_from_expression(f.x, noTableName, escape, ignoreBindable); - auto expr2 = this->string_from_expression(f.y, noTableName, escape, ignoreBindable); + auto expr = this->string_from_expression(std::get<0>(f.args), noTableName, escape, ignoreBindable); + auto expr2 = this->string_from_expression(std::get<1>(f.args), noTableName, escape, ignoreBindable); ss << static_cast(f) << "(" << expr << ", " << expr2 << ") "; return ss.str(); } @@ -8648,8 +8659,8 @@ namespace sqlite_orm { template std::set> parse_table_name(const core_functions::rtrim_double_t &f) { - auto res = this->parse_table_name(f.x); - auto res2 = this->parse_table_name(f.y); + auto res = this->parse_table_name(std::get<0>(f.args)); + auto res2 = this->parse_table_name(std::get<1>(f.args)); res.insert(res2.begin(), res2.end()); return res; } @@ -9446,7 +9457,6 @@ namespace sqlite_orm { ss << "INSERT INTO '" << impl.table.name << "' "; std::vector columnNames; columnNames.reserve(colsCount); - using columns_tuple = typename std::decay::type::columns_type; iterate_tuple(cols.columns, [&columnNames, this](auto &m){ auto columnName = this->string_from_expression(m, true, false, true); if(!columnName.empty()){ diff --git a/tests/tests.cpp b/tests/tests.cpp index 74f653bb5..6e0f54553 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -20,13 +20,8 @@ void testRtrim() { auto rows = storage.select(rtrim("ototo ")); assert(rows.size() == 1); assert(rows.front() == "ototo"); -} - -void testLtrimDouble() { - cout << __func__ << endl; - auto storage = make_storage({}); - auto rows = storage.select(ltrim(" ototo", " ")); + rows = storage.select(rtrim("ototo ", " ")); assert(rows.size() == 1); assert(rows.front() == "ototo"); } @@ -38,13 +33,8 @@ void testLtrim() { auto rows = storage.select(ltrim(" ototo")); assert(rows.size() == 1); assert(rows.front() == "ototo"); -} - -void testTrimDouble() { - cout << __func__ << endl; - auto storage = make_storage({}); - auto rows = storage.select(trim(" ototo ", " ")); + rows = storage.select(ltrim(" ototo", " ")); assert(rows.size() == 1); assert(rows.front() == "ototo"); } @@ -56,6 +46,10 @@ void testTrim() { auto rows = storage.select(trim(" ototo ")); assert(rows.size() == 1); assert(rows.front() == "ototo"); + + rows = storage.select(trim(" ototo ", " ")); + assert(rows.size() == 1); + assert(rows.front() == "ototo"); } void testUpper() { @@ -2970,11 +2964,7 @@ int main(int, char **) { testStorageCopy(); - testTrimDouble(); - testLtrim(); - testLtrimDouble(); - testRtrim(); } From 3259f7d08b75e86ca45dd5cecd7fc84affe59dc8 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Fri, 21 Jun 2019 13:01:13 +0300 Subject: [PATCH 127/232] refactored char --- dev/ast_iterator.h | 15 +++++++++++++++ dev/core_functions.h | 16 ++++++++-------- dev/storage.h | 1 - include/sqlite_orm/sqlite_orm.h | 32 +++++++++++++++++++++++--------- tests/tests.cpp | 14 ++++++++++++++ 5 files changed, 60 insertions(+), 18 deletions(-) diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index f7ec9af08..ca6cdf6f2 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -344,5 +344,20 @@ namespace sqlite_orm { }); } }; + +#if SQLITE_VERSION_NUMBER >= 3007016 + template + struct ast_iterator, void> { + using node_type = core_functions::char_t_; + + template + void operator()(const node_type &f, const L &l) const { + iterate_tuple(f.args, [&l](auto &v){ + iterate_ast(v, l); + }); + } + }; + +#endif } } diff --git a/dev/core_functions.h b/dev/core_functions.h index 5f7c22be3..2a7250b05 100644 --- a/dev/core_functions.h +++ b/dev/core_functions.h @@ -184,22 +184,22 @@ namespace sqlite_orm { #if SQLITE_VERSION_NUMBER >= 3007016 + struct char_string { + operator std::string() const { + return "CHAR"; + } + }; + /** * CHAR(X1,X2,...,XN) function https://sqlite.org/lang_corefunc.html#char */ template - struct char_t_ : public core_function_t { + struct char_t_ : public core_function_t, char_string { using args_type = std::tuple; args_type args; - char_t_() = default; - - char_t_(args_type args_): args(args_) {} - - operator std::string() const { - return "CHAR"; - } + char_t_(args_type &&args_): args(std::move(args_)) {} }; struct random_t : core_function_t, internal::arithmetic_t { diff --git a/dev/storage.h b/dev/storage.h index 3aceca9b7..3936f7677 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -1758,7 +1758,6 @@ namespace sqlite_orm { template std::set> parse_table_names(const internal::columns_t &cols) { std::set> res; - using columns_tuple = typename std::decay::type::columns_type; iterate_tuple(cols.columns, [&res, this](auto &m){ auto tableName = this->parse_table_name(m); res.insert(tableName.begin(), tableName.end()); diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 65160fd43..098242f6c 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -3005,22 +3005,22 @@ namespace sqlite_orm { #if SQLITE_VERSION_NUMBER >= 3007016 + struct char_string { + operator std::string() const { + return "CHAR"; + } + }; + /** * CHAR(X1,X2,...,XN) function https://sqlite.org/lang_corefunc.html#char */ template - struct char_t_ : public core_function_t { + struct char_t_ : public core_function_t, char_string { using args_type = std::tuple; args_type args; - char_t_() = default; - - char_t_(args_type args_): args(args_) {} - - operator std::string() const { - return "CHAR"; - } + char_t_(args_type &&args_): args(std::move(args_)) {} }; struct random_t : core_function_t, internal::arithmetic_t { @@ -7062,6 +7062,21 @@ namespace sqlite_orm { }); } }; + +#if SQLITE_VERSION_NUMBER >= 3007016 + template + struct ast_iterator, void> { + using node_type = core_functions::char_t_; + + template + void operator()(const node_type &f, const L &l) const { + iterate_tuple(f.args, [&l](auto &v){ + iterate_ast(v, l); + }); + } + }; + +#endif } } @@ -8835,7 +8850,6 @@ namespace sqlite_orm { template std::set> parse_table_names(const internal::columns_t &cols) { std::set> res; - using columns_tuple = typename std::decay::type::columns_type; iterate_tuple(cols.columns, [&res, this](auto &m){ auto tableName = this->parse_table_name(m); res.insert(tableName.begin(), tableName.end()); diff --git a/tests/tests.cpp b/tests/tests.cpp index 6e0f54553..a9c2dd9ef 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -13,6 +13,17 @@ using namespace sqlite_orm; using std::cout; using std::endl; +#if SQLITE_VERSION_NUMBER >= 3007016 +void testChar() { + cout << __func__ << endl; + + auto storage = make_storage({}); + auto rows = storage.select(char_(67,72,65,82)); + assert(rows.size() == 1); + assert(rows.front() == "CHAR"); +} +#endif + void testRtrim() { cout << __func__ << endl; @@ -2967,4 +2978,7 @@ int main(int, char **) { testLtrim(); testRtrim(); +#if SQLITE_VERSION_NUMBER >= 3007016 + testChar(); +#endif } From 378f5681c183d2049c5ed45ce305c1264d481e59 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Fri, 21 Jun 2019 19:06:59 +0300 Subject: [PATCH 128/232] refactored date function --- dev/ast_iterator.h | 13 +++++- dev/core_functions.h | 38 +++++++++-------- dev/storage.h | 23 ++++++---- include/sqlite_orm/sqlite_orm.h | 74 +++++++++++++++++++++------------ tests/tests.cpp | 12 ++++++ 5 files changed, 108 insertions(+), 52 deletions(-) diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index ca6cdf6f2..a4c384cb7 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -357,7 +357,18 @@ namespace sqlite_orm { }); } }; - #endif + + template + struct ast_iterator, void> { + using node_type = core_functions::date_t; + + template + void operator()(const node_type &f, const L &l) const { + iterate_tuple(f.args, [&l](auto &v){ + iterate_ast(v, l); + }); + } + }; } } diff --git a/dev/core_functions.h b/dev/core_functions.h index 2a7250b05..e74a2f9e6 100644 --- a/dev/core_functions.h +++ b/dev/core_functions.h @@ -211,34 +211,37 @@ namespace sqlite_orm { #endif + struct coalesce_string { + operator std::string() const { + return "COALESCE"; + } + }; + template - struct coalesce_t : core_function_t { + struct coalesce_t : core_function_t, coalesce_string { using return_type = R; using args_type = std::tuple; args_type args; coalesce_t(args_type args_) : args(std::move(args_)) {} - + }; + + struct date_string { operator std::string() const { - return "COALESCE"; + return "DATE"; } }; - template - struct date_t : core_function_t { - using modifiers_type = std::tuple; - - T timestring; - modifiers_type modifiers; + template + struct date_t : core_function_t, date_string { + using args_type = std::tuple; - date_t() = default; + static constexpr const size_t args_size = std::tuple_size::value; - date_t(T timestring_, modifiers_type modifiers_): timestring(timestring_), modifiers(modifiers_) {} + args_type args; - operator std::string() const { - return "DATE"; - } + date_t(args_type &&args_): args(std::move(args_)) {} }; template @@ -330,9 +333,10 @@ namespace sqlite_orm { return {}; } - template> - Res date(T timestring, Args ...modifiers) { - return Res(timestring, std::make_tuple(std::forward(modifiers)...)); + template + core_functions::date_t date(Args &&...args) { + std::tuple t{std::forward(args)...}; + return {std::move(t)}; } template> diff --git a/dev/storage.h b/dev/storage.h index 3936f7677..193e65dfa 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -675,13 +675,21 @@ namespace sqlite_orm { return ss.str(); } - template - std::string string_from_expression(const core_functions::date_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { + template + std::string string_from_expression(const core_functions::date_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); - iterate_tuple(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ - ss << ", " << this->string_from_expression(v, noTableName, escape, ignoreBindable); + ss << static_cast(f) << "("; + std::vector argStrings; + argStrings.reserve(f.args_size); + iterate_tuple(f.args, [this, noTableName, escape, ignoreBindable, &argStrings](auto &v){ + argStrings.push_back(this->string_from_expression(v, noTableName, escape, ignoreBindable)); }); + for(size_t i = 0; i < argStrings.size(); ++i){ + ss << argStrings[i]; + if(i < argStrings.size() - 1){ + ss << ", "; + } + } ss << ") "; return ss.str(); } @@ -1542,9 +1550,8 @@ namespace sqlite_orm { template std::set> parse_table_name(const core_functions::date_t &f) { - auto res = this->parse_table_name(f.timestring); - using tuple_t = decltype(f.modifiers); - iterate_tuple(f.modifiers, [&res, this](auto &v){ + std::set> res; + iterate_tuple(f.args, [&res, this](auto &v){ auto tableNames = this->parse_table_name(v); res.insert(tableNames.begin(), tableNames.end()); }); diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 098242f6c..eb8d388ad 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -3032,34 +3032,37 @@ namespace sqlite_orm { #endif + struct coalesce_string { + operator std::string() const { + return "COALESCE"; + } + }; + template - struct coalesce_t : core_function_t { + struct coalesce_t : core_function_t, coalesce_string { using return_type = R; using args_type = std::tuple; args_type args; coalesce_t(args_type args_) : args(std::move(args_)) {} - + }; + + struct date_string { operator std::string() const { - return "COALESCE"; + return "DATE"; } }; - template - struct date_t : core_function_t { - using modifiers_type = std::tuple; - - T timestring; - modifiers_type modifiers; + template + struct date_t : core_function_t, date_string { + using args_type = std::tuple; - date_t() = default; + static constexpr const size_t args_size = std::tuple_size::value; - date_t(T timestring_, modifiers_type modifiers_): timestring(timestring_), modifiers(modifiers_) {} + args_type args; - operator std::string() const { - return "DATE"; - } + date_t(args_type &&args_): args(std::move(args_)) {} }; template @@ -3151,9 +3154,10 @@ namespace sqlite_orm { return {}; } - template> - Res date(T timestring, Args ...modifiers) { - return Res(timestring, std::make_tuple(std::forward(modifiers)...)); + template + core_functions::date_t date(Args &&...args) { + std::tuple t{std::forward(args)...}; + return {std::move(t)}; } template> @@ -7075,8 +7079,19 @@ namespace sqlite_orm { }); } }; - #endif + + template + struct ast_iterator, void> { + using node_type = core_functions::date_t; + + template + void operator()(const node_type &f, const L &l) const { + iterate_tuple(f.args, [&l](auto &v){ + iterate_ast(v, l); + }); + } + }; } } @@ -7767,13 +7782,21 @@ namespace sqlite_orm { return ss.str(); } - template - std::string string_from_expression(const core_functions::date_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { + template + std::string string_from_expression(const core_functions::date_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); - iterate_tuple(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ - ss << ", " << this->string_from_expression(v, noTableName, escape, ignoreBindable); + ss << static_cast(f) << "("; + std::vector argStrings; + argStrings.reserve(f.args_size); + iterate_tuple(f.args, [this, noTableName, escape, ignoreBindable, &argStrings](auto &v){ + argStrings.push_back(this->string_from_expression(v, noTableName, escape, ignoreBindable)); }); + for(size_t i = 0; i < argStrings.size(); ++i){ + ss << argStrings[i]; + if(i < argStrings.size() - 1){ + ss << ", "; + } + } ss << ") "; return ss.str(); } @@ -8634,9 +8657,8 @@ namespace sqlite_orm { template std::set> parse_table_name(const core_functions::date_t &f) { - auto res = this->parse_table_name(f.timestring); - using tuple_t = decltype(f.modifiers); - iterate_tuple(f.modifiers, [&res, this](auto &v){ + std::set> res; + iterate_tuple(f.args, [&res, this](auto &v){ auto tableNames = this->parse_table_name(v); res.insert(tableNames.begin(), tableNames.end()); }); diff --git a/tests/tests.cpp b/tests/tests.cpp index a9c2dd9ef..9091ed0d6 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -13,6 +13,16 @@ using namespace sqlite_orm; using std::cout; using std::endl; +void testDate() { + cout << __func__ << endl; + + auto storage = make_storage({}); + auto rows = storage.select(date("now", "start of month", "+1 month", "-1 day")); + assert(rows.size() == 1); + assert(!rows.front().empty()); + +} + #if SQLITE_VERSION_NUMBER >= 3007016 void testChar() { cout << __func__ << endl; @@ -2981,4 +2991,6 @@ int main(int, char **) { #if SQLITE_VERSION_NUMBER >= 3007016 testChar(); #endif + + testDate(); } From 6eee877d18676c23f61c958eeccef545db14906f Mon Sep 17 00:00:00 2001 From: fnc12 Date: Fri, 21 Jun 2019 19:17:07 +0300 Subject: [PATCH 129/232] refactored datetime function --- dev/ast_iterator.h | 12 +++++++ dev/core_functions.h | 30 ++++++++-------- dev/storage.h | 20 +++++++---- include/sqlite_orm/sqlite_orm.h | 62 ++++++++++++++++++++++----------- tests/tests.cpp | 11 ++++++ 5 files changed, 93 insertions(+), 42 deletions(-) diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index a4c384cb7..58af112cc 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -370,5 +370,17 @@ namespace sqlite_orm { }); } }; + + template + struct ast_iterator, void> { + using node_type = core_functions::datetime_t; + + template + void operator()(const node_type &f, const L &l) const { + iterate_tuple(f.args, [&l](auto &v){ + iterate_ast(v, l); + }); + } + }; } } diff --git a/dev/core_functions.h b/dev/core_functions.h index e74a2f9e6..8ee0509ab 100644 --- a/dev/core_functions.h +++ b/dev/core_functions.h @@ -244,22 +244,23 @@ namespace sqlite_orm { date_t(args_type &&args_): args(std::move(args_)) {} }; - template - struct datetime_t : core_function_t { - using modifiers_type = std::tuple; - - T timestring; - modifiers_type modifiers; - - datetime_t() = default; - - datetime_t(T timestring_, modifiers_type modifiers_): timestring(timestring_), modifiers(modifiers_) {} - + struct datetime_string { operator std::string() const { return "DATETIME"; } }; + template + struct datetime_t : core_function_t, datetime_string { + using args_type = std::tuple; + + static constexpr const size_t args_size = std::tuple_size::value; + + args_type args; + + datetime_t(args_type &&args_): args(std::move(args_)) {} + }; + template struct julianday_t : core_function_t, internal::arithmetic_t { using modifiers_type = std::tuple; @@ -339,9 +340,10 @@ namespace sqlite_orm { return {std::move(t)}; } - template> - Res datetime(T timestring, Args ...modifiers) { - return Res(timestring, std::make_tuple(std::forward(modifiers)...)); + template + core_functions::datetime_t datetime(Args &&...args) { + std::tuple t{std::forward(args)...}; + return {std::move(t)}; } template> diff --git a/dev/storage.h b/dev/storage.h index 193e65dfa..e10efda45 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -667,10 +667,18 @@ namespace sqlite_orm { template std::string string_from_expression(const core_functions::datetime_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); - iterate_tuple(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ - ss << ", " << this->string_from_expression(v, noTableName, escape, ignoreBindable); + ss << static_cast(f) << "("; + std::vector argStrings; + argStrings.reserve(f.args_size); + iterate_tuple(f.args, [this, noTableName, escape, ignoreBindable, &argStrings](auto &v){ + argStrings.push_back(this->string_from_expression(v, noTableName, escape, ignoreBindable)); }); + for(size_t i = 0; i < argStrings.size(); ++i){ + ss << argStrings[i]; + if(i < argStrings.size() - 1){ + ss << ", "; + } + } ss << ") "; return ss.str(); } @@ -1140,7 +1148,6 @@ namespace sqlite_orm { template void process_conditions(std::stringstream &ss, const std::tuple &args) { - using argsType = typename std::decay::type; iterate_tuple(args, [this, &ss](auto &v){ this->process_single_condition(ss, v); }); @@ -1560,9 +1567,8 @@ namespace sqlite_orm { template std::set> parse_table_name(const core_functions::datetime_t &f) { - auto res = this->parse_table_name(f.timestring); - using tuple_t = decltype(f.modifiers); - iterate_tuple(f.modifiers, [&res, this](auto &v){ + std::set> res; + iterate_tuple(f.args, [&res, this](auto &v){ auto tableNames = this->parse_table_name(v); res.insert(tableNames.begin(), tableNames.end()); }); diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index eb8d388ad..34468e3d0 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -3065,22 +3065,23 @@ namespace sqlite_orm { date_t(args_type &&args_): args(std::move(args_)) {} }; - template - struct datetime_t : core_function_t { - using modifiers_type = std::tuple; - - T timestring; - modifiers_type modifiers; - - datetime_t() = default; - - datetime_t(T timestring_, modifiers_type modifiers_): timestring(timestring_), modifiers(modifiers_) {} - + struct datetime_string { operator std::string() const { return "DATETIME"; } }; + template + struct datetime_t : core_function_t, datetime_string { + using args_type = std::tuple; + + static constexpr const size_t args_size = std::tuple_size::value; + + args_type args; + + datetime_t(args_type &&args_): args(std::move(args_)) {} + }; + template struct julianday_t : core_function_t, internal::arithmetic_t { using modifiers_type = std::tuple; @@ -3160,9 +3161,10 @@ namespace sqlite_orm { return {std::move(t)}; } - template> - Res datetime(T timestring, Args ...modifiers) { - return Res(timestring, std::make_tuple(std::forward(modifiers)...)); + template + core_functions::datetime_t datetime(Args &&...args) { + std::tuple t{std::forward(args)...}; + return {std::move(t)}; } template> @@ -7092,6 +7094,18 @@ namespace sqlite_orm { }); } }; + + template + struct ast_iterator, void> { + using node_type = core_functions::datetime_t; + + template + void operator()(const node_type &f, const L &l) const { + iterate_tuple(f.args, [&l](auto &v){ + iterate_ast(v, l); + }); + } + }; } } @@ -7774,10 +7788,18 @@ namespace sqlite_orm { template std::string string_from_expression(const core_functions::datetime_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); - iterate_tuple(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ - ss << ", " << this->string_from_expression(v, noTableName, escape, ignoreBindable); + ss << static_cast(f) << "("; + std::vector argStrings; + argStrings.reserve(f.args_size); + iterate_tuple(f.args, [this, noTableName, escape, ignoreBindable, &argStrings](auto &v){ + argStrings.push_back(this->string_from_expression(v, noTableName, escape, ignoreBindable)); }); + for(size_t i = 0; i < argStrings.size(); ++i){ + ss << argStrings[i]; + if(i < argStrings.size() - 1){ + ss << ", "; + } + } ss << ") "; return ss.str(); } @@ -8247,7 +8269,6 @@ namespace sqlite_orm { template void process_conditions(std::stringstream &ss, const std::tuple &args) { - using argsType = typename std::decay::type; iterate_tuple(args, [this, &ss](auto &v){ this->process_single_condition(ss, v); }); @@ -8667,9 +8688,8 @@ namespace sqlite_orm { template std::set> parse_table_name(const core_functions::datetime_t &f) { - auto res = this->parse_table_name(f.timestring); - using tuple_t = decltype(f.modifiers); - iterate_tuple(f.modifiers, [&res, this](auto &v){ + std::set> res; + iterate_tuple(f.args, [&res, this](auto &v){ auto tableNames = this->parse_table_name(v); res.insert(tableNames.begin(), tableNames.end()); }); diff --git a/tests/tests.cpp b/tests/tests.cpp index 9091ed0d6..01561d966 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -13,6 +13,15 @@ using namespace sqlite_orm; using std::cout; using std::endl; +void testDatetime() { + cout << __func__ << endl; + + auto storage = make_storage({}); + auto rows = storage.select(datetime("now")); + assert(rows.size() == 1); + assert(!rows.front().empty()); +} + void testDate() { cout << __func__ << endl; @@ -2993,4 +3002,6 @@ int main(int, char **) { #endif testDate(); + + testDatetime(); } From c5f5d3b0c8e026fcb9ed0e426bd8fc6b1ed7f5dd Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sat, 22 Jun 2019 14:01:01 +0300 Subject: [PATCH 130/232] refactored julianday --- dev/ast_iterator.h | 12 +++++++ dev/core_functions.h | 30 +++++++++-------- dev/storage.h | 16 ++++++--- include/sqlite_orm/sqlite_orm.h | 57 ++++++++++++++++++++++----------- tests/tests.cpp | 11 +++++++ 5 files changed, 89 insertions(+), 37 deletions(-) diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index 58af112cc..d9d3e46dc 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -382,5 +382,17 @@ namespace sqlite_orm { }); } }; + + template + struct ast_iterator, void> { + using node_type = core_functions::julianday_t; + + template + void operator()(const node_type &f, const L &l) const { + iterate_tuple(f.args, [&l](auto &v){ + iterate_ast(v, l); + }); + } + }; } } diff --git a/dev/core_functions.h b/dev/core_functions.h index 8ee0509ab..c6f1ab8f8 100644 --- a/dev/core_functions.h +++ b/dev/core_functions.h @@ -261,21 +261,22 @@ namespace sqlite_orm { datetime_t(args_type &&args_): args(std::move(args_)) {} }; - template - struct julianday_t : core_function_t, internal::arithmetic_t { - using modifiers_type = std::tuple; - - T timestring; - modifiers_type modifiers; - - julianday_t() = default; - - julianday_t(T timestring_, modifiers_type modifiers_): timestring(timestring_), modifiers(modifiers_) {} - + struct julianday_string { operator std::string() const { return "JULIANDAY"; } }; + + template + struct julianday_t : core_function_t, internal::arithmetic_t, julianday_string { + using args_type = std::tuple; + + static constexpr const size_t args_size = std::tuple_size::value; + + args_type args; + + julianday_t(args_type &&args_): args(std::move(args_)) {} + }; } /** @@ -346,9 +347,10 @@ namespace sqlite_orm { return {std::move(t)}; } - template> - Res julianday(T timestring, Args ...modifiers) { - return Res(timestring, std::make_tuple(std::forward(modifiers)...)); + template + core_functions::julianday_t julianday(Args &&...args) { + std::tuple t{std::forward(args)...}; + return {std::move(t)}; } #if SQLITE_VERSION_NUMBER >= 3007016 diff --git a/dev/storage.h b/dev/storage.h index e10efda45..3bf8d7215 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -705,10 +705,18 @@ namespace sqlite_orm { template std::string string_from_expression(const core_functions::julianday_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); - iterate_tuple(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ - ss << ", " << this->string_from_expression(v, noTableName, escape, ignoreBindable); + ss << static_cast(f) << "("; + std::vector argStrings; + argStrings.reserve(f.args_size); + iterate_tuple(f.args, [this, noTableName, escape, ignoreBindable, &argStrings](auto &v){ + argStrings.push_back(this->string_from_expression(v, noTableName, escape, ignoreBindable)); }); + for(size_t i = 0; i < argStrings.size(); ++i){ + ss << argStrings[i]; + if(i < argStrings.size() - 1){ + ss << ", "; + } + } ss << ") "; return ss.str(); } @@ -802,7 +810,6 @@ namespace sqlite_orm { std::vector get_column_names(const internal::columns_t &cols) { std::vector columnNames; columnNames.reserve(static_cast(cols.count)); - using columns_tuple = typename std::decay::type::columns_type; iterate_tuple(cols.columns, [&columnNames, this](auto &m){ auto columnName = this->string_from_expression(m, false, false, true); if(columnName.length()){ @@ -861,7 +868,6 @@ namespace sqlite_orm { ss << " "; } } - using tuple_t = typename std::decay::type::conditions_type; iterate_tuple(sel.conditions, [&ss, this](auto &v){ this->process_single_condition(ss, v); }); diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 34468e3d0..1608a8472 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -3082,21 +3082,22 @@ namespace sqlite_orm { datetime_t(args_type &&args_): args(std::move(args_)) {} }; - template - struct julianday_t : core_function_t, internal::arithmetic_t { - using modifiers_type = std::tuple; - - T timestring; - modifiers_type modifiers; - - julianday_t() = default; - - julianday_t(T timestring_, modifiers_type modifiers_): timestring(timestring_), modifiers(modifiers_) {} - + struct julianday_string { operator std::string() const { return "JULIANDAY"; } }; + + template + struct julianday_t : core_function_t, internal::arithmetic_t, julianday_string { + using args_type = std::tuple; + + static constexpr const size_t args_size = std::tuple_size::value; + + args_type args; + + julianday_t(args_type &&args_): args(std::move(args_)) {} + }; } /** @@ -3167,9 +3168,10 @@ namespace sqlite_orm { return {std::move(t)}; } - template> - Res julianday(T timestring, Args ...modifiers) { - return Res(timestring, std::make_tuple(std::forward(modifiers)...)); + template + core_functions::julianday_t julianday(Args &&...args) { + std::tuple t{std::forward(args)...}; + return {std::move(t)}; } #if SQLITE_VERSION_NUMBER >= 3007016 @@ -7106,6 +7108,18 @@ namespace sqlite_orm { }); } }; + + template + struct ast_iterator, void> { + using node_type = core_functions::julianday_t; + + template + void operator()(const node_type &f, const L &l) const { + iterate_tuple(f.args, [&l](auto &v){ + iterate_ast(v, l); + }); + } + }; } } @@ -7826,10 +7840,18 @@ namespace sqlite_orm { template std::string string_from_expression(const core_functions::julianday_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - ss << static_cast(f) << "(" << this->string_from_expression(f.timestring, noTableName, escape, ignoreBindable); - iterate_tuple(f.modifiers, [&ss, this, noTableName, escape, ignoreBindable](auto &v){ - ss << ", " << this->string_from_expression(v, noTableName, escape, ignoreBindable); + ss << static_cast(f) << "("; + std::vector argStrings; + argStrings.reserve(f.args_size); + iterate_tuple(f.args, [this, noTableName, escape, ignoreBindable, &argStrings](auto &v){ + argStrings.push_back(this->string_from_expression(v, noTableName, escape, ignoreBindable)); }); + for(size_t i = 0; i < argStrings.size(); ++i){ + ss << argStrings[i]; + if(i < argStrings.size() - 1){ + ss << ", "; + } + } ss << ") "; return ss.str(); } @@ -7982,7 +8004,6 @@ namespace sqlite_orm { ss << " "; } } - using tuple_t = typename std::decay::type::conditions_type; iterate_tuple(sel.conditions, [&ss, this](auto &v){ this->process_single_condition(ss, v); }); diff --git a/tests/tests.cpp b/tests/tests.cpp index 01561d966..5a910b2f6 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -13,6 +13,15 @@ using namespace sqlite_orm; using std::cout; using std::endl; +void testJulianday() { + cout << __func__ << endl; + + auto storage = make_storage({}); + auto rows = storage.select(julianday("2016-10-18")); + assert(rows.size() == 1); + assert(rows.front() == 2457679.5); +} + void testDatetime() { cout << __func__ << endl; @@ -3004,4 +3013,6 @@ int main(int, char **) { testDate(); testDatetime(); + + testJulianday(); } From 5eafd3720fef9d96b150108a29c7fbcbd5561cc0 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sat, 22 Jun 2019 14:17:56 +0300 Subject: [PATCH 131/232] refactored julianday --- dev/storage.h | 14 ++++++++++++-- include/sqlite_orm/sqlite_orm.h | 15 ++++++++++++--- tests/tests.cpp | 29 +++++++++++++++++++++++++---- 3 files changed, 49 insertions(+), 9 deletions(-) diff --git a/dev/storage.h b/dev/storage.h index 3bf8d7215..83bceea9b 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -1561,6 +1561,16 @@ namespace sqlite_orm { return this->parse_table_name(len.arg); } + template + std::set> parse_table_name(const core_functions::julianday_t &f) { + std::set> res; + iterate_tuple(f.args, [&res, this](auto &v){ + auto tableNames = this->parse_table_name(v); + res.insert(tableNames.begin(), tableNames.end()); + }); + return res; + } + template std::set> parse_table_name(const core_functions::date_t &f) { std::set> res; @@ -1762,12 +1772,12 @@ namespace sqlite_orm { } template - std::set> parse_table_names(Args...) { + std::set> parse_table_names(Args &&...) { return {}; } template - std::set> parse_table_names(H h, Args&& ...args) { + std::set> parse_table_names(H h, Args &&...args) { auto res = this->parse_table_names(std::forward(args)...); auto tableName = this->parse_table_name(h); res.insert(tableName.begin(), tableName.end()); diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 1608a8472..1994f381c 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -7945,7 +7945,6 @@ namespace sqlite_orm { std::vector get_column_names(const internal::columns_t &cols) { std::vector columnNames; columnNames.reserve(static_cast(cols.count)); - using columns_tuple = typename std::decay::type::columns_type; iterate_tuple(cols.columns, [&columnNames, this](auto &m){ auto columnName = this->string_from_expression(m, false, false, true); if(columnName.length()){ @@ -8697,6 +8696,16 @@ namespace sqlite_orm { return this->parse_table_name(len.arg); } + template + std::set> parse_table_name(const core_functions::julianday_t &f) { + std::set> res; + iterate_tuple(f.args, [&res, this](auto &v){ + auto tableNames = this->parse_table_name(v); + res.insert(tableNames.begin(), tableNames.end()); + }); + return res; + } + template std::set> parse_table_name(const core_functions::date_t &f) { std::set> res; @@ -8898,12 +8907,12 @@ namespace sqlite_orm { } template - std::set> parse_table_names(Args...) { + std::set> parse_table_names(Args &&...) { return {}; } template - std::set> parse_table_names(H h, Args&& ...args) { + std::set> parse_table_names(H h, Args &&...args) { auto res = this->parse_table_names(std::forward(args)...); auto tableName = this->parse_table_name(h); res.insert(tableName.begin(), tableName.end()); diff --git a/tests/tests.cpp b/tests/tests.cpp index 5a910b2f6..c2de781ab 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -16,10 +16,31 @@ using std::endl; void testJulianday() { cout << __func__ << endl; - auto storage = make_storage({}); - auto rows = storage.select(julianday("2016-10-18")); - assert(rows.size() == 1); - assert(rows.front() == 2457679.5); + struct Test { + std::string text; + }; + + auto storage = make_storage({}, + make_table("test", + make_column("text", &Test::text))); + storage.sync_schema(); + auto singleTestCase = [&storage](const std::string &arg, double expected){ + { + auto rows = storage.select(julianday(arg)); + assert(rows.size() == 1); + assert((rows.front() - expected) < 0.001); // too much precision + } + { + storage.insert(Test{arg}); + auto rows = storage.select(julianday(&Test::text)); + assert(rows.size() == 1); + assert((rows.front() - expected) < 0.001); + storage.remove_all(); + } + }; + singleTestCase("2016-10-18", 2457679.5); + singleTestCase("2016-10-18 16:45", 2457680.19791667); + singleTestCase("2016-10-18 16:45:30", 2457680.19826389); } void testDatetime() { From 52a2c7b4917911c3dcdc8a405db725d82a589465 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sat, 22 Jun 2019 14:40:19 +0300 Subject: [PATCH 132/232] removed core function string to dedicated classes --- dev/column_result.h | 10 +++--- dev/core_functions.h | 50 +++++++++++++++------------ include/sqlite_orm/sqlite_orm.h | 60 +++++++++++++++++++-------------- 3 files changed, 68 insertions(+), 52 deletions(-) diff --git a/dev/column_result.h b/dev/column_result.h index fe6ffaf8c..56ebeb39c 100644 --- a/dev/column_result.h +++ b/dev/column_result.h @@ -49,6 +49,11 @@ namespace sqlite_orm { using type = typename setter_traits::field_type; }; + template + struct column_result_t, void> { + using type = R; + }; + template struct column_result_t, void> { using type = int; @@ -306,10 +311,5 @@ namespace sqlite_orm { struct column_result_t, void> { using type = T; }; - - template - struct column_result_t, void> { - using type = R; - }; } } diff --git a/dev/core_functions.h b/dev/core_functions.h index c6f1ab8f8..c8d8f4977 100644 --- a/dev/core_functions.h +++ b/dev/core_functions.h @@ -16,19 +16,27 @@ namespace sqlite_orm { */ struct core_function_t {}; + struct length_string { + operator std::string() const { + return "LENGTH"; + } + }; + /** * LENGTH(x) function https://sqlite.org/lang_corefunc.html#length */ template - struct length_t : public core_function_t { + struct length_t : core_function_t, length_string { using arg_type = T; arg_type arg; length_t(arg_type &&arg_) : arg(std::move(arg_)) {} - + }; + + struct abs_string { operator std::string() const { - return "LENGTH"; + return "ABS"; } }; @@ -36,15 +44,17 @@ namespace sqlite_orm { * ABS(x) function https://sqlite.org/lang_corefunc.html#abs */ template - struct abs_t : public core_function_t { + struct abs_t : core_function_t, abs_string { using arg_type = T; arg_type arg; abs_t(arg_type &&arg_): arg(std::move(arg_)) {} - + }; + + struct lower_string { operator std::string() const { - return "ABS"; + return "LOWER"; } }; @@ -52,15 +62,17 @@ namespace sqlite_orm { * LOWER(x) function https://sqlite.org/lang_corefunc.html#lower */ template - struct lower_t : public core_function_t { + struct lower_t : core_function_t, lower_string { using arg_type = T; arg_type arg; lower_t(arg_type &&arg_): arg(std::move(arg_)) {} - + }; + + struct upper_string { operator std::string() const { - return "LOWER"; + return "UPPER"; } }; @@ -68,16 +80,12 @@ namespace sqlite_orm { * UPPER(x) function https://sqlite.org/lang_corefunc.html#upper */ template - struct upper_t : public core_function_t { + struct upper_t : core_function_t, upper_string { using arg_type = T; arg_type arg; upper_t(arg_type &&arg_): arg(std::move(arg_)) {} - - operator std::string() const { - return "UPPER"; - } }; /** @@ -100,7 +108,7 @@ namespace sqlite_orm { * TRIM(X) function https://sqlite.org/lang_corefunc.html#trim */ template - struct trim_single_t : public core_function_t, trim_string { + struct trim_single_t : core_function_t, trim_string { using arg_type = T; arg_type arg; @@ -112,7 +120,7 @@ namespace sqlite_orm { * TRIM(X,Y) function https://sqlite.org/lang_corefunc.html#trim */ template - struct trim_double_t : public core_function_t, trim_string { + struct trim_double_t : core_function_t, trim_string { using args_type = std::tuple; args_type args; @@ -130,7 +138,7 @@ namespace sqlite_orm { * LTRIM(X) function https://sqlite.org/lang_corefunc.html#ltrim */ template - struct ltrim_single_t : public core_function_t, ltrim_string { + struct ltrim_single_t : core_function_t, ltrim_string { using arg_type = X; arg_type arg; @@ -142,7 +150,7 @@ namespace sqlite_orm { * LTRIM(X,Y) function https://sqlite.org/lang_corefunc.html#ltrim */ template - struct ltrim_double_t : public core_function_t, ltrim_string { + struct ltrim_double_t : core_function_t, ltrim_string { using args_type = std::tuple; args_type args; @@ -160,7 +168,7 @@ namespace sqlite_orm { * RTRIM(X) function https://sqlite.org/lang_corefunc.html#rtrim */ template - struct rtrim_single_t : public core_function_t, rtrim_string { + struct rtrim_single_t : core_function_t, rtrim_string { using arg_type = X; arg_type arg; @@ -172,7 +180,7 @@ namespace sqlite_orm { * RTRIM(X,Y) function https://sqlite.org/lang_corefunc.html#rtrim */ template - struct rtrim_double_t : public core_function_t, rtrim_string { + struct rtrim_double_t : core_function_t, rtrim_string { using args_type = std::tuple; args_type args; @@ -194,7 +202,7 @@ namespace sqlite_orm { * CHAR(X1,X2,...,XN) function https://sqlite.org/lang_corefunc.html#char */ template - struct char_t_ : public core_function_t, char_string { + struct char_t_ : core_function_t, char_string { using args_type = std::tuple; args_type args; diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 1994f381c..6dbea8272 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -2837,19 +2837,27 @@ namespace sqlite_orm { */ struct core_function_t {}; + struct length_string { + operator std::string() const { + return "LENGTH"; + } + }; + /** * LENGTH(x) function https://sqlite.org/lang_corefunc.html#length */ template - struct length_t : public core_function_t { + struct length_t : core_function_t, length_string { using arg_type = T; arg_type arg; length_t(arg_type &&arg_) : arg(std::move(arg_)) {} - + }; + + struct abs_string { operator std::string() const { - return "LENGTH"; + return "ABS"; } }; @@ -2857,15 +2865,17 @@ namespace sqlite_orm { * ABS(x) function https://sqlite.org/lang_corefunc.html#abs */ template - struct abs_t : public core_function_t { + struct abs_t : core_function_t, abs_string { using arg_type = T; arg_type arg; abs_t(arg_type &&arg_): arg(std::move(arg_)) {} - + }; + + struct lower_string { operator std::string() const { - return "ABS"; + return "LOWER"; } }; @@ -2873,15 +2883,17 @@ namespace sqlite_orm { * LOWER(x) function https://sqlite.org/lang_corefunc.html#lower */ template - struct lower_t : public core_function_t { + struct lower_t : core_function_t, lower_string { using arg_type = T; arg_type arg; lower_t(arg_type &&arg_): arg(std::move(arg_)) {} - + }; + + struct upper_string { operator std::string() const { - return "LOWER"; + return "UPPER"; } }; @@ -2889,16 +2901,12 @@ namespace sqlite_orm { * UPPER(x) function https://sqlite.org/lang_corefunc.html#upper */ template - struct upper_t : public core_function_t { + struct upper_t : core_function_t, upper_string { using arg_type = T; arg_type arg; upper_t(arg_type &&arg_): arg(std::move(arg_)) {} - - operator std::string() const { - return "UPPER"; - } }; /** @@ -2921,7 +2929,7 @@ namespace sqlite_orm { * TRIM(X) function https://sqlite.org/lang_corefunc.html#trim */ template - struct trim_single_t : public core_function_t, trim_string { + struct trim_single_t : core_function_t, trim_string { using arg_type = T; arg_type arg; @@ -2933,7 +2941,7 @@ namespace sqlite_orm { * TRIM(X,Y) function https://sqlite.org/lang_corefunc.html#trim */ template - struct trim_double_t : public core_function_t, trim_string { + struct trim_double_t : core_function_t, trim_string { using args_type = std::tuple; args_type args; @@ -2951,7 +2959,7 @@ namespace sqlite_orm { * LTRIM(X) function https://sqlite.org/lang_corefunc.html#ltrim */ template - struct ltrim_single_t : public core_function_t, ltrim_string { + struct ltrim_single_t : core_function_t, ltrim_string { using arg_type = X; arg_type arg; @@ -2963,7 +2971,7 @@ namespace sqlite_orm { * LTRIM(X,Y) function https://sqlite.org/lang_corefunc.html#ltrim */ template - struct ltrim_double_t : public core_function_t, ltrim_string { + struct ltrim_double_t : core_function_t, ltrim_string { using args_type = std::tuple; args_type args; @@ -2981,7 +2989,7 @@ namespace sqlite_orm { * RTRIM(X) function https://sqlite.org/lang_corefunc.html#rtrim */ template - struct rtrim_single_t : public core_function_t, rtrim_string { + struct rtrim_single_t : core_function_t, rtrim_string { using arg_type = X; arg_type arg; @@ -2993,7 +3001,7 @@ namespace sqlite_orm { * RTRIM(X,Y) function https://sqlite.org/lang_corefunc.html#rtrim */ template - struct rtrim_double_t : public core_function_t, rtrim_string { + struct rtrim_double_t : core_function_t, rtrim_string { using args_type = std::tuple; args_type args; @@ -3015,7 +3023,7 @@ namespace sqlite_orm { * CHAR(X1,X2,...,XN) function https://sqlite.org/lang_corefunc.html#char */ template - struct char_t_ : public core_function_t, char_string { + struct char_t_ : core_function_t, char_string { using args_type = std::tuple; args_type args; @@ -4826,6 +4834,11 @@ namespace sqlite_orm { using type = typename setter_traits::field_type; }; + template + struct column_result_t, void> { + using type = R; + }; + template struct column_result_t, void> { using type = int; @@ -5083,11 +5096,6 @@ namespace sqlite_orm { struct column_result_t, void> { using type = T; }; - - template - struct column_result_t, void> { - using type = R; - }; } } #pragma once From 5375b50a780271996211ad289069c814e357c2c3 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sun, 23 Jun 2019 00:47:58 +0300 Subject: [PATCH 133/232] refactored left_join_t --- dev/ast_iterator.h | 20 +++++++ dev/conditions.h | 72 +++++++++++++------------ dev/storage.h | 2 +- include/sqlite_orm/sqlite_orm.h | 94 +++++++++++++++++++++------------ tests/tests.cpp | 47 +++++++++++++++++ 5 files changed, 165 insertions(+), 70 deletions(-) diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index d9d3e46dc..a5182f59d 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -394,5 +394,25 @@ namespace sqlite_orm { }); } }; + + template + struct ast_iterator, void> { + using node_type = conditions::left_join_t; + + template + void operator()(const node_type &j, const L &l) const { + iterate_ast(j.constraint, l); + } + }; + + template + struct ast_iterator, void> { + using node_type = conditions::on_t; + + template + void operator()(const node_type &o, const L &l) const { + iterate_ast(o.arg, l); + } + }; } } diff --git a/dev/conditions.h b/dev/conditions.h index ccadd80c9..f328d8162 100644 --- a/dev/conditions.h +++ b/dev/conditions.h @@ -347,8 +347,6 @@ namespace sqlite_orm { L l; // left expression A arg; // in arg - in_t() = default; - in_t(L l_, A arg_, bool negative): in_base{negative}, l(l_), arg(std::move(arg_)) {} negated_condition_t operator!() const { @@ -391,19 +389,21 @@ namespace sqlite_orm { } }; + struct where_string { + operator std::string () const { + return "WHERE"; + } + }; + /** * WHERE argument holder. * C is conditions type. Can be any condition like: is_equal_t, is_null_t, exists_t etc */ template - struct where_t { + struct where_t : where_string { C c; - where_t() = default; - - operator std::string () const { - return "WHERE"; - } + where_t(C c_) : c(std::move(c_)) {} }; struct order_by_base { @@ -411,23 +411,23 @@ namespace sqlite_orm { std::string _collate_argument; }; + struct order_by_string { + operator std::string() const { + return "ORDER BY"; + } + }; + /** * ORDER BY argument holder. */ template - struct order_by_t : order_by_base { + struct order_by_t : order_by_base, order_by_string { using self = order_by_t; O o; - order_by_t(): o() {} - order_by_t(O o_): o(o_) {} - operator std::string() const { - return "ORDER BY"; - } - self asc() { auto res = *this; res.asc_desc = 1; @@ -469,12 +469,12 @@ namespace sqlite_orm { * ORDER BY pack holder. */ template - struct multi_order_by_t { - std::tuple args; + struct multi_order_by_t : order_by_string { + using args_type = std::tuple; - operator std::string() const { - return static_cast(order_by_t()); - } + args_type args; + + multi_order_by_t(args_type args_) : args(std::move(args_)) {} }; /** @@ -498,8 +498,6 @@ namespace sqlite_orm { T b1; T b2; - between_t() = default; - between_t(A expr_, T b1_, T b2_): expr(expr_), b1(b1_), b2(b2_) {} operator std::string() const { @@ -515,8 +513,6 @@ namespace sqlite_orm { A a; T t; - like_t() = default; - like_t(A a_, T t_): a(a_), t(t_) {} operator std::string() const { @@ -550,21 +546,25 @@ namespace sqlite_orm { } }; + struct left_join_string { + operator std::string() const { + return "LEFT JOIN"; + } + }; + /** * LEFT JOIN holder. * T is joined type which represents any mapped table. * O is on(...) argument type. */ template - struct left_join_t { + struct left_join_t : left_join_string { using type = T; using on_type = O; on_type constraint; - operator std::string() const { - return "LEFT JOIN"; - } + left_join_t(on_type constraint_) : constraint(std::move(constraint_)) {} }; /** @@ -601,19 +601,23 @@ namespace sqlite_orm { } }; + struct on_string { + operator std::string() const { + return "ON"; + } + }; + /** * on(...) argument holder used for JOIN, LEFT JOIN, LEFT OUTER JOIN and INNER JOIN * T is on type argument. */ template - struct on_t { - using type = T; + struct on_t : on_string { + using arg_type = T; - type t; + arg_type arg; - operator std::string() const { - return "ON"; - } + on_t(arg_type arg_) : arg(std::move(arg_)) {} }; /** diff --git a/dev/storage.h b/dev/storage.h index 83bceea9b..58182de3d 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -1030,7 +1030,7 @@ namespace sqlite_orm { template void process_join_constraint(std::stringstream &ss, const conditions::on_t &t) { - ss << static_cast(t) << " " << this->process_where(t.t) << " "; + ss << static_cast(t) << " " << this->process_where(t.arg) << " "; } template diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 6dbea8272..335ac0d75 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -1863,8 +1863,6 @@ namespace sqlite_orm { L l; // left expression A arg; // in arg - in_t() = default; - in_t(L l_, A arg_, bool negative): in_base{negative}, l(l_), arg(std::move(arg_)) {} negated_condition_t operator!() const { @@ -1907,19 +1905,21 @@ namespace sqlite_orm { } }; + struct where_string { + operator std::string () const { + return "WHERE"; + } + }; + /** * WHERE argument holder. * C is conditions type. Can be any condition like: is_equal_t, is_null_t, exists_t etc */ template - struct where_t { + struct where_t : where_string { C c; - where_t() = default; - - operator std::string () const { - return "WHERE"; - } + where_t(C c_) : c(std::move(c_)) {} }; struct order_by_base { @@ -1927,23 +1927,23 @@ namespace sqlite_orm { std::string _collate_argument; }; + struct order_by_string { + operator std::string() const { + return "ORDER BY"; + } + }; + /** * ORDER BY argument holder. */ template - struct order_by_t : order_by_base { + struct order_by_t : order_by_base, order_by_string { using self = order_by_t; O o; - order_by_t(): o() {} - order_by_t(O o_): o(o_) {} - operator std::string() const { - return "ORDER BY"; - } - self asc() { auto res = *this; res.asc_desc = 1; @@ -1985,12 +1985,12 @@ namespace sqlite_orm { * ORDER BY pack holder. */ template - struct multi_order_by_t { - std::tuple args; + struct multi_order_by_t : order_by_string { + using args_type = std::tuple; - operator std::string() const { - return static_cast(order_by_t()); - } + args_type args; + + multi_order_by_t(args_type args_) : args(std::move(args_)) {} }; /** @@ -2014,8 +2014,6 @@ namespace sqlite_orm { T b1; T b2; - between_t() = default; - between_t(A expr_, T b1_, T b2_): expr(expr_), b1(b1_), b2(b2_) {} operator std::string() const { @@ -2031,8 +2029,6 @@ namespace sqlite_orm { A a; T t; - like_t() = default; - like_t(A a_, T t_): a(a_), t(t_) {} operator std::string() const { @@ -2066,21 +2062,25 @@ namespace sqlite_orm { } }; + struct left_join_string { + operator std::string() const { + return "LEFT JOIN"; + } + }; + /** * LEFT JOIN holder. * T is joined type which represents any mapped table. * O is on(...) argument type. */ template - struct left_join_t { + struct left_join_t : left_join_string { using type = T; using on_type = O; on_type constraint; - operator std::string() const { - return "LEFT JOIN"; - } + left_join_t(on_type constraint_) : constraint(std::move(constraint_)) {} }; /** @@ -2117,19 +2117,23 @@ namespace sqlite_orm { } }; + struct on_string { + operator std::string() const { + return "ON"; + } + }; + /** * on(...) argument holder used for JOIN, LEFT JOIN, LEFT OUTER JOIN and INNER JOIN * T is on type argument. */ template - struct on_t { - using type = T; + struct on_t : on_string { + using arg_type = T; - type t; + arg_type arg; - operator std::string() const { - return "ON"; - } + on_t(arg_type arg_) : arg(std::move(arg_)) {} }; /** @@ -7128,6 +7132,26 @@ namespace sqlite_orm { }); } }; + + template + struct ast_iterator, void> { + using node_type = conditions::left_join_t; + + template + void operator()(const node_type &j, const L &l) const { + iterate_ast(j.constraint, l); + } + }; + + template + struct ast_iterator, void> { + using node_type = conditions::on_t; + + template + void operator()(const node_type &o, const L &l) const { + iterate_ast(o.arg, l); + } + }; } } @@ -8173,7 +8197,7 @@ namespace sqlite_orm { template void process_join_constraint(std::stringstream &ss, const conditions::on_t &t) { - ss << static_cast(t) << " " << this->process_where(t.t) << " "; + ss << static_cast(t) << " " << this->process_where(t.arg) << " "; } template diff --git a/tests/tests.cpp b/tests/tests.cpp index c2de781ab..112bbe84a 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -13,6 +13,51 @@ using namespace sqlite_orm; using std::cout; using std::endl; +void testLeftJoin() { + cout << __func__ << endl; + + struct User { + int id = 0; + std::string name; + }; + + struct Visit { + int id = 0; + int userId = 0; + time_t date = 0; + }; + + auto storage = make_storage({}, + make_table("users", + make_column("id", &User::id, primary_key()), + make_column("name", &User::name)), + make_table("visits", + make_column("id", &Visit::id, primary_key()), + make_column("user_id", &Visit::userId), + make_column("date", &Visit::date))); + storage.sync_schema(); + + int id = 1; + User will{id++, "Will"}; + User smith{id++, "Smith"}; + User nicole{id++, "Nicole"}; + + storage.replace(will); + storage.replace(smith); + storage.replace(nicole); + + id = 1; + storage.replace(Visit{id++, will.id, 10}); + storage.replace(Visit{id++, will.id, 20}); + storage.replace(Visit{id++, will.id, 30}); + + storage.replace(Visit{id++, smith.id, 25}); + storage.replace(Visit{id++, smith.id, 35}); + + auto rows = storage.get_all(left_join(on(is_equal(&Visit::userId, 2)))); + assert(rows.size() == 6); +} + void testJulianday() { cout << __func__ << endl; @@ -3036,4 +3081,6 @@ int main(int, char **) { testDatetime(); testJulianday(); + + testLeftJoin(); } From cc56793d8e58a2ba97d1f50d2a8fbabce9dcf160 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sun, 23 Jun 2019 00:56:24 +0300 Subject: [PATCH 134/232] refactored join_t --- dev/ast_iterator.h | 10 ++++++++++ dev/conditions.h | 12 ++++++++---- include/sqlite_orm/sqlite_orm.h | 22 ++++++++++++++++++---- tests/tests.cpp | 14 ++++++++++---- 4 files changed, 46 insertions(+), 12 deletions(-) diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index a5182f59d..317bcbf6a 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -414,5 +414,15 @@ namespace sqlite_orm { iterate_ast(o.arg, l); } }; + + template + struct ast_iterator, void> { + using node_type = conditions::join_t; + + template + void operator()(const node_type &j, const L &l) const { + iterate_ast(j.constraint, l); + } + }; } } diff --git a/dev/conditions.h b/dev/conditions.h index f328d8162..0ad98458c 100644 --- a/dev/conditions.h +++ b/dev/conditions.h @@ -567,21 +567,25 @@ namespace sqlite_orm { left_join_t(on_type constraint_) : constraint(std::move(constraint_)) {} }; + struct join_string { + operator std::string() const { + return "JOIN"; + } + }; + /** * Simple JOIN holder. * T is joined type which represents any mapped table. * O is on(...) argument type. */ template - struct join_t { + struct join_t : join_string { using type = T; using on_type = O; on_type constraint; - operator std::string() const { - return "JOIN"; - } + join_t(on_type constraint_) : constraint(std::move(constraint_)) {} }; /** diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 335ac0d75..51628172b 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -2083,21 +2083,25 @@ namespace sqlite_orm { left_join_t(on_type constraint_) : constraint(std::move(constraint_)) {} }; + struct join_string { + operator std::string() const { + return "JOIN"; + } + }; + /** * Simple JOIN holder. * T is joined type which represents any mapped table. * O is on(...) argument type. */ template - struct join_t { + struct join_t : join_string { using type = T; using on_type = O; on_type constraint; - operator std::string() const { - return "JOIN"; - } + join_t(on_type constraint_) : constraint(std::move(constraint_)) {} }; /** @@ -7152,6 +7156,16 @@ namespace sqlite_orm { iterate_ast(o.arg, l); } }; + + template + struct ast_iterator, void> { + using node_type = conditions::join_t; + + template + void operator()(const node_type &j, const L &l) const { + iterate_ast(j.constraint, l); + } + }; } } diff --git a/tests/tests.cpp b/tests/tests.cpp index 112bbe84a..48b6400ae 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -13,7 +13,7 @@ using namespace sqlite_orm; using std::cout; using std::endl; -void testLeftJoin() { +void testJoin() { cout << __func__ << endl; struct User { @@ -54,8 +54,14 @@ void testLeftJoin() { storage.replace(Visit{id++, smith.id, 25}); storage.replace(Visit{id++, smith.id, 35}); - auto rows = storage.get_all(left_join(on(is_equal(&Visit::userId, 2)))); - assert(rows.size() == 6); + { + auto rows = storage.get_all(left_join(on(is_equal(&Visit::userId, 2)))); + assert(rows.size() == 6); + } + { + auto rows = storage.get_all(join(on(is_equal(&Visit::userId, 2)))); + assert(rows.size() == 6); + } } void testJulianday() { @@ -3082,5 +3088,5 @@ int main(int, char **) { testJulianday(); - testLeftJoin(); + testJoin(); } From ebbbb9e80e5ae255e3c3bb90e8f061ab41240e70 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sun, 23 Jun 2019 00:59:39 +0300 Subject: [PATCH 135/232] refactored left_outer_join_t --- dev/ast_iterator.h | 10 ++++++++++ dev/conditions.h | 12 ++++++++---- include/sqlite_orm/sqlite_orm.h | 22 ++++++++++++++++++---- tests/tests.cpp | 4 ++++ 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index 317bcbf6a..b7d31fe03 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -424,5 +424,15 @@ namespace sqlite_orm { iterate_ast(j.constraint, l); } }; + + template + struct ast_iterator, void> { + using node_type = conditions::left_outer_join_t; + + template + void operator()(const node_type &j, const L &l) const { + iterate_ast(j.constraint, l); + } + }; } } diff --git a/dev/conditions.h b/dev/conditions.h index 0ad98458c..fc4d2dadd 100644 --- a/dev/conditions.h +++ b/dev/conditions.h @@ -588,21 +588,25 @@ namespace sqlite_orm { join_t(on_type constraint_) : constraint(std::move(constraint_)) {} }; + struct left_outer_join_string { + operator std::string() const { + return "LEFT OUTER JOIN"; + } + }; + /** * LEFT OUTER JOIN holder. * T is joined type which represents any mapped table. * O is on(...) argument type. */ template - struct left_outer_join_t { + struct left_outer_join_t : left_outer_join_string { using type = T; using on_type = O; on_type constraint; - operator std::string() const { - return "LEFT OUTER JOIN"; - } + left_outer_join_t(on_type constraint_) : constraint(std::move(constraint_)) {} }; struct on_string { diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 51628172b..bc981fd7d 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -2104,21 +2104,25 @@ namespace sqlite_orm { join_t(on_type constraint_) : constraint(std::move(constraint_)) {} }; + struct left_outer_join_string { + operator std::string() const { + return "LEFT OUTER JOIN"; + } + }; + /** * LEFT OUTER JOIN holder. * T is joined type which represents any mapped table. * O is on(...) argument type. */ template - struct left_outer_join_t { + struct left_outer_join_t : left_outer_join_string { using type = T; using on_type = O; on_type constraint; - operator std::string() const { - return "LEFT OUTER JOIN"; - } + left_outer_join_t(on_type constraint_) : constraint(std::move(constraint_)) {} }; struct on_string { @@ -7166,6 +7170,16 @@ namespace sqlite_orm { iterate_ast(j.constraint, l); } }; + + template + struct ast_iterator, void> { + using node_type = conditions::left_outer_join_t; + + template + void operator()(const node_type &j, const L &l) const { + iterate_ast(j.constraint, l); + } + }; } } diff --git a/tests/tests.cpp b/tests/tests.cpp index 48b6400ae..e6b2db713 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -62,6 +62,10 @@ void testJoin() { auto rows = storage.get_all(join(on(is_equal(&Visit::userId, 2)))); assert(rows.size() == 6); } + { + auto rows = storage.get_all(left_outer_join(on(is_equal(&Visit::userId, 2)))); + assert(rows.size() == 6); + } } void testJulianday() { From c3b8b913869dfa7b6f2c44b7a691b324499de79c Mon Sep 17 00:00:00 2001 From: Roelf-Jilling Date: Sun, 23 Jun 2019 00:00:30 +0200 Subject: [PATCH 136/232] Revert "Removed os x gcc until it is fixed in vcpkg" This reverts commit 37979bf1ef22434b63d89f408e2575e32fe419da. --- .travis.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.travis.yml b/.travis.yml index a958d35fc..7a375735a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -58,6 +58,18 @@ matrix: - CXX=/usr/local/opt/llvm/bin/clang++ - VCPKG_ALLOW_APPLE_CLANG=1 - SQLITE_ORM_OMITS_CODECVT=ON + - name: "osx gcc" + addons: + homebrew: + packages: + - gcc6 + compiler: gcc + os: osx + osx_image: xcode10.1 + env: + - CC=gcc-6 + - CXX=g++-6 + - SQLITE_ORM_OMITS_CODECVT=OFF before_install: # coveralls test coverage: From 72a66193d7e5cf69f73a7e12878874448143d4fb Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sun, 23 Jun 2019 01:03:53 +0300 Subject: [PATCH 137/232] refactored inner_join_t --- dev/ast_iterator.h | 10 ++++++++++ dev/conditions.h | 12 ++++++++---- include/sqlite_orm/sqlite_orm.h | 22 ++++++++++++++++++---- tests/tests.cpp | 4 ++++ 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index b7d31fe03..1b44210c2 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -434,5 +434,15 @@ namespace sqlite_orm { iterate_ast(j.constraint, l); } }; + + template + struct ast_iterator, void> { + using node_type = conditions::inner_join_t; + + template + void operator()(const node_type &j, const L &l) const { + iterate_ast(j.constraint, l); + } + }; } } diff --git a/dev/conditions.h b/dev/conditions.h index fc4d2dadd..2d619fa51 100644 --- a/dev/conditions.h +++ b/dev/conditions.h @@ -640,21 +640,25 @@ namespace sqlite_orm { } }; + struct inner_join_string { + operator std::string() const { + return "INNER JOIN"; + } + }; + /** * INNER JOIN holder. * T is joined type which represents any mapped table. * O is on(...) argument type. */ template - struct inner_join_t { + struct inner_join_t : inner_join_string { using type = T; using on_type = O; on_type constraint; - operator std::string() const { - return "INNER JOIN"; - } + inner_join_t(on_type constraint_) : constraint(std::move(constraint_)) {} }; template diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index bc981fd7d..e22a6646d 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -2156,21 +2156,25 @@ namespace sqlite_orm { } }; + struct inner_join_string { + operator std::string() const { + return "INNER JOIN"; + } + }; + /** * INNER JOIN holder. * T is joined type which represents any mapped table. * O is on(...) argument type. */ template - struct inner_join_t { + struct inner_join_t : inner_join_string { using type = T; using on_type = O; on_type constraint; - operator std::string() const { - return "INNER JOIN"; - } + inner_join_t(on_type constraint_) : constraint(std::move(constraint_)) {} }; template @@ -7180,6 +7184,16 @@ namespace sqlite_orm { iterate_ast(j.constraint, l); } }; + + template + struct ast_iterator, void> { + using node_type = conditions::inner_join_t; + + template + void operator()(const node_type &j, const L &l) const { + iterate_ast(j.constraint, l); + } + }; } } diff --git a/tests/tests.cpp b/tests/tests.cpp index e6b2db713..f34b8388e 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -66,6 +66,10 @@ void testJoin() { auto rows = storage.get_all(left_outer_join(on(is_equal(&Visit::userId, 2)))); assert(rows.size() == 6); } + { + auto rows = storage.get_all(inner_join(on(is_equal(&Visit::userId, 2)))); + assert(rows.size() == 6); + } } void testJulianday() { From f6fe6bfba57fec4280b719b7b314b8b6b3932c57 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sun, 23 Jun 2019 01:05:56 +0300 Subject: [PATCH 138/232] removed default ctor from exists_t --- dev/conditions.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/dev/conditions.h b/dev/conditions.h index 2d619fa51..1b4be3ef2 100644 --- a/dev/conditions.h +++ b/dev/conditions.h @@ -668,8 +668,6 @@ namespace sqlite_orm { type t; - exists_t() = default; - exists_t(T t_) : t(std::move(t_)) {} operator std::string() const { From e339b9f5eb66af48adcb16f810f10b78b5423587 Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sun, 23 Jun 2019 10:54:42 +0300 Subject: [PATCH 139/232] added move to assign ctor --- dev/ast_iterator.h | 4 +- dev/operators.h | 17 +++----- dev/storage.h | 48 +++++++++++----------- include/sqlite_orm/sqlite_orm.h | 71 +++++++++++++++------------------ tests/tests.cpp | 25 ++++++++++++ 5 files changed, 89 insertions(+), 76 deletions(-) diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index 1b44210c2..5c35d0d79 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -62,8 +62,8 @@ namespace sqlite_orm { template void operator()(const node_type &binaryOperator, const L &l) const { - iterate_ast(binaryOperator.l, l); - iterate_ast(binaryOperator.r, l); + iterate_ast(binaryOperator.lhs, l); + iterate_ast(binaryOperator.rhs, l); } }; diff --git a/dev/operators.h b/dev/operators.h index 98ffb5f77..9a3da889e 100644 --- a/dev/operators.h +++ b/dev/operators.h @@ -16,12 +16,10 @@ namespace sqlite_orm { using left_type = L; using right_type = R; - left_type l; - right_type r; + left_type lhs; + right_type rhs; - binary_operator() = default; - - binary_operator(left_type l_, right_type r_) : l(std::move(l_)), r(std::move(r_)) {} + binary_operator(left_type lhs_, right_type rhs_) : lhs(std::move(lhs_)), rhs(std::move(rhs_)) {} }; /** @@ -92,9 +90,7 @@ namespace sqlite_orm { L l; R r; - assign_t(){} - - assign_t(L l_, R r_): l(l_), r(r_) {} + assign_t(L l_, R r_): l(std::move(l_)), r(std::move(r_)) {} }; /** @@ -116,7 +112,7 @@ namespace sqlite_orm { struct expression_t { T t; - expression_t(T t_): t(t_) {} + expression_t(T t_): t(std::move(t_)) {} template assign_t operator=(R r) const { @@ -135,8 +131,7 @@ namespace sqlite_orm { */ template internal::expression_t c(T t) { - using result_type = internal::expression_t; - return result_type(std::move(t)); + return {std::move(t)}; } /** diff --git a/dev/storage.h b/dev/storage.h index 58182de3d..3b03381b0 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -473,8 +473,8 @@ namespace sqlite_orm { template std::string string_from_expression(const conc_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); - auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); + auto lhs = this->string_from_expression(f.lhs, noTableName, escape, ignoreBindable); + auto rhs = this->string_from_expression(f.rhs, noTableName, escape, ignoreBindable); ss << "(" << lhs << " || " << rhs << ") "; return ss.str(); } @@ -482,8 +482,8 @@ namespace sqlite_orm { template std::string string_from_expression(const add_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); - auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); + auto lhs = this->string_from_expression(f.lhs, noTableName, escape, ignoreBindable); + auto rhs = this->string_from_expression(f.rhs, noTableName, escape, ignoreBindable); ss << "(" << lhs << " + " << rhs << ") "; return ss.str(); } @@ -491,8 +491,8 @@ namespace sqlite_orm { template std::string string_from_expression(const sub_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); - auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); + auto lhs = this->string_from_expression(f.lhs, noTableName, escape, ignoreBindable); + auto rhs = this->string_from_expression(f.rhs, noTableName, escape, ignoreBindable); ss << "(" << lhs << " - " << rhs << ") "; return ss.str(); } @@ -500,8 +500,8 @@ namespace sqlite_orm { template std::string string_from_expression(const mul_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); - auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); + auto lhs = this->string_from_expression(f.lhs, noTableName, escape, ignoreBindable); + auto rhs = this->string_from_expression(f.rhs, noTableName, escape, ignoreBindable); ss << "(" << lhs << " * " << rhs << ") "; return ss.str(); } @@ -509,8 +509,8 @@ namespace sqlite_orm { template std::string string_from_expression(const div_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); - auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); + auto lhs = this->string_from_expression(f.lhs, noTableName, escape, ignoreBindable); + auto rhs = this->string_from_expression(f.rhs, noTableName, escape, ignoreBindable); ss << "(" << lhs << " / " << rhs << ") "; return ss.str(); } @@ -518,8 +518,8 @@ namespace sqlite_orm { template std::string string_from_expression(const mod_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); - auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); + auto lhs = this->string_from_expression(f.lhs, noTableName, escape, ignoreBindable); + auto rhs = this->string_from_expression(f.rhs, noTableName, escape, ignoreBindable); ss << "(" << lhs << " % " << rhs << ") "; return ss.str(); } @@ -1677,9 +1677,9 @@ namespace sqlite_orm { template std::set> parse_table_name(const conc_t &f) { std::set> res; - auto leftSet = this->parse_table_names(f.l); + auto leftSet = this->parse_table_names(f.lhs); res.insert(leftSet.begin(), leftSet.end()); - auto rightSet = this->parse_table_names(f.r); + auto rightSet = this->parse_table_names(f.rhs); res.insert(rightSet.begin(), rightSet.end()); return res; } @@ -1687,9 +1687,9 @@ namespace sqlite_orm { template std::set> parse_table_name(const add_t &f) { std::set> res; - auto leftSet = this->parse_table_names(f.l); + auto leftSet = this->parse_table_names(f.lhs); res.insert(leftSet.begin(), leftSet.end()); - auto rightSet = this->parse_table_names(f.r); + auto rightSet = this->parse_table_names(f.rhs); res.insert(rightSet.begin(), rightSet.end()); return res; } @@ -1697,9 +1697,9 @@ namespace sqlite_orm { template std::set> parse_table_name(const sub_t &f) { std::set> res; - auto leftSet = this->parse_table_names(f.l); + auto leftSet = this->parse_table_names(f.lhs); res.insert(leftSet.begin(), leftSet.end()); - auto rightSet = this->parse_table_names(f.r); + auto rightSet = this->parse_table_names(f.rhs); res.insert(rightSet.begin(), rightSet.end()); return res; } @@ -1707,9 +1707,9 @@ namespace sqlite_orm { template std::set> parse_table_name(const mul_t &f) { std::set> res; - auto leftSet = this->parse_table_names(f.l); + auto leftSet = this->parse_table_names(f.lhs); res.insert(leftSet.begin(), leftSet.end()); - auto rightSet = this->parse_table_names(f.r); + auto rightSet = this->parse_table_names(f.rhs); res.insert(rightSet.begin(), rightSet.end()); return res; } @@ -1717,9 +1717,9 @@ namespace sqlite_orm { template std::set> parse_table_name(const div_t &f) { std::set> res; - auto leftSet = this->parse_table_names(f.l); + auto leftSet = this->parse_table_names(f.lhs); res.insert(leftSet.begin(), leftSet.end()); - auto rightSet = this->parse_table_names(f.r); + auto rightSet = this->parse_table_names(f.rhs); res.insert(rightSet.begin(), rightSet.end()); return res; } @@ -1727,9 +1727,9 @@ namespace sqlite_orm { template std::set> parse_table_name(const mod_t &f) { std::set> res; - auto leftSet = this->parse_table_names(f.l); + auto leftSet = this->parse_table_names(f.lhs); res.insert(leftSet.begin(), leftSet.end()); - auto rightSet = this->parse_table_names(f.r); + auto rightSet = this->parse_table_names(f.rhs); res.insert(rightSet.begin(), rightSet.end()); return res; } diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index e22a6646d..d2c6c5f18 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -922,12 +922,10 @@ namespace sqlite_orm { using left_type = L; using right_type = R; - left_type l; - right_type r; + left_type lhs; + right_type rhs; - binary_operator() = default; - - binary_operator(left_type l_, right_type r_) : l(std::move(l_)), r(std::move(r_)) {} + binary_operator(left_type lhs_, right_type rhs_) : lhs(std::move(lhs_)), rhs(std::move(rhs_)) {} }; /** @@ -998,9 +996,7 @@ namespace sqlite_orm { L l; R r; - assign_t(){} - - assign_t(L l_, R r_): l(l_), r(r_) {} + assign_t(L l_, R r_): l(std::move(l_)), r(std::move(r_)) {} }; /** @@ -1022,7 +1018,7 @@ namespace sqlite_orm { struct expression_t { T t; - expression_t(T t_): t(t_) {} + expression_t(T t_): t(std::move(t_)) {} template assign_t operator=(R r) const { @@ -1041,8 +1037,7 @@ namespace sqlite_orm { */ template internal::expression_t c(T t) { - using result_type = internal::expression_t; - return result_type(std::move(t)); + return {std::move(t)}; } /** @@ -2184,8 +2179,6 @@ namespace sqlite_orm { type t; - exists_t() = default; - exists_t(T t_) : t(std::move(t_)) {} operator std::string() const { @@ -6812,8 +6805,8 @@ namespace sqlite_orm { template void operator()(const node_type &binaryOperator, const L &l) const { - iterate_ast(binaryOperator.l, l); - iterate_ast(binaryOperator.r, l); + iterate_ast(binaryOperator.lhs, l); + iterate_ast(binaryOperator.rhs, l); } }; @@ -7682,8 +7675,8 @@ namespace sqlite_orm { template std::string string_from_expression(const conc_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); - auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); + auto lhs = this->string_from_expression(f.lhs, noTableName, escape, ignoreBindable); + auto rhs = this->string_from_expression(f.rhs, noTableName, escape, ignoreBindable); ss << "(" << lhs << " || " << rhs << ") "; return ss.str(); } @@ -7691,8 +7684,8 @@ namespace sqlite_orm { template std::string string_from_expression(const add_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); - auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); + auto lhs = this->string_from_expression(f.lhs, noTableName, escape, ignoreBindable); + auto rhs = this->string_from_expression(f.rhs, noTableName, escape, ignoreBindable); ss << "(" << lhs << " + " << rhs << ") "; return ss.str(); } @@ -7700,8 +7693,8 @@ namespace sqlite_orm { template std::string string_from_expression(const sub_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); - auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); + auto lhs = this->string_from_expression(f.lhs, noTableName, escape, ignoreBindable); + auto rhs = this->string_from_expression(f.rhs, noTableName, escape, ignoreBindable); ss << "(" << lhs << " - " << rhs << ") "; return ss.str(); } @@ -7709,8 +7702,8 @@ namespace sqlite_orm { template std::string string_from_expression(const mul_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); - auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); + auto lhs = this->string_from_expression(f.lhs, noTableName, escape, ignoreBindable); + auto rhs = this->string_from_expression(f.rhs, noTableName, escape, ignoreBindable); ss << "(" << lhs << " * " << rhs << ") "; return ss.str(); } @@ -7718,8 +7711,8 @@ namespace sqlite_orm { template std::string string_from_expression(const div_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); - auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); + auto lhs = this->string_from_expression(f.lhs, noTableName, escape, ignoreBindable); + auto rhs = this->string_from_expression(f.rhs, noTableName, escape, ignoreBindable); ss << "(" << lhs << " / " << rhs << ") "; return ss.str(); } @@ -7727,8 +7720,8 @@ namespace sqlite_orm { template std::string string_from_expression(const mod_t &f, bool noTableName, bool escape, bool ignoreBindable = false) { std::stringstream ss; - auto lhs = this->string_from_expression(f.l, noTableName, escape, ignoreBindable); - auto rhs = this->string_from_expression(f.r, noTableName, escape, ignoreBindable); + auto lhs = this->string_from_expression(f.lhs, noTableName, escape, ignoreBindable); + auto rhs = this->string_from_expression(f.rhs, noTableName, escape, ignoreBindable); ss << "(" << lhs << " % " << rhs << ") "; return ss.str(); } @@ -8886,9 +8879,9 @@ namespace sqlite_orm { template std::set> parse_table_name(const conc_t &f) { std::set> res; - auto leftSet = this->parse_table_names(f.l); + auto leftSet = this->parse_table_names(f.lhs); res.insert(leftSet.begin(), leftSet.end()); - auto rightSet = this->parse_table_names(f.r); + auto rightSet = this->parse_table_names(f.rhs); res.insert(rightSet.begin(), rightSet.end()); return res; } @@ -8896,9 +8889,9 @@ namespace sqlite_orm { template std::set> parse_table_name(const add_t &f) { std::set> res; - auto leftSet = this->parse_table_names(f.l); + auto leftSet = this->parse_table_names(f.lhs); res.insert(leftSet.begin(), leftSet.end()); - auto rightSet = this->parse_table_names(f.r); + auto rightSet = this->parse_table_names(f.rhs); res.insert(rightSet.begin(), rightSet.end()); return res; } @@ -8906,9 +8899,9 @@ namespace sqlite_orm { template std::set> parse_table_name(const sub_t &f) { std::set> res; - auto leftSet = this->parse_table_names(f.l); + auto leftSet = this->parse_table_names(f.lhs); res.insert(leftSet.begin(), leftSet.end()); - auto rightSet = this->parse_table_names(f.r); + auto rightSet = this->parse_table_names(f.rhs); res.insert(rightSet.begin(), rightSet.end()); return res; } @@ -8916,9 +8909,9 @@ namespace sqlite_orm { template std::set> parse_table_name(const mul_t &f) { std::set> res; - auto leftSet = this->parse_table_names(f.l); + auto leftSet = this->parse_table_names(f.lhs); res.insert(leftSet.begin(), leftSet.end()); - auto rightSet = this->parse_table_names(f.r); + auto rightSet = this->parse_table_names(f.rhs); res.insert(rightSet.begin(), rightSet.end()); return res; } @@ -8926,9 +8919,9 @@ namespace sqlite_orm { template std::set> parse_table_name(const div_t &f) { std::set> res; - auto leftSet = this->parse_table_names(f.l); + auto leftSet = this->parse_table_names(f.lhs); res.insert(leftSet.begin(), leftSet.end()); - auto rightSet = this->parse_table_names(f.r); + auto rightSet = this->parse_table_names(f.rhs); res.insert(rightSet.begin(), rightSet.end()); return res; } @@ -8936,9 +8929,9 @@ namespace sqlite_orm { template std::set> parse_table_name(const mod_t &f) { std::set> res; - auto leftSet = this->parse_table_names(f.l); + auto leftSet = this->parse_table_names(f.lhs); res.insert(leftSet.begin(), leftSet.end()); - auto rightSet = this->parse_table_names(f.r); + auto rightSet = this->parse_table_names(f.rhs); res.insert(rightSet.begin(), rightSet.end()); return res; } diff --git a/tests/tests.cpp b/tests/tests.cpp index f34b8388e..65316dc3c 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -13,6 +13,29 @@ using namespace sqlite_orm; using std::cout; using std::endl; +void testUniquePtrInUpdate() { + cout << __func__ << endl; + + struct User { + int id = 0; + std::unique_ptr name; + }; + + auto storage = make_storage({}, + make_table("users", + make_column("id", &User::id, primary_key()), + make_column("name", &User::name))); + storage.sync_schema(); + + storage.insert(User{}); + storage.insert(User{}); + storage.insert(User{}); + + storage.update_all(set(assign(&User::name, std::make_unique("Nick")))); + + assert(storage.count(where(is_null(&User::name))) == 0); +} + void testJoin() { cout << __func__ << endl; @@ -3097,4 +3120,6 @@ int main(int, char **) { testJulianday(); testJoin(); + + testUniquePtrInUpdate(); } From a4cceec6382b472594d3b359e2667c47e2efdd9f Mon Sep 17 00:00:00 2001 From: fnc12 Date: Sun, 23 Jun 2019 13:06:45 +0300 Subject: [PATCH 140/232] added return_type to core_function_t --- dev/column_result.h | 87 +----------- dev/core_functions.h | 66 +++++---- dev/is_base_of_template.h | 39 ++++++ dev/select_constraints.h | 32 +---- dev/storage.h | 15 +- include/sqlite_orm/sqlite_orm.h | 241 ++++++++++++-------------------- 6 files changed, 174 insertions(+), 306 deletions(-) create mode 100644 dev/is_base_of_template.h diff --git a/dev/column_result.h b/dev/column_result.h index 56ebeb39c..81903e9a5 100644 --- a/dev/column_result.h +++ b/dev/column_result.h @@ -49,92 +49,9 @@ namespace sqlite_orm { using type = typename setter_traits::field_type; }; - template - struct column_result_t, void> { - using type = R; - }; - template - struct column_result_t, void> { - using type = int; - }; - -#if SQLITE_VERSION_NUMBER >= 3007016 - - template - struct column_result_t, void> { - using type = std::string; - }; -#endif - - template - struct column_result_t { - using type = int; - }; - - template - struct column_result_t { - using type = int; - }; - - template - struct column_result_t, void> { - using type = std::unique_ptr; - }; - - template - struct column_result_t, void> { - using type = std::string; - }; - - template - struct column_result_t, void> { - using type = std::string; - }; - - template - struct column_result_t, void> { - using type = std::string; - }; - - template - struct column_result_t, void> { - using type = std::string; - }; - - template - struct column_result_t, void> { - using type = std::string; - }; - - template - struct column_result_t, void> { - using type = std::string; - }; - - template - struct column_result_t, void> { - using type = std::string; - }; - - template - struct column_result_t, void> { - using type = std::string; - }; - - template - struct column_result_t, void> { - using type = std::string; - }; - - template - struct column_result_t, void> { - using type = double; - }; - - template - struct column_result_t, void> { - using type = std::string; + struct column_result_t::value>::type> { + using type = typename T::return_type; }; template diff --git a/dev/core_functions.h b/dev/core_functions.h index c8d8f4977..6e2aaea15 100644 --- a/dev/core_functions.h +++ b/dev/core_functions.h @@ -3,9 +3,11 @@ #include // std::string #include // std::make_tuple #include // std::forward, std::is_base_of, std::enable_if +#include // std::unique_ptr #include "conditions.h" #include "operators.h" +#include "is_base_of_template.h" namespace sqlite_orm { @@ -13,8 +15,12 @@ namespace sqlite_orm { /** * Base class for operator overloading + * R is return type */ - struct core_function_t {}; + template + struct core_function_t { + using return_type = R; + }; struct length_string { operator std::string() const { @@ -26,7 +32,7 @@ namespace sqlite_orm { * LENGTH(x) function https://sqlite.org/lang_corefunc.html#length */ template - struct length_t : core_function_t, length_string { + struct length_t : core_function_t, length_string { using arg_type = T; arg_type arg; @@ -44,7 +50,7 @@ namespace sqlite_orm { * ABS(x) function https://sqlite.org/lang_corefunc.html#abs */ template - struct abs_t : core_function_t, abs_string { + struct abs_t : core_function_t>, abs_string { using arg_type = T; arg_type arg; @@ -62,7 +68,7 @@ namespace sqlite_orm { * LOWER(x) function https://sqlite.org/lang_corefunc.html#lower */ template - struct lower_t : core_function_t, lower_string { + struct lower_t : core_function_t, lower_string { using arg_type = T; arg_type arg; @@ -80,7 +86,7 @@ namespace sqlite_orm { * UPPER(x) function https://sqlite.org/lang_corefunc.html#upper */ template - struct upper_t : core_function_t, upper_string { + struct upper_t : core_function_t, upper_string { using arg_type = T; arg_type arg; @@ -91,7 +97,7 @@ namespace sqlite_orm { /** * CHANGES() function https://sqlite.org/lang_corefunc.html#changes */ - struct changes_t : public core_function_t { + struct changes_t : public core_function_t { operator std::string() const { return "CHANGES"; @@ -108,7 +114,7 @@ namespace sqlite_orm { * TRIM(X) function https://sqlite.org/lang_corefunc.html#trim */ template - struct trim_single_t : core_function_t, trim_string { + struct trim_single_t : core_function_t, trim_string { using arg_type = T; arg_type arg; @@ -120,7 +126,7 @@ namespace sqlite_orm { * TRIM(X,Y) function https://sqlite.org/lang_corefunc.html#trim */ template - struct trim_double_t : core_function_t, trim_string { + struct trim_double_t : core_function_t, trim_string { using args_type = std::tuple; args_type args; @@ -138,7 +144,7 @@ namespace sqlite_orm { * LTRIM(X) function https://sqlite.org/lang_corefunc.html#ltrim */ template - struct ltrim_single_t : core_function_t, ltrim_string { + struct ltrim_single_t : core_function_t, ltrim_string { using arg_type = X; arg_type arg; @@ -150,7 +156,7 @@ namespace sqlite_orm { * LTRIM(X,Y) function https://sqlite.org/lang_corefunc.html#ltrim */ template - struct ltrim_double_t : core_function_t, ltrim_string { + struct ltrim_double_t : core_function_t, ltrim_string { using args_type = std::tuple; args_type args; @@ -168,7 +174,7 @@ namespace sqlite_orm { * RTRIM(X) function https://sqlite.org/lang_corefunc.html#rtrim */ template - struct rtrim_single_t : core_function_t, rtrim_string { + struct rtrim_single_t : core_function_t, rtrim_string { using arg_type = X; arg_type arg; @@ -180,7 +186,7 @@ namespace sqlite_orm { * RTRIM(X,Y) function https://sqlite.org/lang_corefunc.html#rtrim */ template - struct rtrim_double_t : core_function_t, rtrim_string { + struct rtrim_double_t : core_function_t, rtrim_string { using args_type = std::tuple; args_type args; @@ -202,7 +208,7 @@ namespace sqlite_orm { * CHAR(X1,X2,...,XN) function https://sqlite.org/lang_corefunc.html#char */ template - struct char_t_ : core_function_t, char_string { + struct char_t_ : core_function_t, char_string { using args_type = std::tuple; args_type args; @@ -210,7 +216,7 @@ namespace sqlite_orm { char_t_(args_type &&args_): args(std::move(args_)) {} }; - struct random_t : core_function_t, internal::arithmetic_t { + struct random_t : core_function_t, internal::arithmetic_t { operator std::string() const { return "RANDOM"; @@ -226,7 +232,7 @@ namespace sqlite_orm { }; template - struct coalesce_t : core_function_t, coalesce_string { + struct coalesce_t : core_function_t, coalesce_string { using return_type = R; using args_type = std::tuple; @@ -242,7 +248,7 @@ namespace sqlite_orm { }; template - struct date_t : core_function_t, date_string { + struct date_t : core_function_t, date_string { using args_type = std::tuple; static constexpr const size_t args_size = std::tuple_size::value; @@ -259,7 +265,7 @@ namespace sqlite_orm { }; template - struct datetime_t : core_function_t, datetime_string { + struct datetime_t : core_function_t, datetime_string { using args_type = std::tuple; static constexpr const size_t args_size = std::tuple_size::value; @@ -276,7 +282,7 @@ namespace sqlite_orm { }; template - struct julianday_t : core_function_t, internal::arithmetic_t, julianday_string { + struct julianday_t : core_function_t, internal::arithmetic_t, julianday_string { using args_type = std::tuple; static constexpr const size_t args_size = std::tuple_size::value; @@ -294,49 +300,49 @@ namespace sqlite_orm { template< class F, class R, - typename = typename std::enable_if::value>::type> + typename = typename std::enable_if::value>::type> conditions::lesser_than_t operator<(F f, R r) { - return {f, r}; + return {std::move(f), std::move(r)}; } template< class F, class R, - typename = typename std::enable_if::value>::type> + typename = typename std::enable_if::value>::type> conditions::lesser_or_equal_t operator<=(F f, R r) { - return {f, r}; + return {std::move(f), std::move(r)}; } template< class F, class R, - typename = typename std::enable_if::value>::type> + typename = typename std::enable_if::value>::type> conditions::greater_than_t operator>(F f, R r) { - return {f, r}; + return {std::move(f), std::move(r)}; } template< class F, class R, - typename = typename std::enable_if::value>::type> + typename = typename std::enable_if::value>::type> conditions::greater_or_equal_t operator>=(F f, R r) { - return {f, r}; + return {std::move(f), std::move(r)}; } template< class F, class R, - typename = typename std::enable_if::value>::type> + typename = typename std::enable_if::value>::type> conditions::is_equal_t operator==(F f, R r) { - return {f, r}; + return {std::move(f), std::move(r)}; } template< class F, class R, - typename = typename std::enable_if::value>::type> + typename = typename std::enable_if::value>::type> conditions::is_not_equal_t operator!=(F f, R r) { - return {f, r}; + return {std::move(f), std::move(r)}; } inline core_functions::random_t random() { diff --git a/dev/is_base_of_template.h b/dev/is_base_of_template.h new file mode 100644 index 000000000..7b4dbe4d2 --- /dev/null +++ b/dev/is_base_of_template.h @@ -0,0 +1,39 @@ +#pragma once + +#include // std::true_type, std::false_type, std::declval + +namespace sqlite_orm { + + namespace internal { + + /* + * This is because of bug in MSVC, for more information, please visit + * https://stackoverflow.com/questions/34672441/stdis-base-of-for-template-classes/34672753#34672753 + */ +#if defined(_MSC_VER) + template