diff --git a/.github/actions/setup_cache/action.yaml b/.github/actions/setup_cache/action.yaml index ad73d0f..cb9dbde 100644 --- a/.github/actions/setup_cache/action.yaml +++ b/.github/actions/setup_cache/action.yaml @@ -20,7 +20,7 @@ runs: using: "composite" steps: - name: Cache - uses: actions/cache@v2 + uses: actions/cache@v4.0.2 with: # You might want to add .ccache to your cache configuration? path: | diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 8945214..39ea5a5 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -19,7 +19,7 @@ env: jobs: Test: runs-on: ${{ matrix.os }} - continue-on-error: ${{ matrix.os == 'macos-13' }} + continue-on-error: ${{ matrix.os == 'macos-13' || matrix.os == 'macos-14' }} strategy: fail-fast: false # Recommendations: @@ -33,9 +33,9 @@ jobs: os: - ubuntu-20.04 - ubuntu-22.04 - - macos-11 - macos-12 - macos-13 + - macos-14 compiler: # you can specify the version after `-` like "llvm-13.0.0". - llvm-13.0.0 @@ -51,12 +51,12 @@ jobs: exclude: # mingw is determined by this author to be too buggy to support - - os: macos-11 - compiler: gcc-11 - os: macos-12 compiler: gcc-11 - os: macos-13 compiler: gcc-11 + - os: macos-14 + compiler: gcc-11 - os: ubuntu-20.04 compiler: llvm-13.0.0 - os: ubuntu-22.04 @@ -121,14 +121,14 @@ jobs: generator: ${{ matrix.generator }} - name: Setup Cpp - uses: aminya/setup-cpp@v1 + uses: aminya/setup-cpp@v0.37.0 with: compiler: ${{ matrix.compiler }} vcvarsall: ${{ contains(matrix.os, 'windows' )}} cmake: true ninja: true - conan: true + conan: false vcpkg: false ccache: true clangtidy: ${{ env.CLANG_TIDY_VERSION }} @@ -136,10 +136,6 @@ jobs: gcovr: true opencppcoverage: true - - name: Cleanup Conan system packages (they are not properly cached) - run: | - conan remove -f '*/system' - # make sure coverage is only enabled for Debug builds, since it sets -O0 to make sure coverage # has meaningful results - name: Configure CMake @@ -158,19 +154,25 @@ jobs: # Execute tests defined by the CMake configuration. # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail run: | - ctest -C ${{matrix.build_type}} --output-on-failure + ctest -C ${{matrix.build_type}} --output-on-failure -O ../test-result.txt gcovr -j ${{env.nproc}} --delete --root ../ --print-summary --xml-pretty --xml coverage.xml . --gcov-executable '${{ matrix.gcov_executable }}' - name: Windows - Test and coverage if: runner.os == 'Windows' && success() - continue-on-error: ${{ matrix.os == 'macos-13' }} + continue-on-error: ${{ matrix.os == 'macos-13' || matrix.os == 'macos-14' }} working-directory: ./build run: | - OpenCppCoverage.exe --export_type cobertura:coverage.xml --cover_children -- ctest -C ${{matrix.build_type}} --output-on-failure + OpenCppCoverage.exe --export_type cobertura:coverage.xml --cover_children -- ctest -C ${{matrix.build_type}} --output-on-failure -O ../test-result.txt + + - name: Archive test results + uses: actions/upload-artifact@v4 + with: + name: test-results-${{matrix.os}}-${{matrix.compiler}}-${{matrix.generator}}-${{matrix.build_type}}-${{matrix.developer_mode}} + path: test-result.txt - name: CPack if: matrix.package_generator != '' && success() - continue-on-error: ${{ matrix.os == 'macos-13' }} + continue-on-error: ${{ matrix.os == 'macos-13' || matrix.os == 'macos-14' }} working-directory: ./build run: | cpack -C ${{matrix.build_type}} -G ${{matrix.package_generator}} @@ -178,7 +180,7 @@ jobs: - name: Publish Tagged Release uses: softprops/action-gh-release@v1 if: ${{ startsWith(github.ref, 'refs/tags/') && matrix.package_generator != '' && success() }} - continue-on-error: ${{ matrix.os == 'macos-13' }} + continue-on-error: ${{ matrix.os == 'macos-13' || matrix.os == 'macos-14' }} with: files: | build/*-*${{ matrix.build_type }}*-*.* @@ -186,7 +188,7 @@ jobs: - name: Publish to codecov if: success() - continue-on-error: ${{ matrix.os == 'macos-13' }} + continue-on-error: ${{ matrix.os == 'macos-13' || matrix.os == 'macos-14' }} uses: codecov/codecov-action@v4 with: token: ${{ secrets.CODECOV_TOKEN }} @@ -195,7 +197,7 @@ jobs: files: ./build/coverage.xml - name: Raise warning - if: ${{ failure() && matrix.os == 'macos-13' }} + if: ${{ failure() && matrix.os == 'macos-13' || matrix.os == 'macos-14' }} uses: actions/github-script@v7 with: script: | diff --git a/.gitignore b/.gitignore index 06ad4b3..cd3051f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,7 @@ -.vscode/ *.exe **/*.exe -cmake_install.cmake -CMakeCache.txt -CMakeFiles/ -Makefile -mysql-connector-c++-1.1.13/ -cmake/ -out/ .vs/ .vscode/ -WSL_Build/ +lib/include/ORM/ORM-version.hpp build*/ **/.DS_Store \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 8401cec..60e4f68 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,7 +44,8 @@ endif() if(RUN_TESTS) include(CTest) enable_testing() - add_subdirectory("tests/") + + add_subdirectory("tests") endif() # Generate example source code diff --git a/README.md b/README.md index 708b227..af3f72b 100644 --- a/README.md +++ b/README.md @@ -143,19 +143,27 @@ Check [example/](https://github.com/WebFrame/ORM-Abstract/blob/main/example) for [![LinkedIn](https://img.shields.io/badge/linkedin-%230077B5.svg?logo=linkedin&logoColor=white)](https://www.linkedin.com/in/alex-tsvetanov/) # ToDo -1. Limits fix - - ```sql - [LIMIT [offset_value] number_rows | LIMIT number_rows OFFSET offset_value] - ``` +1. Properties + - ``== nullptr`` + - ``!= nullptr`` 1. Result type - Member pointers and standard types - Get references by member pointer - Get references by table class - Get references by index 1. Rules + - EXISTS - IN / NOT IN 1. CRUD operations + - ~~Create / insert~~ - Read / select + - ~~ALL~~ + - ~~JOIN~~ + - ~~WHERE~~ + - ~~LIMIT~~ + - DISTINCT / DISTINCTROW + - GROUP BY / HAVING + - ORDER BY - COUNT(*) / COUNT(...) ```sql SELECT [ ALL | DISTINCT | DISTINCTROW ] @@ -172,11 +180,18 @@ Check [example/](https://github.com/WebFrame/ORM-Abstract/blob/main/example) for [HAVING condition] [ORDER BY expression [ ASC | DESC ]] [LIMIT [offset_value] number_rows | LIMIT number_rows OFFSET offset_value] - INTO [ OUTFILE 'file_name' options + [INTO [ OUTFILE 'file_name' options | DUMPFILE 'file_name' | @variable1, @variable2, ... @variable_n] [FOR UPDATE | LOCK IN SHARE MODE]; ``` + - Update / update + - ~~WHERE~~ + - ORDER BY + - Delete / delete + - WHERE + - ORDER BY + - LIMIT 1. Transferring the abstract database implementation from v1.1 to v2 using the new SQL-free query style 1. Implement free MySQL driver 1. Implement free MongoDB driver @@ -184,4 +199,4 @@ Check [example/](https://github.com/WebFrame/ORM-Abstract/blob/main/example) for - Keep track of latest migration done - Apply new migrations if any - C++ Migrations tool -1. Run tests with SQL and NoSQL databases +1. Run tests with SQL and NoSQL databases \ No newline at end of file diff --git a/example/ORM.cpp b/example/ORM.cpp index d3c359a..358ea5c 100644 --- a/example/ORM.cpp +++ b/example/ORM.cpp @@ -8,64 +8,32 @@ using namespace std; using namespace webframe::ORM::literals; -template constexpr void create_table_helper() -{ - if constexpr (i >= pfr::tuple_size::value) - { - return; - } - if constexpr (std::derived_from(std::declval())), webframe::ORM::details::property>) - { - constexpr std::string_view column_name = decltype(pfr::get(std::declval()))::_name(); - using ColumnType = typename decltype(pfr::get(std::declval()))::var_t; - - std::cout << MockDB::MockDB::delim << /*T::table_name << "." <<*/ column_name << " " << typeid(ColumnType).name(); - } - if constexpr (i + 1 < pfr::tuple_size::value) - { - std::cout << ","; - create_table_helper(); - } -} - -template void create_table() -{ - std::cout << "CREATE TABLE " << T::table_name << "("; - create_table_helper(); - std::cout << "\n);"; -} - -#define my_assert(x) \ - if (!(x)) \ - { \ - std::cout << "\"" << #x << "\" failed." << std::endl; \ - } - int main() { - create_table(); - std::cout << std::endl << std::endl; - - User alex = webframe::ORM::Table::tuple_to_struct(webframe::ORM::Table::to_tuple((INTEGER<>)(0), (TEXT<>)("Alex"))); - my_assert(alex.id == 0); - my_assert(alex.username == "Alex"); + User test; + std::cout << test.id.name() << std::endl; + test.id = 5; + std::cout << test.id << std::endl; + test.id += 10; + std::cout << test.id << std::endl; - MockDB::MockDB db; - std::cout << (db << Utils::insert_new_user)("Name") << std::endl; - std::cout << std::endl; - std::cout << (db << Utils::insert_new_user_with_id_placeholder)(5, "Name") << std::endl; - std::cout << std::endl; - std::cout << (db << Utils::insert_new_user_with_id_placeholder)(5, "Name", 6, "alex") << std::endl; + std::apply([](auto&&... args) { ((std::cout << typeid(args).name() << std::endl), ...); }, decltype(User::insert_new_user_with_name)::parameters_type()); + std::apply([](auto&&... args) { ((std::cout << typeid(args).name() << std::endl), ...); }, User::insert_new_user_with_name.get_columns()); + std::apply([](auto&&... args) { ((std::cout << typeid(args).name() << std::endl), ...); }, User::insert_new_user_with_name.get_values()); + std::apply([](auto&&... args) { ((std::cout << typeid(args).name() << std::endl), ...); }, User::insert_new_user_with_name.get_update_statements()); std::cout << std::endl; - std::cout << (db << Utils::get_all_posts_with_their_assosiated_users)() << std::endl; + std::apply([](auto&&... args) { ((std::cout << typeid(args).name() << std::endl), ...); }, decltype(User::insert_into_select_test)::parameters_type()); + std::apply([](auto&&... args) { ((std::cout << typeid(args).name() << std::endl), ...); }, User::insert_into_select_test.get_columns()); + std::apply([](auto&&... args) { ((std::cout << typeid(args).name() << std::endl), ...); }, User::insert_into_select_test.get_update_statements()); std::cout << std::endl; - std::cout << (db << Utils::get_all_users_with_id_above)(5) << std::endl; + std::apply([](auto&&... args) { ((std::cout << typeid(args).name() << std::endl), ...); }, User::update_test.get_orders()); + std::apply([](auto&&... args) { ((std::cout << typeid(args).name() << std::endl), ...); }, User::update_test.get_limits()); std::cout << std::endl; - std::cout << (db << Utils::update_something)(5, 10) << std::endl; - std::cout << std::endl; - std::cout << (db << Utils::update_with_optimized_rules)(5, 10) << std::endl; - std::cout << std::endl; - std::cout << (db << Utils::delete_all_posts)(5, 5) << std::endl; + std::apply([](auto&&... args) { ((std::cout << typeid(args).name() << std::endl), ...); }, User::update_test2.get_orders()); + std::apply([](auto&&... args) { ((std::cout << typeid(args).name() << std::endl), ...); }, User::update_test2.get_limits()); std::cout << std::endl; + std::apply([](auto&&... args) { ((std::cout << typeid(args).name() << std::endl), ...); }, User::delete_all.get_orders()); + std::apply([](auto&&... args) { ((std::cout << typeid(args).name() << std::endl), ...); }, User::update_test.get_limits()); + return 0; } diff --git a/example/ORM_original.cpp b/example/ORM_original.cpp new file mode 100644 index 0000000..cfdabbb --- /dev/null +++ b/example/ORM_original.cpp @@ -0,0 +1,74 @@ +// ORM.cpp : Defines the entry point for the testing application. +// + +#include +#include +#include "users/users.hpp" + +using namespace std; +using namespace webframe::ORM::literals; + +template constexpr void create_table_helper() +{ + if constexpr (i >= pfr::tuple_size::value) + { + return; + } + if constexpr (std::derived_from(std::declval())), webframe::ORM::details::property>) + { + constexpr std::string_view column_name = decltype(pfr::get(std::declval()))::_name(); + using ColumnType = typename decltype(pfr::get(std::declval()))::var_t; + + std::cout << column_name << " " << typeid(ColumnType).name() << std::endl; + } + if constexpr (i + 1 < pfr::tuple_size::value) + { + create_table_helper(); + } +} + +template void create_table() +{ + create_table_helper(); +} + +#define my_assert(x) \ + if (!(x)) \ + { \ + std::cout << "\"" << #x << "\" failed." << std::endl; \ + } + +int main() +{ + std::cout << typeid(P<&UserPost::post> == P<&Post::id>).name(); + User test; + std::cout << test.id._name() << std::endl; + test.id = 5; + std::cout << test.id << std::endl; + test.id += 10; + std::cout << test.id << std::endl; + create_table(); + my_assert(webframe::ORM::Table::get_index_by_column("id"sv) == 0); + my_assert(webframe::ORM::Table::get_index_by_column("username"sv) == 1); + my_assert(webframe::ORM::Table::get_index_by_column(decltype(std::declval().username)::_name()) == 1); + std::cout << webframe::ORM::Table::get_index_by_column("id"sv) << std::endl; + std::cout << webframe::ORM::Table::get_index_by_column("username"sv) << std::endl; + User alex = webframe::ORM::Table::tuple_to_struct(webframe::ORM::Table::to_tuple(0, "Alex")); + my_assert(alex.id == 0); + my_assert(alex.username == "Alex"); + std::cout << alex.id << " " << std::string(alex.username) << std::endl; + + webframe::ORM::relationship y; + + std::cout << typeid(!(P<&UserPost::author> == P<&User::id> && P<&UserPost::post> == P<&Post::id>)).name() << std::endl; + std::cout << typeid(!((P<&UserPost::author> == P<&User::id>)^(P<&UserPost::post> == P<&Post::id>))).name() << std::endl; + MockDB::MockDB db; + std::cout << (db << Utils::insert_new_user)("Name") << std::endl; + std::cout << (db << Utils::insert_new_user_with_id_placeholder)(5, "Name") << std::endl; + std::cout << (db << Utils::insert_new_user_with_id_placeholder)(5, "Name", 6, "alex") << std::endl; + std::cout << (db << Utils::get_all_posts_with_their_assosiated_users)() << std::endl; + std::cout << (db << Utils::get_all_users_with_id_above)(5) << std::endl; + std::cout << (db << Utils::update_something)(5, 10) << std::endl; + std::cout << (db << Utils::update_with_optimized_rules)(5, 10) << std::endl; + return 0; +} diff --git a/example/users/users.hpp b/example/users/users.hpp index cd34c9b..c22d86c 100644 --- a/example/users/users.hpp +++ b/example/users/users.hpp @@ -3,66 +3,23 @@ #include using namespace webframe::ORM; - -template class Utils; - -struct Post -{ - static constexpr std::string_view table_name = "Posts"; - property, "id"> id; - property, "content"> content; -}; +using namespace webframe::ORM::placeholders; struct User { - static constexpr std::string_view table_name = "Users"; - property, "id"> id; - property, "username"> username; - relationship posts; -}; + static constexpr std::string_view entity_name = "Users"; + property id; + property, "name"> name; -struct UserPost -{ - static constexpr std::string_view table_name = "UserPosts"; - property>, "id"> id; - relationship author; - relationship post; -}; + static constexpr auto insert_new_user_with_name = + webframe::ORM::insert<&User::name>.values(_1).on_duplicate_key_update(DB<& User::name> += "_copy"); -template <> class Utils : public webframe::ORM::Table -{ - public: - static constexpr auto insert_new_user_with_id_placeholder = webframe::ORM::insert<&User::id, &User::username>; - static constexpr auto insert_new_user = webframe::ORM::insert<&User::username>; - static constexpr auto get_all_users_with_id_above = - webframe::ORM::select.where(P<&User::id> > P>).limit(15_per_page & 5_page).limit(5_page & 15_per_page); - static constexpr auto update_with_optimized_rules = webframe::ORM::update(P<& User::id> = P>, P<& User::username> = "Test") - .where(!(P<&User::id> > P>)) - .order_by<&User::id, modes::ASC>() - .limit(5_page & 15_per_page); - static constexpr auto update_something = - webframe::ORM::update(P<& User::id> = P>, P<& User::username> = "Test").where(P<&User::id> > P>); - static constexpr auto update_something_2 = - webframe::ORM::update(P<& User::id> = P>).update(P<& User::username> = "Test").where(P<&User::id> > P>); -}; + static constexpr auto insert_into_select_test = + webframe::ORM::insert<&User::name>.into(insert_new_user_with_name).on_duplicate_key_update(DB<& User::name> += "_copy"); -template <> class Utils : public webframe::ORM::Table -{ - public: - static constexpr auto get_all_posts_with_their_assosiated_users = - webframe::ORM::select - .join(!(P<&UserPost::post> == P<&Post::id> && P<&UserPost::post> != P<&Post::id>)) - .limit(15_per_page & 5_page) - .limit(5_page & 15_per_page) - .group_by<&UserPost::id>(P<&Post::id> == 5) - .group_by<&UserPost::id>() - .order_by<&UserPost::id, modes::ASC, &UserPost::id, modes::DESC, &UserPost::id, modes::DEFAULT, &UserPost::id>() - ; - static constexpr auto delete_all_posts = - webframe::ORM::deleteq - .where(P<&UserPost::id> > P>) - .where(P<&UserPost::id> != P) - .order_by<&UserPost::id, modes::ASC, &UserPost::id, modes::DESC, &UserPost::id, modes::DEFAULT, &UserPost::id>() - .limit(5_page & 15_per_page) - ; + static constexpr auto update_test = + webframe::ORM::update.where(DB<&User::name> == "_copy").order_by<&User::name, ASC>().order_by<&User::id>().limit<4>(); + static constexpr auto update_test2 = + webframe::ORM::update.where(DB<&User::name> == "_copy").order_by<&User::name, ASC>().order_by<&User::id>().limit<_1>(); + static constexpr auto delete_all = webframe::ORM::delete_from.where(DB<&User::name> != "").order_by<&User::name, ASC>().order_by<&User::id>(); }; diff --git a/example/users/users_original.hpp b/example/users/users_original.hpp new file mode 100644 index 0000000..3265d14 --- /dev/null +++ b/example/users/users_original.hpp @@ -0,0 +1,55 @@ +#pragma once +#include +#include + +using namespace webframe::ORM; + +template class Utils; + +struct Post +{ + static constexpr std::string_view entity_name = "Posts"; + property id; + property content; +}; + +struct User +{ + static constexpr std::string_view entity_name = "Users"; + property id; + property username; + relationship posts; +}; + +struct UserPost +{ + static constexpr std::string_view entity_name = "UserPosts"; + property id; + relationship author; + relationship post; +}; + +template <> class Utils : public webframe::ORM::Table +{ + public: + static constexpr auto insert_new_user_with_id_placeholder = webframe::ORM::insert, &User::username>; + static constexpr auto insert_new_user = webframe::ORM::insert<&User::username>; + static constexpr auto get_all_users_with_id_above = + webframe::ORM::select<&User::id, &User::username>.where(P<&User::id> > P>).limit(15_per_page & 5_page).limit(5_page & 15_per_page); + static constexpr auto update_with_optimized_rules = + webframe::ORM::update(P<& User::id> = P>, P<& User::username> = "Test").where(!(P<&User::id> > P>)); + static constexpr auto update_something = + webframe::ORM::update(P<& User::id> = P>, P<& User::username> = "Test").where(P<&User::id> > P>); + static constexpr auto update_something_2 = + webframe::ORM::update(P<& User::id> = P>).update(P<& User::username> = "Test").where(P<&User::id> > P>); +}; + +template <> class Utils : public webframe::ORM::Table +{ + public: + static constexpr auto get_all_posts_with_their_assosiated_users = webframe::ORM::select<&UserPost::id, &User::id, &User::username, &Post::id, &Post::content> + .join(P<&UserPost::post> == P<&Post::id>) + .limit(15_per_page & 5_page) + .limit(5_page & 15_per_page) + ; +}; diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 74fca50..dd65a61 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -1,58 +1,6 @@ cmake_minimum_required (VERSION 3.14) -SET(SOURCE_COMPONENTS - table - limits - ORM-version - details/warnings - details/orm_tuple - details/fundamental_type - details/member_pointer - details/result_type - details/string_literal - CRUD/utils - CRUD/select - CRUD/insert - db/connectors/interface - db/connectors/MockDB/data - db/connectors/MockDB/init - rules - fields -) - -SET(HEADER_COMPONENTS - rules - fields - details/string_literal - details/result_type - details/fundamental_type - details/member_pointer - details/warnings - details/select - limits - db/connectors/interface - table -) - -foreach(component ${HEADER_COMPONENTS}) - LIST(APPEND ORM_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include/ORM/${component}.hpp) -endforeach() - -foreach(component ${SOURCE_COMPONENTS}) - string(REPLACE "/" "_" lib_name ${component}) - - add_library(Webframe_ORM_${lib_name} OBJECT ${CMAKE_CURRENT_SOURCE_DIR}/src/ORM/${component}.cpp) - target_include_directories(Webframe_ORM_${lib_name} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/pfr/include") - set_target_properties(Webframe_ORM_${lib_name} PROPERTIES LINKER_LANGUAGE CXX) - - LIST(APPEND libs Webframe_ORM_${lib_name}) - LIST(APPEND ORM_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/ORM/${component}.cpp) -endforeach() - -add_library(Webframe_ORM STATIC src/ORM/ORM.cpp) -target_include_directories(Webframe_ORM PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/pfr/include") -set_target_properties(Webframe_ORM PROPERTIES LINKER_LANGUAGE CXX) -target_link_libraries(Webframe_ORM PUBLIC ${libs}) +add_subdirectory(src/ORM) install(TARGETS Webframe_ORM DESTINATION ${PROJECT_BINARY_DIR}) diff --git a/lib/include/ORM/CRUD/delete.hpp b/lib/include/ORM/CRUD/delete.hpp deleted file mode 100644 index be871d6..0000000 --- a/lib/include/ORM/CRUD/delete.hpp +++ /dev/null @@ -1,128 +0,0 @@ -#pragma once - -#include "../details/orm_tuple.hpp" -#include "../details/member_pointer.hpp" -#include "utils.hpp" - -namespace webframe::ORM::CRUD -{ - template class delete_query : public details::delete_query_t - { - Filters filters; - Limits limits; - Ordering ordering; - - public: - using table = Table; - using tables = - decltype(webframe::ORM::details::orm_tuple(typename details::unique_tables_t::properties(), - typename webframe::ORM::details::get_properties::properties()))>::orm_tuple_type())); - using properties = decltype(webframe::ORM::details::orm_tuple(std::tuple_cat(typename webframe::ORM::details::get_properties::properties()))); - - static constexpr size_t where_size = Filters::size; - static constexpr size_t order_size = Ordering::size; - static constexpr size_t limit_size = Limits::size; - - constexpr delete_query() : filters(), limits(), ordering() - { - } - constexpr delete_query(Filters _filters, Ordering _ordering, Limits _limits) : filters(_filters), limits(_limits), ordering(_ordering) - { - } - - constexpr inline Filters wheres() const - { - return filters; - } - constexpr inline Ordering order_clauses() const - { - return ordering; - } - constexpr inline Limits limit_clauses() const - { - return limits; - } - - template constexpr inline auto where(Ts... new_filters) const - { - using new_wheres = decltype(webframe::ORM::details::orm_tuple(std::tuple_cat(filters.to_tuple(), std::tuple(new_filters...)))); - return delete_query( - webframe::ORM::details::orm_tuple(std::tuple_cat(filters.to_tuple(), std::tuple(new_filters...))), ordering, limits); - } - - protected: - template constexpr inline auto order_by_helper1() const - { - using tuple_type = decltype(std::tuple_cat( - std::declval().to_tuple(), std::declval())>>())); - using orm_tuple_type = decltype(webframe::ORM::details::orm_tuple(std::declval())); - orm_tuple_type orm_new_tuple(std::tuple_cat(ordering.to_tuple(), std::make_tuple(webframe::ORM::OrderBy()))); - return delete_query(filters, orm_new_tuple, limits); - } - - template constexpr inline auto order_by_helper2() const - { - using tuple_type = - decltype(std::tuple_cat(std::declval().to_tuple(), std::declval())>>())); - using orm_tuple_type = decltype(webframe::ORM::details::orm_tuple(std::declval())); - orm_tuple_type orm_new_tuple(std::tuple_cat(ordering.to_tuple(), std::make_tuple(webframe::ORM::OrderBy()))); - return delete_query(filters, orm_new_tuple, limits); - } - - template constexpr inline auto order_by_impl(std::index_sequence) const - { - constexpr auto args = webframe::ORM::details::orm_tuple(std::make_tuple(Args...)); - if constexpr (sizeof...(Args) > 0) - { - if constexpr ( - webframe::ORM::details::is_property && std::is_same_v()), webframe::ORM::modes::order>) - { - return order_by_helper2().template order_by_impl(std::make_index_sequence{}); - } - if constexpr ( - webframe::ORM::details::is_property && !std::is_same_v()), webframe::ORM::modes::order>) - { - return order_by_helper1().template order_by_impl(std::make_index_sequence{}); - } - } - if constexpr (sizeof...(Args) > 0 && !webframe::ORM::details::is_property) - { - return order_by_impl(std::make_index_sequence{}); - } - if constexpr (sizeof...(Args) == 0) - { - if constexpr (webframe::ORM::details::is_property) - { - return order_by_helper1(); - } - if constexpr (!webframe::ORM::details::is_property) - { - return *this; - } - } - } - - public: - template constexpr inline auto order_by() const - { - return order_by_impl(std::make_index_sequence{}); - } - - template constexpr inline auto limit(Ts... new_limits) const - { - using new_limits_t = decltype(webframe::ORM::details::orm_tuple(std::tuple_cat(limits.to_tuple(), std::tuple(new_limits...)))); - return delete_query( - filters, ordering, webframe::ORM::details::orm_tuple(std::tuple_cat(limits.to_tuple(), std::tuple(new_limits...)))); - } - - template friend class delete_query; - }; -} // namespace webframe::ORM::CRUD - -namespace webframe::ORM -{ - template - static constexpr auto deleteq = CRUD::delete_query, details::orm_tuple<>, details::orm_tuple<>>( - details::orm_tuple(), details::orm_tuple(), details::orm_tuple()); -} diff --git a/lib/include/ORM/CRUD/insert.hpp b/lib/include/ORM/CRUD/insert.hpp deleted file mode 100644 index 1f79fd2..0000000 --- a/lib/include/ORM/CRUD/insert.hpp +++ /dev/null @@ -1,31 +0,0 @@ -/** - * @file select.hpp - * @brief Functional-programming-like select queries - * @author Alex Tsvetanov - * @date 2023-08-31 - ***********************************************/ - -#pragma once - -#include -#include -#include -#include "../details/result_type.hpp" -#include "utils.hpp" - -namespace webframe::ORM::CRUD -{ - template class insert_query : public details::insert_query_t - { - public: - using properties = - typename webframe::ORM::details::get_placeholders_and_properties>::orm_placeholders; - using tables = typename details::unique_tables::orm_tuple_type; - static constexpr auto signature = webframe::ORM::details::orm_tuple(std::make_tuple(Properties...)); - }; -} // namespace webframe::ORM::CRUD -namespace webframe::ORM -{ - template static constexpr auto insert = webframe::ORM::CRUD::insert_query(); -} -#include "../../../src/ORM/CRUD/insert.cpp" diff --git a/lib/include/ORM/CRUD/select.hpp b/lib/include/ORM/CRUD/select.hpp deleted file mode 100644 index a30f980..0000000 --- a/lib/include/ORM/CRUD/select.hpp +++ /dev/null @@ -1,117 +0,0 @@ -/** - * @file select.hpp - * @brief Functional-programming-like select queries - * @author Alex Tsvetanov - * @date 2023-08-31 - ***********************************************/ - -#pragma once - -#include -#include -#include "../details/result_type.hpp" -#include "utils.hpp" -#include "../join_rule.hpp" - -namespace webframe::ORM::CRUD -{ - template - class select_query : public details::select_query_t - { - protected: - Result properties_to_select_query; - Rules joins; - Filters filters; - Limits limits; - Grouping groupings; - Ordering ordering; - - public: - static constexpr webframe::ORM::modes::select mode = row_way; - using properties = typename webframe::ORM::details::get_placeholders::properties(), - typename webframe::ORM::details::get_properties::properties(), - typename webframe::ORM::details::get_properties::properties()))>::orm_placeholders; - using Response = Result; - using Joins = Rules; - using Wheres = Filters; - using Limitations = Limits; - using Groupings = Grouping; - using OrderBy = Ordering; - - constexpr select_query(Result _properties_to_select_query, Rules _joins, Filters _filters, Limits _limits, Grouping _groupings, Ordering _ordering) - : properties_to_select_query(_properties_to_select_query), joins(_joins), filters(_filters), limits(_limits), groupings(_groupings), - ordering(_ordering) - { - } - - template constexpr inline auto join(Ts...) const; - - template constexpr inline auto where(Ts...) const; - - template constexpr inline auto limit(Ts...) const; - - template constexpr inline auto group_by(auto) const; - - template constexpr inline auto group_by() const; - - protected: - template constexpr inline auto order_by_impl(std::index_sequence) const; - - template constexpr inline auto order_by_helper1() const; - - template constexpr inline auto order_by_helper2() const; - - public: - template constexpr inline auto order_by() const; - - constexpr Response selected_properties() const - { - return properties_to_select_query; - } - constexpr Joins join_clauses() const - { - return joins; - } - constexpr Wheres where_clauses() const - { - return filters; - } - constexpr Limits limit_clauses() const - { - return limits; - } - constexpr Grouping group_clauses() const - { - return groupings; - } - constexpr Ordering order_clauses() const - { - return ordering; - } - - template friend class select_query; - }; -} // namespace webframe::ORM::CRUD -namespace webframe::ORM -{ - template - static constexpr auto select = CRUD::select_query< - mode, - decltype(webframe::ORM::details::result_t::create(args...)), // properties to select - webframe::ORM::details::orm_tuple<>, // Join clauses - webframe::ORM::details::orm_tuple<>, // Where clauses - webframe::ORM::details::orm_tuple<>, // Limit clauses - webframe::ORM::details::orm_tuple<>, // Group-by clauses - webframe::ORM::details::orm_tuple<> // Order-by clauses - >( - webframe::ORM::details::result_t::create(args...), // properties to select - webframe::ORM::details::orm_tuple<>(), // Join clauses - webframe::ORM::details::orm_tuple<>(), // Where clauses - webframe::ORM::details::orm_tuple<>(), // Limit clauses - webframe::ORM::details::orm_tuple<>(), // Group-by clauses - webframe::ORM::details::orm_tuple<>() // Order-by clauses - ); -} - -#include "../../../src/ORM/CRUD/select.cpp" diff --git a/lib/include/ORM/CRUD/update.hpp b/lib/include/ORM/CRUD/update.hpp deleted file mode 100644 index ee9d4f0..0000000 --- a/lib/include/ORM/CRUD/update.hpp +++ /dev/null @@ -1,146 +0,0 @@ -#pragma once - -#include "../details/orm_tuple.hpp" -#include "../details/member_pointer.hpp" -#include "utils.hpp" - -namespace webframe::ORM::CRUD -{ - template class update_query : public details::update_query_t - { - Statements statements; - Filters filters; - Limits limits; - Ordering ordering; - - public: - using tables = - decltype(webframe::ORM::details::orm_tuple(typename details::unique_tables_t::properties(), - typename webframe::ORM::details::get_properties::properties(), - typename webframe::ORM::details::get_properties::properties()))>::orm_tuple_type())); - using properties = decltype(webframe::ORM::details::orm_tuple(std::tuple_cat( - typename webframe::ORM::details::get_placeholders::orm_tuple_type>::placeholders(), - typename webframe::ORM::details::get_properties::properties()))); - - static constexpr size_t size = Statements::size; - static constexpr size_t where_size = Filters::size; - static constexpr size_t order_size = Ordering::size; - static constexpr size_t limit_size = Limits::size; - - constexpr update_query() : statements(), filters(), limits(), ordering() - { - } - constexpr update_query(Statements _statements, Filters _filters, Ordering _ordering, Limits _limits) - : statements(_statements), filters(_filters), limits(_limits), ordering(_ordering) - { - } - - constexpr inline Statements updates() const - { - return statements; - } - constexpr inline Filters wheres() const - { - return filters; - } - constexpr inline Ordering order_clauses() const - { - return ordering; - } - constexpr inline Limits limit_clauses() const - { - return limits; - } - - template constexpr inline auto update(Ts... new_statements) const - { - using new_statements_t = decltype(webframe::ORM::details::orm_tuple(std::tuple_cat(statements.to_tuple(), std::tuple(new_statements...)))); - return update_query( - webframe::ORM::details::orm_tuple(std::tuple_cat(statements.to_tuple(), std::tuple(new_statements...))), filters, ordering, limits); - } - - template constexpr inline auto where(Ts... new_filters) const - { - using new_wheres = decltype(webframe::ORM::details::orm_tuple(std::tuple_cat(filters.to_tuple(), std::tuple(new_filters...)))); - return update_query( - statements, webframe::ORM::details::orm_tuple(std::tuple_cat(filters.to_tuple(), std::tuple(new_filters...))), ordering, limits); - } - - protected: - template constexpr inline auto order_by_helper1() const - { - using tuple_type = decltype(std::tuple_cat( - std::declval().to_tuple(), std::declval())>>())); - using orm_tuple_type = decltype(webframe::ORM::details::orm_tuple(std::declval())); - orm_tuple_type orm_new_tuple(std::tuple_cat(ordering.to_tuple(), std::make_tuple(webframe::ORM::OrderBy()))); - return update_query(statements, filters, orm_new_tuple, limits); - } - - template constexpr inline auto order_by_helper2() const - { - using tuple_type = - decltype(std::tuple_cat(std::declval().to_tuple(), std::declval())>>())); - using orm_tuple_type = decltype(webframe::ORM::details::orm_tuple(std::declval())); - orm_tuple_type orm_new_tuple(std::tuple_cat(ordering.to_tuple(), std::make_tuple(webframe::ORM::OrderBy()))); - return update_query(statements, filters, orm_new_tuple, limits); - } - - template constexpr inline auto order_by_impl(std::index_sequence) const - { - constexpr auto args = webframe::ORM::details::orm_tuple(std::make_tuple(Args...)); - if constexpr (sizeof...(Args) > 0) - { - if constexpr ( - webframe::ORM::details::is_property && std::is_same_v()), webframe::ORM::modes::order>) - { - return order_by_helper2().template order_by_impl(std::make_index_sequence{}); - } - if constexpr ( - webframe::ORM::details::is_property && !std::is_same_v()), webframe::ORM::modes::order>) - { - return order_by_helper1().template order_by_impl(std::make_index_sequence{}); - } - } - if constexpr (sizeof...(Args) > 0 && !webframe::ORM::details::is_property) - { - return order_by_impl(std::make_index_sequence{}); - } - if constexpr (sizeof...(Args) == 0) - { - if constexpr (webframe::ORM::details::is_property) - { - return order_by_helper1(); - } - if constexpr (!webframe::ORM::details::is_property) - { - return *this; - } - } - } - - public: - template constexpr inline auto order_by() const - { - return order_by_impl(std::make_index_sequence{}); - } - - template constexpr inline auto limit(Ts... new_limits) const - { - using new_limits_t = decltype(webframe::ORM::details::orm_tuple(std::tuple_cat(limits.to_tuple(), std::tuple(new_limits...)))); - return update_query( - statements, filters, ordering, webframe::ORM::details::orm_tuple(std::tuple_cat(limits.to_tuple(), std::tuple(new_limits...)))); - } - - template friend class update_query; - }; -} // namespace webframe::ORM::CRUD - -namespace webframe::ORM -{ - static constexpr auto update(auto... Statements) - { - return CRUD::update_query, details::orm_tuple<>, details::orm_tuple<>, details::orm_tuple<>>( - details::orm_tuple(std::tuple(Statements...)), details::orm_tuple(), details::orm_tuple(), details::orm_tuple()); - } -} // namespace webframe::ORM diff --git a/lib/include/ORM/CRUD/utils.hpp b/lib/include/ORM/CRUD/utils.hpp deleted file mode 100644 index a39e9d0..0000000 --- a/lib/include/ORM/CRUD/utils.hpp +++ /dev/null @@ -1,333 +0,0 @@ -#pragma once - -#include -#include "../details/member_pointer.hpp" -#include "../db/connectors/interface.hpp" -#include "../details/orm_tuple.hpp" - -namespace webframe::ORM::CRUD::details -{ - - // Unique tables utils - template struct contains; - - template struct contains> - { - static constexpr inline bool check() - { - return (std::is_same_v || ...); - } - }; - - template struct contains> - { - static constexpr inline bool check() - { - return false; - } - }; - - template constexpr bool contains_v = contains::check(); - - template - concept not_new_type = contains_v; - - template - concept new_type = !not_new_type; - - template struct type_container - { - using type = T; - constexpr type_container() - { - } - }; - - template struct unique_first_tables; - - template <> struct unique_first_tables> - { - static constexpr auto empty_tuple() - { - return type_container>(); - } - using types = std::tuple<>; - using orm_tuple_type = decltype(webframe::ORM::details::orm_tuple(std::declval>())); - }; - - template struct unique_first_tables> - { - static constexpr auto empty_tuple() - { - using T = decltype(std::declval()._1); - using Ts = webframe::ORM::details::orm_tuple; - // skip non-property things - if constexpr (!webframe::ORM::details::is_property || webframe::ORM::details::is_orm_placeholder) - { - if constexpr (Ts::size == 0) - { - return type_container>(); - } - else - { - return unique_first_tables::empty_tuple(); - } - } - if constexpr (webframe::ORM::details::is_property && !webframe::ORM::details::is_orm_placeholder) - { - // so we end up with a property - if constexpr (Ts::size == 0) - { - return type_container::Table>>(); - } - - constexpr auto empty_tuple_of_righter_tables = unique_first_tables::empty_tuple(); - - if constexpr (new_type::Table, typename decltype(empty_tuple_of_righter_tables)::type>) - { - return type_container::Table>(), typename decltype(empty_tuple_of_righter_tables)::type()))>(); - } - - if constexpr (not_new_type::Table, typename decltype(empty_tuple_of_righter_tables)::type>) - { - return empty_tuple_of_righter_tables; - } - } - } - using types = typename decltype(empty_tuple())::type; - using orm_tuple_type = decltype(webframe::ORM::details::orm_tuple(std::declval())); - }; - - template struct second_properties; - - template struct second_properties> - { - static constexpr auto empty_tuple() - { - using T = decltype(std::declval()._2); - using Ts = webframe::ORM::details::orm_tuple; - // constexpr bool is_property = webframe::ORM::details::is_property; - // skip property things - // if constexpr (is_property) { - // if constexpr (Ts::size == 0) - // return type_container>(); - // if constexpr (Ts::size != 0) - // return second_properties::empty_tuple(); - // } - // if constexpr (!is_property) - { - // so we end up with a property - if constexpr (Ts::size == 0) - { - return type_container>(); - } - - constexpr auto empty_tuple_of_righter_tables = second_properties::empty_tuple(); - - return type_container(), typename decltype(empty_tuple_of_righter_tables)::type()))>(); - } - static_assert(true, "balo si e mamata"); - } - using types = typename decltype(empty_tuple())::type; - using orm_tuple_type = decltype(webframe::ORM::details::orm_tuple(std::declval())); - }; - - template <> struct second_properties> - { - static constexpr type_container> empty_tuple() - { - return type_container>(); - } - using types = typename decltype(empty_tuple())::type; - using orm_tuple_type = decltype(webframe::ORM::details::orm_tuple(std::declval())); - }; - - // unique tables using mem_ptr - template struct unique_tables; - - template <> struct unique_tables<> - { - static constexpr auto empty_tuple() - { - return type_container>(); - } - }; - - template struct unique_tables - { - static constexpr auto empty_tuple() - { - // skip non-property things - if constexpr (!webframe::ORM::details::is_property || webframe::ORM::details::is_orm_placeholder) - { - if constexpr (sizeof...(Ts) == 0) - { - return type_container>(); - } - else - { - return unique_tables::empty_tuple(); - } - } - if constexpr (webframe::ORM::details::is_property && !webframe::ORM::details::is_orm_placeholder) - { - // so we end up with a property - if constexpr (sizeof...(Ts) == 0) - { - return type_container::Table>>(); - } - - constexpr auto empty_tuple_of_righter_tables = unique_tables::empty_tuple(); - - if constexpr (new_type::Table, typename decltype(empty_tuple_of_righter_tables)::type>) - { - return type_container::Table>(), typename decltype(empty_tuple_of_righter_tables)::type()))>(); - } - - if constexpr (not_new_type::Table, typename decltype(empty_tuple_of_righter_tables)::type>) - { - return empty_tuple_of_righter_tables; - } - } - } - using types = typename decltype(empty_tuple())::type; - using orm_tuple_type = decltype(webframe::ORM::details::orm_tuple(std::declval())); - }; - - // unique tables using tuple - template struct unique_tables_t; - - template struct unique_tables_t> - { - static constexpr auto empty_tuple() - { - return type_container>(); - } - using types = typename unique_tables_t>::types; - using orm_tuple_type = typename unique_tables_t>::orm_tuple_type; - }; - - template <> struct unique_tables_t> - { - static constexpr auto empty_tuple() - { - return type_container>(); - } - using types = std::tuple<>; - using orm_tuple_type = decltype(webframe::ORM::details::orm_tuple(std::declval>())); - }; - - template struct unique_tables_t> - { - static constexpr auto empty_tuple() - { - // skip non-property things - if constexpr (!webframe::ORM::details::is_property || webframe::ORM::details::is_orm_placeholder) - { - if constexpr (sizeof...(Ts) == 0) - { - return type_container>(); - } - else - { - return unique_tables_t>::empty_tuple(); - } - } - if constexpr (webframe::ORM::details::is_property && !webframe::ORM::details::is_orm_placeholder) - { - // so we end up with a property - if constexpr (sizeof...(Ts) == 0) - { - return type_container::Table>>(); - } - - constexpr auto empty_tuple_of_righter_tables = unique_tables_t>::empty_tuple(); - - if constexpr (new_type::Table, typename decltype(empty_tuple_of_righter_tables)::type>) - { - return type_container::Table>(), typename decltype(empty_tuple_of_righter_tables)::type()))>(); - } - - if constexpr (not_new_type::Table, typename decltype(empty_tuple_of_righter_tables)::type>) - { - return empty_tuple_of_righter_tables; - } - } - } - using types = typename decltype(empty_tuple())::type; - using orm_tuple_type = decltype(webframe::ORM::details::orm_tuple(std::declval())); - }; - - // Query utils - class IQuery - { - }; - template - concept is_query = std::derived_from; - - template - concept params_match = requires { - { - webframe::ORM::details::convertible_tuples>{} - } -> webframe::ORM::details::pseudo_concept; - }; - - // DB << query operator - template auto operator<<(DB db, const QueryType query) - { - return [ db, query ](auto... args) - requires(params_match) - { - if constexpr (std::is_same_v) - { - db.execute(query, args...); - return; - } - if constexpr (!std::is_same_v) - { - return db.execute(query, args...); - } - }; - } - // concepts - class select_query_t : public IQuery - { - }; - class insert_query_t : public IQuery - { - }; - class update_query_t : public IQuery - { - }; - class delete_query_t : public IQuery - { - }; -} // namespace webframe::ORM::CRUD::details - -namespace webframe::ORM::modes -{ - enum select - { - ALL, - DISTINCT, - DISTINCTROW - }; - - enum join - { - INNER, - LEFT, - RIGHT, - FULL - }; - - enum order - { - DEFAULT, - ASC, - DESC - }; -} // namespace webframe::ORM::modes diff --git a/lib/include/ORM/ORM.hpp b/lib/include/ORM/ORM.hpp index d60f936..f0797d3 100644 --- a/lib/include/ORM/ORM.hpp +++ b/lib/include/ORM/ORM.hpp @@ -1,45 +1,17 @@ -/** - * @file ORM.hpp - * @brief Single header containing all the necessary tools regarding the abstract ORM - * @author Alex Tsvetanov - * @date 2022-09-09 - ***********************************************/ - #pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -// #include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace webframe::ORM { - template class Query - { - public: - using res_t = Result; - constexpr Query() - { - } - }; - -} // namespace webframe::ORM - -#include "../../src/ORM/ORM.cpp" +} diff --git a/lib/include/ORM/db/connectors/MockDB/data.hpp b/lib/include/ORM/db/connectors/MockDB/data.hpp deleted file mode 100644 index ff97aa5..0000000 --- a/lib/include/ORM/db/connectors/MockDB/data.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -namespace webframe::ORM::MockDB::data -{ - struct mock_int - { - }; - struct mock_string - { - }; -} // namespace webframe::ORM::MockDB::data diff --git a/lib/include/ORM/db/connectors/MockDB/init.hpp b/lib/include/ORM/db/connectors/MockDB/init.hpp deleted file mode 100644 index 623f1de..0000000 --- a/lib/include/ORM/db/connectors/MockDB/init.hpp +++ /dev/null @@ -1,538 +0,0 @@ -#pragma once - -#include "data.hpp" -#include "../interface.hpp" -#include "../../../details/member_pointer.hpp" -#include "../../../rules.hpp" -#include "../../../CRUD/utils.hpp" -#include -#include -#include -#include - -namespace webframe::ORM -{ - - // template<> - // Connector::operator webframe::ORM::MockDB::data::mock_int() const { - // return MockDB::data::mock_int(); - // } - - // template<> - // Connector::operator MockDB::data::mock_int&() { - // MockDB::data::mock_int* answer_ptr = new MockDB::data::mock_int; - // MockDB::data::mock_int& answer = *answer_ptr; - // return answer; - // } - - // template<> - // Connector::operator MockDB::data::mock_string() const { - // return MockDB::data::mock_string(); - // } - - // template<> - // Connector::operator MockDB::data::mock_string&() { - // MockDB::data::mock_string* answer_ptr = new MockDB::data::mock_string; - // MockDB::data::mock_string& answer = *answer_ptr; - // return answer; - // } - - namespace MockDB - { - class MockDB - { - public: - static constexpr std::string_view delim = "\n\t"; - - private: - template struct prepare_rule; - - template struct prepare_rule> - { - static constexpr size_t run() - { - if constexpr (std::derived_from) - { - constexpr size_t new_placeholder = prepare_rule::run(); - if constexpr (std::derived_from) - { - return prepare_rule::run(); - } - return new_placeholder; - } - if constexpr (!std::derived_from) - { - constexpr size_t new_placeholder = ind_placeholders + (webframe::ORM::details::is_orm_placeholder); - if constexpr (std::derived_from) - { - return prepare_rule::run(); - } - return new_placeholder; - } - } - }; - - template - static void print_rule(std::stringstream& ss, const webframe::ORM::Rule rule, const Tuple vals) - { - if constexpr (std::derived_from) - { - constexpr size_t new_placeholder = prepare_rule::run(); - print_rule(ss, rule._1, vals); - ss << " " << op.operator std::string_view() << " "; - if constexpr (std::derived_from) - { - print_rule(ss, rule._2, vals); - } - if constexpr (!std::derived_from) - { - if constexpr (webframe::ORM::details::is_orm_placeholder) - { - ss << injection_prevent(vals.template get()); - } - if constexpr (!webframe::ORM::details::is_orm_placeholder) - { - ss << injection_prevent(rule._2); - } - } - } - if constexpr (!std::derived_from) - { - constexpr size_t new_placeholder = ind_placeholders + (webframe::ORM::details::is_orm_placeholder); - if constexpr (webframe::ORM::details::is_orm_placeholder) - { - ss << injection_prevent(vals.template get()) << " "; - } - if constexpr (!webframe::ORM::details::is_orm_placeholder) - { - ss << injection_prevent(rule._1) << " "; - } - ss << op.operator std::string_view() << " "; - if constexpr (std::derived_from) - { - print_rule(ss, rule._2, vals); - } - if constexpr (!std::derived_from) - { - if constexpr (webframe::ORM::details::is_orm_placeholder) - { - ss << injection_prevent(vals.template get()); - } - if constexpr (!webframe::ORM::details::is_orm_placeholder) - { - ss << injection_prevent(rule._2); - } - } - } - } - - template static constexpr auto injection_prevent(T val) - { - if constexpr (std::is_same_v) - { - return "NULL"sv; - } - if constexpr (std::is_same_v) - { - return val; - } - if constexpr (std::is_same_v) - { - return "\"" + val + "\""; - } - if constexpr (std::is_same_v) - { - return "\"" + val + "\""; - } - if constexpr (std::is_same_v) - { - return std::string("\"") + std::string(val) + "\""; - } - if constexpr (std::is_member_pointer_v) - { - if constexpr (std::is_same_v::Table>) - { - return std::string(webframe::ORM::details::i_mem_ptr::type::_name()); - } - if constexpr (!std::is_same_v::Table>) - { - return std::string(webframe::ORM::details::i_mem_ptr::Table::table_name) + "." + - std::string(webframe::ORM::details::i_mem_ptr::type::_name()); - } - } - // if constexpr ( - // !std::is_same_v && - // !std::is_same_v && - // !std::is_same_v && - // !std::is_same_v && - // !std::is_member_pointer_v - //) - // return val; - } - - template void execute_insert_impl(std::stringstream& ss, const auto& query, const auto& tuple_params) const - { - if constexpr (ind_query < std::remove_cvref_t::properties::size) - { - if constexpr ( - !details::is_property())> && - !details::is_orm_placeholder())>) - { - ss << query.signature.template get(); - if constexpr (ind_query + 1 < std::remove_cvref_t::properties::size) - { - ss << ", "; - } - execute_insert_impl(ss, query, tuple_params); - } - if constexpr (ind_param < std::remove_cvref_t::size) - { - if constexpr ( - details::is_orm_placeholder())> || - details::is_property())>) - { - ss << injection_prevent(tuple_params.template get()); - if constexpr (ind_query + 1 < std::remove_cvref_t::properties::size) - { - ss << ", "; - } - execute_insert_impl(ss, query, tuple_params); - } - } - } - if constexpr (ind_query == std::remove_cvref_t::properties::size) - { - ss << ")"; - if constexpr (ind_param * 2 <= std::remove_cvref_t::size) - { - ss << ", ("; - execute_insert_impl<0, ind_param>(ss, query, tuple_params); - } - } - } - - std::string execute_insert(auto query, auto... params) const - requires(decltype(query)::tables::size == 1) - { - webframe::ORM::details::orm_tuple args(std::make_tuple(params...)); - std::stringstream ss; - ss << "INSERT INTO " << std::remove_cvref_t::tables::template orm_type<0>::table_name; - ss << "("; - for_with( - [&]() { - ss << webframe::ORM::details::i_mem_ptr>::type::_name(); - if constexpr (i != T::size - 1) - { - ss << ", "; - } - }, - std::make_index_sequence::properties::size>{}); - ss << ") VALUES ("; - execute_insert_impl<0, 0>(ss, query, args); - return ss.str(); - } - - template void for_(auto func, std::index_sequence) const - { - (func.template operator()(), ...); - } - - template void for_with(auto func, std::index_sequence) const - { - (func.template operator()(), ...); - } - - template - inline void execute_select_impl(std::stringstream& ss, const auto& query, const auto& tuple_params) const - { - using select_type = std::remove_cvref_t; - if constexpr (ind_to_select < select_type::Response::size) - { - ss << injection_prevent(query.selected_properties().template get()); - if constexpr (ind_to_select + 1 < select_type::Response::size) - { - ss << ", "; - } - execute_select_impl(ss, query, tuple_params); - } - if constexpr (ind_to_select == select_type::Response::size && ind_join < select_type::Joins::size) - { - constexpr auto mode = decltype(query.join_clauses().template get())::mode; - if constexpr (mode == webframe::ORM::modes::join::LEFT) - { - ss << " LEFT"; - } - if constexpr (mode == webframe::ORM::modes::join::RIGHT) - { - ss << " RIGHT"; - } - // if constexpr (mode == webframe::ORM::modes::join::FULL) ss << " FULL"; - if constexpr (mode == webframe::ORM::modes::join::INNER) - { - ss << " INNER"; - } - ss << delim << "JOIN " << decltype(query.join_clauses().template get())::Table::table_name << " ON "; - print_rule(ss, query.join_clauses().template get().to_rule(), tuple_params); - constexpr size_t next_placeholder = prepare_rule().to_rule())>::run(); - execute_select_impl( - ss, query, tuple_params); - } - if constexpr (ind_to_select == select_type::Response::size && ind_join == select_type::Joins::size && ind_filter < select_type::Wheres::size) - { - ss << delim << "WHERE "; - print_rule(ss, query.where_clauses().template get(), tuple_params); - constexpr size_t next_placeholder = prepare_rule())>::run(); - execute_select_impl( - ss, query, tuple_params); - } - if constexpr ( - ind_to_select == select_type::Response::size && ind_join == select_type::Joins::size && ind_filter == select_type::Wheres::size && - ind_limit < select_type::Limitations::size) - { - ss << delim << "LIMIT " << query.limit_clauses().template get().get_elements_per_page() << " x " - << query.limit_clauses().template get().get_number_of_page(); - execute_select_impl(ss, query, tuple_params); - } - if constexpr ( - ind_to_select == select_type::Response::size && ind_join == select_type::Joins::size && ind_filter == select_type::Wheres::size && - ind_limit == select_type::Limitations::size && ind_grouping < select_type::Groupings::size) - { - ss << delim << "GROUP BY ("; - for_( - [&]() { ss << injection_prevent(query.group_clauses().template get().properties.template get()); }, - std::make_index_sequence())::Properties::size>{}); - ss << ")"; - if constexpr (decltype(query.group_clauses().template get())::has_rule()) - { - ss << delim << "HAVING "; - print_rule(ss, query.group_clauses().template get().to_rule(), tuple_params); - constexpr size_t next_placeholder = - prepare_rule().to_rule())>::run(); - execute_select_impl( - ss, query, tuple_params); - } - else - { - execute_select_impl(ss, query, tuple_params); - } - } - if constexpr ( - ind_to_select == select_type::Response::size && ind_join == select_type::Joins::size && ind_filter == select_type::Wheres::size && - ind_limit == select_type::Limitations::size && ind_grouping == select_type::Groupings::size && ind_ordering < select_type::OrderBy::size) - { - if constexpr (ind_ordering == 0) - { - ss << delim << "ORDER BY "; - } - ss << injection_prevent(decltype(query.order_clauses().template get())::property); - if constexpr (decltype(query.order_clauses().template get())::sort == webframe::ORM::modes::order::ASC) - { - ss << " ASC"; - } - if constexpr (decltype(query.order_clauses().template get())::sort == webframe::ORM::modes::order::DESC) - { - ss << " DESC"; - } - if constexpr (ind_ordering + 1 < decltype(query.order_clauses())::size) - { - ss << ", "; - } - execute_select_impl(ss, query, tuple_params); - } - return; - } - std::string execute_select(auto query, auto... params) const - { - webframe::ORM::details::orm_tuple args(std::make_tuple(params...)); - std::stringstream ss; - ss << "SELECT "; - if constexpr (decltype(query)::mode == webframe::ORM::modes::select::ALL) - { - ss << "ALL "; - } - if constexpr (decltype(query)::mode == webframe::ORM::modes::select::DISTINCT) - { - ss << "DISTINCT "; - } - if constexpr (decltype(query)::mode == webframe::ORM::modes::select::DISTINCTROW) - { - ss << "DISTINCTROW "; - } - execute_select_impl<0, 0, 0, 0, 0, 0, 0>(ss, query, args); - return ss.str(); - } - - template - inline void execute_update_impl(std::stringstream& ss, const auto& query, const auto& tuple_params) const - { - if constexpr (ind_query < std::remove_cvref_t::size) - { - auto statement = query.updates().template get(); - ss << injection_prevent(statement._1) << " = "; - if constexpr (details::is_orm_placeholder) - { - ss << injection_prevent(tuple_params.template get()) << ", "; - execute_update_impl(ss, query, tuple_params); - } - if constexpr (!details::is_orm_placeholder) - { - ss << injection_prevent(statement._2); - if constexpr (ind_query + 1 != std::remove_cvref_t::size) - { - ss << ", "; - } - execute_update_impl(ss, query, tuple_params); - } - } - if constexpr (ind_query == std::remove_cvref_t::size) - { - if constexpr (ind_filter != std::remove_cvref_t::where_size) - { - ss << delim << "WHERE "; - } - if constexpr (ind_filter == std::remove_cvref_t::where_size) - { - if constexpr (ind_ordering == std::remove_cvref_t::order_size) - { - // re-run functionality not available - // if constexpr (ind_limit == std::remove_cvref_t::limit_size && ind_param + ind_query + ind_filter + ind_ordering - // + ind_limit <= std::remove_cvref_t::size) { - // execute_update_impl<0, ind_param, 0, 0, 0>(ss, query, tuple_params); - // } - if constexpr (ind_limit < std::remove_cvref_t::limit_size) - { - ss << delim << "LIMIT " << query.limit_clauses().template get().get_elements_per_page() << " x " - << query.limit_clauses().template get().get_number_of_page(); - execute_update_impl(ss, query, tuple_params); - } - } - if constexpr (ind_ordering < std::remove_cvref_t::order_size && std::remove_cvref_t::order_size != 0) - { - if constexpr (ind_ordering == 0) - { - ss << delim << "ORDER BY "; - } - ss << injection_prevent(decltype(query.order_clauses().template get())::property); - if constexpr (decltype(query.order_clauses().template get())::sort == webframe::ORM::modes::order::ASC) - { - ss << " ASC"; - } - if constexpr (decltype(query.order_clauses().template get())::sort == webframe::ORM::modes::order::DESC) - { - ss << " DESC"; - } - if constexpr (ind_ordering + 1 < decltype(query.order_clauses())::size) - { - ss << ", "; - } - execute_update_impl(ss, query, tuple_params); - } - } - if constexpr (ind_filter < std::remove_cvref_t::where_size) - { - print_rule(ss, query.wheres().template get(), tuple_params); - constexpr size_t next_placeholder = prepare_rule())>::run(); - execute_update_impl(ss, query, tuple_params); - } - } - return; - } - std::string execute_update(auto query, auto... params) const - requires(decltype(query)::tables::size == 1) - { - webframe::ORM::details::orm_tuple args(std::make_tuple(params...)); - std::stringstream ss; - ss << "UPDATE " << decltype(query)::tables::template orm_type<0>::table_name << " SET "; - execute_update_impl<0, 0, 0, 0, 0>(ss, query, args); - return ss.str(); - } - template - inline void execute_delete_impl(std::stringstream& ss, const auto& query, const auto& tuple_params) const - { - if constexpr (ind_filter != std::remove_cvref_t::where_size) - { - ss << delim << "WHERE "; - } - if constexpr (ind_filter == std::remove_cvref_t::where_size) - { - if constexpr (ind_ordering == std::remove_cvref_t::order_size) - { - // re-run functionality not available - // if constexpr (ind_limit == std::remove_cvref_t::limit_size && ind_param + ind_filter + ind_ordering + ind_limit <= - // std::remove_cvref_t::size) { - // execute_delete_impl(ss, query, tuple_params); - // } - if constexpr (ind_limit < std::remove_cvref_t::limit_size) - { - ss << delim << "LIMIT " << query.limit_clauses().template get().get_elements_per_page() << " x " - << query.limit_clauses().template get().get_number_of_page(); - execute_delete_impl(ss, query, tuple_params); - } - } - if constexpr (ind_ordering < std::remove_cvref_t::order_size && std::remove_cvref_t::order_size != 0) - { - if constexpr (ind_ordering == 0) - { - ss << delim << "ORDER BY "; - } - ss << injection_prevent(decltype(query.order_clauses().template get())::property); - if constexpr (decltype(query.order_clauses().template get())::sort == webframe::ORM::modes::order::ASC) - { - ss << " ASC"; - } - if constexpr (decltype(query.order_clauses().template get())::sort == webframe::ORM::modes::order::DESC) - { - ss << " DESC"; - } - if constexpr (ind_ordering + 1 < decltype(query.order_clauses())::size) - { - ss << ", "; - } - execute_delete_impl(ss, query, tuple_params); - } - } - if constexpr (ind_filter < std::remove_cvref_t::where_size) - { - print_rule(ss, query.wheres().template get(), tuple_params); - constexpr size_t next_placeholder = prepare_rule())>::run(); - execute_delete_impl(ss, query, tuple_params); - } - return; - } - std::string execute_delete(auto query, auto... params) const - { - webframe::ORM::details::orm_tuple args(std::make_tuple(params...)); - std::stringstream ss; - ss << "DELETE " << decltype(query)::table::table_name << " "; - execute_delete_impl<0, 0, 0, 0>(ss, query, args); - return ss.str(); - } - - public: - template inline auto execute(QueryType query, auto... params) const - { - // Select query handling - if constexpr (std::is_base_of_v) - { - return this->execute_select(query, params...); - } - // Insert query handling - if constexpr (std::is_base_of_v) - { - return this->execute_insert(query, params...); - } - // Update query handling - if constexpr (std::is_base_of_v) - { - return this->execute_update(query, params...); - } - // Delete query handling - if constexpr (std::is_base_of_v) - { - return this->execute_delete(query, params...); - } - } - }; - } // namespace MockDB - -} // namespace webframe::ORM diff --git a/lib/include/ORM/db/connectors/interface.hpp b/lib/include/ORM/db/connectors/interface.hpp deleted file mode 100644 index 8702989..0000000 --- a/lib/include/ORM/db/connectors/interface.hpp +++ /dev/null @@ -1,94 +0,0 @@ -#pragma once - -#include -#include "../../details/fundamental_type.hpp" - -namespace webframe::ORM -{ - namespace details - { - class DBDataType - { - }; - class IDB - { - }; - } // namespace details - - template - concept is_db = std::derived_from; - - template - concept is_db_data_type = std::derived_from; - - template class Connector; - - template class Connector<_DB_type, CPP_type> : public details::DBDataType, public CPP_type - { - public: - using DB_type = _DB_type; - using type = CPP_type; - - Connector(const _DB_type value) - { - *this = value; - } - Connector(_DB_type& value) - { - *this = value; - } - - operator _DB_type() const; - operator _DB_type&(); - const _DB_type& operator=(const _DB_type& _value); - }; - - template class Connector<_DB_type, CPP_type> : public details::DBDataType - { - protected: - CPP_type value; - - public: - using DB_type = _DB_type; - using type = CPP_type; - - Connector(const CPP_type value) : value(value) - { - } - Connector(CPP_type& value) : value(value) - { - } - - Connector(const _DB_type value) - { - *this = value; - } - Connector(_DB_type& value) - { - *this = value; - } - - Connector() : value() - { - } - - inline operator CPP_type() const - { - return value; - } - inline operator CPP_type&() - { - return value; - } - - CPP_type operator=(const CPP_type& _value) - { - return value = _value; - } - - operator _DB_type() const; - operator _DB_type&(); - const _DB_type& operator=(const _DB_type& _value); - }; - -} // namespace webframe::ORM diff --git a/lib/include/ORM/db/types/db_type_wrappers.hpp b/lib/include/ORM/db/types/db_type_wrappers.hpp deleted file mode 100644 index a346f2b..0000000 --- a/lib/include/ORM/db/types/db_type_wrappers.hpp +++ /dev/null @@ -1,299 +0,0 @@ -#pragma once -#include -#include -#include -#include "primitive_type_wrapper.hpp" - -namespace webframe::ORM -{ - - // Bitset - template class BIT : public std::bitset - { - public: - using reference = typename std::bitset::reference; - using native_type = std::bitset; - static constexpr size_t db_size = n; - static constexpr std::string_view db_type = "BIT"; - - BIT(auto... Ts) : std::bitset(Ts...) - { - } - - native_type& get() - { - return *this; - } - const native_type& get_const() const - { - return *this; - } - }; - - // Strings - template - concept Character = std::same_as || std::same_as || std::same_as || std::same_as || - std::same_as || std::same_as || std::same_as; - - template - requires(Character) - class CHAR : public std::basic_string - { - public: - using native_type = std::basic_string; - static constexpr size_t db_size = n; - static constexpr std::string_view db_type = "CHAR"; - - CHAR(auto... Ts) : std::basic_string(Ts...) - { - } - - native_type& get() - { - return *this; - } - const native_type& get_const() const - { - return *this; - } - }; - - template - requires(Character) - class VARCHAR : public std::basic_string - { - public: - using native_type = std::basic_string; - static constexpr size_t db_size = n; - static constexpr std::string_view db_type = "VARCHAR"; - - VARCHAR(auto... Ts) : std::basic_string(Ts...) - { - } - - native_type& get() - { - return *this; - } - const native_type& get_const() const - { - return *this; - } - }; - - template - requires(n <= 255) - using TINYTEXT = VARCHAR; - template - requires(n <= 65'535) - using TEXT = VARCHAR; - template - requires(n <= 16'777'215) - using MEDIUMTEXT = VARCHAR; - template - requires(n <= 4'294'967'295) - using LONGTEXT = VARCHAR; - - // Binary - template class BINARY : CHAR - { - public: - using native_type = typename CHAR::native_type; - static constexpr size_t db_size = n; - static constexpr std::string_view db_type = "BINARY"; - - BINARY(auto... Ts) : CHAR(Ts...) - { - } - - native_type& get() - { - return *this; - } - const native_type& get_const() const - { - return *this; - } - }; - - template class VARBINARY : VARCHAR - { - public: - using native_type = typename VARCHAR::native_type; - static constexpr size_t db_size = n; - static constexpr std::string_view db_type = "VARBINARY"; - - VARBINARY(auto... Ts) : VARCHAR(Ts...) - { - } - - native_type& get() - { - return *this; - } - const native_type& get_const() const - { - return *this; - } - }; - - template - requires(n <= 255) - using TINYBLOB = VARBINARY; - template - requires(n <= 65'535) - using BLOB = VARBINARY; - template - requires(n <= 16'777'215) - using MEDIUMBLOB = VARBINARY; - template - requires(n <= 4'294'967'295) - using LONGBLOB = VARBINARY; - - // Boolean - class BOOL - { - bool value; - - public: - using native_type = bool; - static constexpr std::string_view db_type = "BOOL"; - - BOOL(const bool value) : value(value) - { - } - BOOL(bool& value) : value(value) - { - } - - BOOL() : value() - { - } - - inline operator bool() const - { - return value; - } - inline operator bool&() - { - return value; - } - - bool& operator=(auto _value) - { - static_cast(*this) = _value; - return this->value; - } - - native_type& get() - { - return this->value; - } - const native_type& get_const() const - { - return this->value; - } - }; - - using BOOLEAN = BOOL; - - // Integers - namespace impl - { - template - requires(n <= 64) - struct INTEGER_wrapper; - -#define specify(CLASS, N1, N2, UN_OR_SIGNED, TYPE) \ - template \ - requires(n >= N1 && n <= N2) \ - struct CLASS \ - { \ - using type = webframe::ORM::Primitive; \ - } - - specify(INTEGER_wrapper, 0, 16, signed, int16_t); - specify(INTEGER_wrapper, 17, 32, signed, int32_t); - specify(INTEGER_wrapper, 33, 64, signed, int64_t); - specify(INTEGER_wrapper, 0, 16, unsigned, uint16_t); - specify(INTEGER_wrapper, 17, 32, unsigned, uint32_t); - specify(INTEGER_wrapper, 33, 64, unsigned, uint64_t); -#undef specify - } // namespace impl - - template - requires(n <= 64) - using INTEGER = typename impl::INTEGER_wrapper::type; - - constexpr size_t percision_not_set = 18446744073709551615ull; - - template - requires(p <= 24 || p == percision_not_set) - using FLOAT = webframe::ORM::Primitive; - - template - requires((p >= 25 && p <= 53) || p == percision_not_set) - using DOUBLE = webframe::ORM::Primitive; - - namespace impl - { - template struct DECIMAL_wrapper; - - template - requires(p <= 24) - struct DECIMAL_wrapper - { - using type = FLOAT; - }; - - template - requires(p >= 25 && p <= 53) - struct DECIMAL_wrapper - { - using type = DOUBLE; - }; - } // namespace impl - - template using DECIMAL = typename impl::DECIMAL_wrapper::type; - - // NULLable - class INullable - { - }; - - template - concept is_nullable = std::is_base_of_v; - - template class Nullable : public INullable, public T - { - bool _is_null; - - public: - using original_type = T; - - Nullable() : Nullable(nullptr) - { - } - - template - requires(!std::is_same_v) - Nullable(U x) : T(x), _is_null(false) - { - } - - template - requires(!std::is_same_v) - Nullable(U x, auto... args) : T(x, args...), _is_null(false) - { - } - - Nullable(nullptr_t) : _is_null(true) - { - } - - bool is_null() const - { - return _is_null; - } - }; -} // namespace webframe::ORM diff --git a/lib/include/ORM/db/types/primitive_type_wrapper.hpp b/lib/include/ORM/db/types/primitive_type_wrapper.hpp deleted file mode 100644 index e2d053b..0000000 --- a/lib/include/ORM/db/types/primitive_type_wrapper.hpp +++ /dev/null @@ -1,286 +0,0 @@ -#pragma once - -#include -#include - -namespace webframe::ORM -{ - namespace details - { - template - requires(std::is_fundamental_v) - class Wrapper - { - protected: - virtual T& get() = 0; - virtual const T& get() const = 0; - }; - - template - concept operator_not_available = false; - -#define BinaryOperatorWrapper(op, name) \ - template struct name; \ - \ - template \ - requires requires(T& a, T b) { \ - { \ - a op b \ - }; \ - } \ - struct name : public Wrapper \ - { \ - template inline decltype(T() op U()) operator op(U b) const \ - { \ - return (this->get() op b); \ - } \ - }; \ - \ - template \ - requires(!requires(T& a, T b) { \ - { \ - a op b \ - }; \ - }) \ - struct name : public Wrapper \ - { \ - template inline T operator op(U) const \ - { \ - static_assert(operator_not_available, "error: invalid operands of types ‘T’ and ‘U’ to binary ‘operator" #op "’"); \ - return this->get(); \ - } \ - } - -#define BinaryRefOperatorWrapper(op, name) \ - template struct name; \ - \ - template \ - requires requires(T& a, T b) { \ - { \ - a op b \ - }; \ - } \ - struct name : public Wrapper \ - { \ - template \ - requires(!std::is_base_of_v) \ - inline T& operator op(U b) \ - { \ - return (this->get() op b); \ - } \ - }; \ - \ - template \ - requires(!requires(T& a, T b) { \ - { \ - a op b \ - }; \ - }) \ - struct name : public Wrapper \ - { \ - template \ - requires(!std::is_base_of_v) \ - inline T& operator op(U) \ - { \ - static_assert(operator_not_available, "error: invalid operands of types ‘T’ and ‘U’ to binary ‘operator" #op "’"); \ - return (this->get()); \ - } \ - } - -#define UnaryPrefixOperatorWrapper(op, name) \ - template struct name; \ - \ - template \ - requires requires(T& a) { \ - { \ - op a \ - }; \ - } \ - struct name : public Wrapper \ - { \ - inline T& operator op() \ - { \ - return (op this->get()); \ - } \ - }; \ - \ - template \ - requires(!requires(T& a) { \ - { \ - op a \ - }; \ - }) \ - struct name : public Wrapper \ - { \ - inline T& operator op() \ - { \ - static_assert(operator_not_available, "error: invalid operand of types ‘T’ to unary prefix ‘operator" #op "’"); \ - return (this->get()); \ - } \ - } - -#define UnarySuffixOperatorWrapper(op, name) \ - template struct name; \ - \ - template \ - requires requires(T& a) { \ - { \ - a op \ - }; \ - } \ - struct name : public Wrapper \ - { \ - inline T& operator op(int) \ - { \ - return (this->get() op); \ - } \ - }; \ - \ - template \ - requires(!requires(T& a) { \ - { \ - a op \ - }; \ - }) \ - struct name : public Wrapper \ - { \ - inline T& operator op(int) \ - { \ - static_assert(operator_not_available, "error: invalid operand of types ‘T’ to unary suffix ‘operator" #op "’"); \ - return (this->get()); \ - } \ - } - - BinaryOperatorWrapper(+, PlusWrapper); - BinaryOperatorWrapper(-, MinusWrapper); - BinaryOperatorWrapper(/, DevisionWrapper); - BinaryOperatorWrapper(*, MultiplicationWrapper); - BinaryOperatorWrapper(%, ModulasWrapper); - - BinaryOperatorWrapper(&, BitWiseAndWrapper); - BinaryOperatorWrapper(|, BitWiseOrWrapper); - BinaryOperatorWrapper(^, BitWiseXorWrapper); - BinaryOperatorWrapper(>>, BitWiseShiftRightWrapper); - BinaryOperatorWrapper(<<, BitWiseShiftLeftWrapper); - - BinaryOperatorWrapper(==, EqualsWrapper); - BinaryOperatorWrapper(!=, NotEqualsWrapper); - BinaryOperatorWrapper(>, GreaterThanWrapper); - BinaryOperatorWrapper(<, LessThanWrapper); - BinaryOperatorWrapper(>=, GreaterOrEqualWrapper); - BinaryOperatorWrapper(<=, LessOrEqualWrapper); - BinaryOperatorWrapper(&&, AndWrapper); - BinaryOperatorWrapper(||, OrWrapper); - - BinaryRefOperatorWrapper(+=, AssignmentPlusWrapper); - BinaryRefOperatorWrapper(-=, AssignmentMinusWrapper); - BinaryRefOperatorWrapper(/=, AssignmentDevisionWrapper); - BinaryRefOperatorWrapper(*=, AssignmentMultiplicationWrapper); - BinaryRefOperatorWrapper(%=, AssignmentModulasWrapper); - BinaryRefOperatorWrapper(>>=, AssignmentShiftRightWrapper); - BinaryRefOperatorWrapper(<<=, AssignmentShiftLeftWrapper); - - BinaryRefOperatorWrapper(&=, AssignmentBitWiseAndWrapper); - BinaryRefOperatorWrapper(|=, AssignmentBitWiseOrWrapper); - BinaryRefOperatorWrapper(^=, AssignmentBitWiseXorWrapper); - - UnaryPrefixOperatorWrapper(!, PrefixNotWrapper); - - UnaryPrefixOperatorWrapper(++, PrefixIncrementWrapper); - UnaryPrefixOperatorWrapper(--, PrefixDecrementWrapper); - - UnarySuffixOperatorWrapper(++, SuffixIncrementWrapper); - UnarySuffixOperatorWrapper(--, SuffixDecrementWrapper); - -#undef BinaryOperatorWrapper -#undef BinaryRefOperatorWrapper -#undef UnaryPrefixOperatorWrapper -#undef UnarySuffixOperatorWrapper - - template struct istreamOperationsWrapper : public Wrapper - { - template - friend inline std::basic_istream& operator>>(std::basic_istream& in, istreamOperationsWrapper& a) - { - return (in >> a.get()); - } - }; - - template struct ostreamOperationsWrapper : public Wrapper - { - template - friend inline std::basic_ostream& operator<<(std::basic_ostream& out, const ostreamOperationsWrapper& a) - { - return (out << a.get()); - } - }; - } // namespace details - - template - class Primitive : public details::PlusWrapper, - public details::MinusWrapper, - public details::DevisionWrapper, - public details::MultiplicationWrapper, - public details::ModulasWrapper, - public details::BitWiseAndWrapper, - public details::BitWiseOrWrapper, - public details::BitWiseXorWrapper, - public details::BitWiseShiftRightWrapper, - public details::BitWiseShiftLeftWrapper, - public details::EqualsWrapper, - public details::NotEqualsWrapper, - public details::GreaterThanWrapper, - public details::LessThanWrapper, - public details::GreaterOrEqualWrapper, - public details::LessOrEqualWrapper, - public details::AndWrapper, - public details::OrWrapper, - public details::AssignmentPlusWrapper, - public details::AssignmentMinusWrapper, - public details::AssignmentDevisionWrapper, - public details::AssignmentMultiplicationWrapper, - public details::AssignmentModulasWrapper, - public details::AssignmentShiftRightWrapper, - public details::AssignmentShiftLeftWrapper, - public details::AssignmentBitWiseAndWrapper, - public details::AssignmentBitWiseOrWrapper, - public details::AssignmentBitWiseXorWrapper, - public details::PrefixNotWrapper, - public details::PrefixIncrementWrapper, - public details::PrefixDecrementWrapper, - public details::SuffixIncrementWrapper, - public details::SuffixDecrementWrapper, - public details::istreamOperationsWrapper, - public details::ostreamOperationsWrapper - { - protected: - T val; - virtual T& get() final - { - return val; - }; - virtual const T& get() const final - { - return val; - }; - - public: - Primitive() : val() - { - } - Primitive(auto... _vals) : val(_vals...) - { - } - - public: - virtual operator T() final - { - return get(); - } - - using native_type = T; - static constexpr size_t db_size = size; - static constexpr size_t db_percision = P; - static constexpr std::string_view db_type = name; - }; -} // namespace webframe::ORM diff --git a/lib/include/ORM/details/fundamental_type.hpp b/lib/include/ORM/details/fundamental_type.hpp deleted file mode 100644 index a559fe7..0000000 --- a/lib/include/ORM/details/fundamental_type.hpp +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @file fundamental_type.hpp - * @brief Concept definition for fundamental type - * @author Alex Tsvetanov - * @date 2023-08-31 - ***********************************************/ - -#pragma once - -#include - -namespace webframe::ORM::details -{ - template - concept is_inheritable = !std::is_fundamental_v && !std::is_enum_v; - - template - concept is_not_inheritable = std::is_fundamental_v || std::is_enum_v; -} // namespace webframe::ORM::details diff --git a/lib/include/ORM/details/member_pointer.hpp b/lib/include/ORM/details/member_pointer.hpp deleted file mode 100644 index 720eee7..0000000 --- a/lib/include/ORM/details/member_pointer.hpp +++ /dev/null @@ -1,301 +0,0 @@ -/** - * @file member_pointer.hpp - * @brief Concept definitions different types of member pointers - * @author Alex Tsvetanov - * @date 2023-08-31 - ***********************************************/ - -#ifndef WEBFRAME_ORM_MEM_PTR -#define WEBFRAME_ORM_MEM_PTR - -#include -#include -#include -#include "string_literal.hpp" - -namespace webframe::ORM::details -{ - template - concept is_property = std::is_member_pointer_v; - - template - concept is_not_property = !std::is_member_pointer_v; - - template - concept is_query_string = std::is_convertible_v && !is_property; - - template class i_mem_ptr; - template class mem_ptr; - - class mem_ptr_detector - { - }; - - template class i_mem_ptr : public mem_ptr_detector - { - public: - using Table = _Table; - using type = T; - using ptr_t = T Table::*; - - public: - virtual constexpr ptr_t get() const = 0; - }; - - template - concept is_mem_ptr_t = std::derived_from; - - template - concept is_not_mem_ptr_t = !is_mem_ptr_t; -} // namespace webframe::ORM::details - -namespace webframe::ORM -{ - - class IStatement - { - }; - template - concept is_statement = std::derived_from; - template class Statement; - - template class Statement : public IStatement - { - public: - static constexpr std::string_view operation = op.operator std::string_view(); - typename T1::ptr_t _1; - T2 _2; - constexpr Statement() - { - } - constexpr Statement(typename T1::ptr_t a, T2 b) : _1(a), _2(b) - { - } - }; - - template class Statement : public IStatement - { - public: - static constexpr std::string_view operation = op.operator std::string_view(); - typename T1::ptr_t _1; - typename T2::ptr_t _2; - constexpr Statement() - { - } - constexpr Statement(typename T1::ptr_t a, typename T2::ptr_t b) : _1(a), _2(b) - { - } - }; - - template - constexpr inline bool are_same(const Statement& Statement1, const Statement& Statement2) - { - // Different operations - if constexpr (op1.operator std::string_view() != op2.operator std::string_view()) - { - return false; - } - // Different operand types - else if constexpr ( - requires { - { - Statement1._1.operation - }; - } ^ - requires { - { - Statement2._1.operation - }; - }) - { - return false; - } - else if constexpr ( - requires { - { - Statement1._2.operation - }; - } ^ - requires { - { - Statement2._2.operation - }; - }) - { - return false; - } - else - { - bool answer = true; - // Both Statements - if constexpr ( - requires { - { - Statement1._1.operation - }; - } && - requires { - { - Statement2._1.operation - }; - }) - { - answer = answer && (are_same(Statement1._1, Statement2._1)); - } - // Both not Statements - if constexpr ( - !requires { - { - Statement1._1.operation - }; - } && - requires { - { - Statement2._1.operation - }; - }) - { - answer = answer && (Statement1._1 == Statement2._1); - } - // Both Statements - if constexpr ( - requires { - { - Statement1._2.operation - }; - } && - requires { - { - Statement2._2.operation - }; - }) - { - answer = answer && (are_same(Statement1._2, Statement2._2)); - } - // Both not Statements - if constexpr ( - !requires { - { - Statement1._2.operation - }; - } && - requires { - { - Statement2._2.operation - }; - }) - { - answer = answer && (Statement1._2 == Statement2._2); - } - return answer; - } - } - - template - inline std::ostream& operator<<(std::ostream& out, const Statement& statement) - { - out << "("; - if constexpr (requires { - { - typename details::i_mem_ptr::Table() - }; - }) - { - out << typeid(typename details::i_mem_ptr::type).name() << " " << typeid(typename details::i_mem_ptr::Table).name() << "::*"; - } - if constexpr (!requires { - { - typename details::i_mem_ptr::Table() - }; - }) - { - out << statement._1; - } - out << ") " << statement.operation << " ("; - if constexpr (requires { - { - typename details::i_mem_ptr::Table() - }; - }) - { - out << typeid(typename details::i_mem_ptr::type).name() << " " << typeid(typename details::i_mem_ptr::Table).name() << "::*"; - } - if constexpr (!requires { - { - typename details::i_mem_ptr::Table() - }; - }) - { - out << statement._2; - } - out << ")"; - return out; - } -} // namespace webframe::ORM - -namespace webframe::ORM::details -{ - template class mem_ptr; - - template - requires(!std::is_same_v) - class mem_ptr : public i_mem_ptr - { - public: - using typename i_mem_ptr::Table; - using typename i_mem_ptr::type; - using typename i_mem_ptr::ptr_t; - - constexpr inline ptr_t get() const - { - return property; - } - - constexpr inline auto operator=(auto x) const - { - if constexpr (details::is_mem_ptr_t) - { - return webframe::ORM::Statement, "=", typename decltype(x)::ptr_t>(this->get(), x.get()); - } - if constexpr (details::is_not_mem_ptr_t) - { - return webframe::ORM::Statement, "=", decltype(x)>(this->get(), x); - } - } - }; - - struct Filler - { - private: - template struct pseudo_property - { - public: - using var_t = T; - static constexpr std::string_view _name() - { - return lit.value; - } - }; - - public: - static constexpr std::string_view table_name = ""; - pseudo_property Null; - }; - - template <> class mem_ptr : public mem_ptr<&Filler::Null> - { - public: - using typename i_mem_ptr::Table; - using typename i_mem_ptr::type; - using typename i_mem_ptr::ptr_t; - }; -} // namespace webframe::ORM::details - -namespace webframe::ORM -{ - template constexpr details::mem_ptr P = details::mem_ptr(); -} - -#include "../../../src/ORM/details/member_pointer.cpp" - -#endif diff --git a/lib/include/ORM/details/orm_tuple.hpp b/lib/include/ORM/details/orm_tuple.hpp deleted file mode 100644 index e04e23e..0000000 --- a/lib/include/ORM/details/orm_tuple.hpp +++ /dev/null @@ -1,294 +0,0 @@ -#pragma once - -#include -#include -#include "member_pointer.hpp" -#include "../rules.hpp" -#include "../fields.hpp" - -namespace webframe::ORM::details -{ - - // Extended std::tuple - template class orm_tuple : public std::tuple - { - public: - static constexpr size_t size = sizeof...(Ts); - - template using orm_type = typename std::tuple_element>::type; - - // explicit constexpr orm_tuple(const std::tuple&& t) : std::tuple(t) {} - // explicit constexpr orm_tuple(const std::tuple& t) : std::tuple(t) {} - constexpr orm_tuple(const std::tuple t) : std::tuple(t) - { - } - constexpr orm_tuple() : std::tuple() - { - } - - constexpr std::tuple to_tuple() const - { - return *this; - } - - template constexpr auto get() const - { - return std::get(*this); - } - - template constexpr auto get() const - { - if constexpr (std::is_integral_v) - { - return std::get(*this); - } - if constexpr (!std::is_integral_v) - { - return std::get(*this); - } - } - }; - - template <> class orm_tuple<> : public std::tuple<> - { - public: - // explicit constexpr orm_tuple(const std::tuple<>&& t) : std::tuple<>(t) {} - // explicit constexpr orm_tuple(const std::tuple<>& t) : std::tuple<>(t) {} - constexpr orm_tuple(const std::tuple<> t) : std::tuple<>(t) - { - } - constexpr orm_tuple() : std::tuple<>() - { - } - static constexpr size_t size = 0; - - constexpr std::tuple<> to_tuple() const - { - return *this; - } - }; - - // Decomposite tuples of params - template class get_type; - - template - requires(std::is_member_pointer_v) - class get_type - { - public: - using type = typename webframe::ORM::details::i_mem_ptr::type::var_t; - using actual_type = typename webframe::ORM::details::i_mem_ptr::type; - using table = typename webframe::ORM::details::i_mem_ptr::Table; - }; - - template - requires(!std::is_member_pointer_v) - class get_type - { - public: - using type = value; - using actual_type = value; - using table = decltype(nullptr); - }; - - template class decomposite_properties; - - template class decomposite_properties> - { - public: - using data_types = orm_tuple::type...>; - using data_tables = orm_tuple::table...>; - }; - - // Convertible tuples utils - template class normalize_type; - - template class normalize_type - { - public: - using type = T; - }; - - template class normalize_type - { - public: - using type = typename i_mem_ptr::type::var_t; - }; - - template class convertible_tuples; - - template class convertible_tuples, webframe::ORM::details::orm_tuple> - { - public: - using T = webframe::ORM::details::orm_tuple; - using U = webframe::ORM::details::orm_tuple; - template static constexpr bool eval(std::index_sequence) - { - if constexpr (T::size == 0) - { - return U::size == 0; - } - return (requires(typename normalize_type>::type var) { - { - var = std::declval>() - }; - } && ...); - } - static constexpr bool value = eval(std::index_sequence_for{}); - }; - - template - concept pseudo_concept = T::value; - - // Placeholders - class IPlaceholder - { - }; - - template class placeholder : public IPlaceholder - { - public: - webframe::ORM::property _; - }; - - template - concept is_orm_placeholder = std::derived_from::Table, IPlaceholder>; - - template - concept is_not_orm_placeholder = !is_orm_placeholder; - - // Get properties - template class get_properties; - - // Tuple - template class get_properties> - { - public: - using properties = decltype(std::tuple_cat(typename get_properties::properties()...)); - using orm_properties = decltype(orm_tuple(properties())); - }; - - template class get_properties> - { - public: - using properties = typename get_properties>::properties; - using orm_properties = decltype(orm_tuple(properties())); - }; - - // Property - template class get_properties - { - public: - using properties = std::tuple; - using orm_properties = decltype(orm_tuple(properties())); - }; - - // Rule - template class get_properties - { - public: - using properties = - decltype(std::tuple_cat(typename get_properties::properties(), typename get_properties::properties())); - using orm_properties = decltype(orm_tuple(properties())); - }; - - // Random value - template struct is_tuple : std::false_type - { - }; - template struct is_tuple> : std::true_type - { - }; - - template - concept is_property_or_rule_or_tuple = is_property || is_rule || is_tuple::value; - template - concept is_not_property_not_rule_not_tuple = !is_property_or_rule_or_tuple; - template class get_properties - { - public: - using properties = std::tuple<>; - using orm_properties = decltype(orm_tuple(properties())); - }; - - // Filter the placeholders from a tuple - template class get_placeholders; - - template class get_placeholders> - { - public: - using placeholders = typename get_placeholders>::placeholders; - using orm_placeholders = typename get_placeholders>::orm_placeholders; - }; - - template <> class get_placeholders> - { - public: - using placeholders = std::tuple<>; - using orm_placeholders = decltype(orm_tuple(placeholders())); - }; - - template class get_placeholders> - { - public: - using placeholders = typename get_placeholders>::placeholders; - using orm_placeholders = typename get_placeholders>::orm_placeholders; - }; - - template class get_placeholders> - { - public: - using placeholders = decltype(std::tuple_cat(std::tuple(), std::declval>::placeholders>())); - using orm_placeholders = decltype(orm_tuple(std::declval())); - }; - - // filter the placeholders and the properties from a tuple - template class get_placeholders_and_properties; - - template <> class get_placeholders_and_properties> - { - public: - using placeholders = std::tuple<>; - using orm_placeholders = decltype(orm_tuple(placeholders())); - }; - - template class get_placeholders_and_properties> - { - public: - using placeholders = - decltype(std::tuple_cat(std::tuple(), std::declval>::placeholders>())); - using orm_placeholders = decltype(orm_tuple(placeholders())); - }; - - template - concept is_property_but_not_placeholder = is_property && !is_orm_placeholder; - template class get_placeholders_and_properties> - { - public: - using placeholders = - decltype(std::tuple_cat(std::tuple(), std::declval>::placeholders>())); - using orm_placeholders = decltype(orm_tuple(placeholders())); - }; - - template - concept is_not_property_or_placeholder = !(is_property_but_not_placeholder || is_orm_placeholder); - - template class get_placeholders_and_properties> - { - public: - using placeholders = typename get_placeholders>::placeholders; - using orm_placeholders = typename get_placeholders>::orm_placeholders; - }; - - template class get_placeholders_and_properties> - { - public: - using placeholders = typename get_placeholders_and_properties>::placeholders; - using orm_placeholders = typename get_placeholders_and_properties>::orm_placeholders; - }; -} // namespace webframe::ORM::details - -namespace webframe::ORM -{ - template static constexpr auto Placeholder = &details::placeholder::_; -} diff --git a/lib/include/ORM/details/result_type.hpp b/lib/include/ORM/details/result_type.hpp deleted file mode 100644 index 169e7c3..0000000 --- a/lib/include/ORM/details/result_type.hpp +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @file result_type.hpp - * @brief Result dataset class definition - * @author Alex Tsvetanov - * @date 2023-08-31 - ***********************************************/ - -#pragma once - -#include "member_pointer.hpp" -#include "orm_tuple.hpp" -#include - -namespace webframe::ORM::details -{ - constexpr auto result_all = []() consteval { return true; }; - constexpr auto result_properties = []() consteval { return details::is_property; }; - - template - requires requires { - { - filter.template operator()() - }; - } - class result_t - { - private: - template static constexpr auto result_t_utils(arg1 a, args1... A) - { - if constexpr (sizeof...(args1) == 0) - { - if constexpr (filter.template operator()()) - { - return orm_tuple(std::make_tuple(a)); - } - if constexpr (!filter.template operator()()) - { - return orm_tuple(std::tuple<>()); - } - } - if constexpr (sizeof...(args1) > 0) - { - return orm_tuple(std::tuple_cat(result_t_utils(a).to_tuple(), result_t_utils(A...).to_tuple())); - } - } - - public: - using type = decltype(result_t_utils((std::declval())...)); - - static constexpr type create(args... argv) - { - return result_t_utils(argv...); - } - - static constexpr type fuck_this_shit(args...) - { - } - }; -} // namespace webframe::ORM::details - -#include "../../../src/ORM/details/result_type.cpp" diff --git a/lib/include/ORM/details/warnings.hpp b/lib/include/ORM/details/warnings.hpp deleted file mode 100644 index e0e44ea..0000000 --- a/lib/include/ORM/details/warnings.hpp +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @file warnings.hpp - * @brief Warning disabling macros for certain scenarios - * @author Alex Tsvetanov - * @date 2023-08-31 - ***********************************************/ - -#pragma once - -#if defined(_MSC_VER) - #define DISABLE_WARNING_PUSH __pragma(warning(push)) - #define DISABLE_WARNING_PUSH3 __pragma(warning(push, 3)) - #define DISABLE_WARNING_POP __pragma(warning(pop)) - #define DISABLE_WARNING(warningNumber) __pragma(warning(disable : warningNumber)) - - #define DISABLE_WARNING_UNREACHABLE_CODE DISABLE_WARNING(4702) - #define DISABLE_WARNING_LOSS_OF_DATA DISABLE_WARNING(4244) -#elif defined(__GNUC__) || defined(__clang__) - #define DO_PRAGMA(X) _Pragma(#X) - #define DISABLE_WARNING_PUSH DO_PRAGMA(GCC diagnostic push) - #define DISABLE_WARNING_PUSH3 /**/ - #define DISABLE_WARNING_POP DO_PRAGMA(GCC diagnostic pop) - #define DISABLE_WARNING(warningName) DO_PRAGMA(GCC diagnostic ignored #warningName) - - #define DISABLE_WARNING_UNREACHABLE_CODE DISABLE_WARNING(-Wunreachable-code) - #define DISABLE_WARNING_LOSS_OF_DATA DISABLE_WARNING(-Wconversion) -#else - #define DISABLE_WARNING_PUSH /**/ - #define DISABLE_WARNING_PUSH3 /**/ - #define DISABLE_WARNING_POP /**/ - #define DISABLE_WARNING_UNREACHABLE_CODE /**/ - #define DISABLE_WARNING_LOSS_OF_DATA /**/ - - #define DISABLE_WARNING_USER_DEFINED_COMMA /**/ -#endif diff --git a/lib/include/ORM/fields.hpp b/lib/include/ORM/fields.hpp deleted file mode 100644 index e89c952..0000000 --- a/lib/include/ORM/fields.hpp +++ /dev/null @@ -1,152 +0,0 @@ -/** - * @file fields.hpp - * @brief Properties and relationships structures - * @author Alex Tsvetanov - * @date 2023-06-04 - ***********************************************/ - -#pragma once -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace webframe::ORM -{ - namespace details - { - class property - { - }; - - class relationship - { - }; - } // namespace details - - template class property; - - template - requires(!std::is_same_v && !std::is_same_v) - class property : public T, public details::property - { - public: - using var_t = typename T::native_type; - static constexpr std::string_view _name() - { - return lit.value; - } - - property() : T() - { - } - property(const T& a) : T(a) - { - } - - template - requires requires(Y a) { - { - static_cast(a) - }; - } - property(const Y& a) : T(static_cast(a)) - { - } - }; - - template - requires(std::is_same_v || std::is_same_v) - class property : public T, public details::property - { - public: - using var_t = T; - static constexpr std::string_view _name() - { - return lit.value; - } - - explicit inline operator T() - { - return *this; - } - - inline const T& operator=(auto _value) - { - return static_cast(*this) = _value; - } - }; - - template class property : public details::property - { - protected: - T value; - - public: - using var_t = T; - static constexpr std::string_view __name = lit.value; - static constexpr std::string_view _name() - { - return lit.value; - } - - property(const T value) : value(value) - { - } - property(T& value) : value(value) - { - } - - property() : value() - { - } - - inline operator T() const - { - return value; - } - inline operator T&() - { - return value; - } - - const T& operator=(auto _value) - { - value = _value; - return value; - } - }; - - enum RelationshipTypes - { - one2one, - one2many - }; - - template class relationship; - - template - class relationship<_type, external_ref, name> : public P, public details::relationship - { - public: - using Source = T; - static constexpr RelationshipTypes type = _type; - static constexpr inline std::string_view _name() - { - return name.to_sv(); - } - - protected: - std::vector records; - }; -} // namespace webframe::ORM - -#include "../../src/ORM/fields.cpp" diff --git a/lib/include/ORM/forward-decl.hpp b/lib/include/ORM/forward-decl.hpp new file mode 100644 index 0000000..e01ec94 --- /dev/null +++ b/lib/include/ORM/forward-decl.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include +#include +#include + +namespace webframe::ORM +{ + template + requires(details::is_database_wrapped_class) + class property; + + template class Rule; +} // namespace webframe::ORM diff --git a/lib/include/ORM/join_rule.hpp b/lib/include/ORM/join_rule.hpp deleted file mode 100644 index e02b404..0000000 --- a/lib/include/ORM/join_rule.hpp +++ /dev/null @@ -1,104 +0,0 @@ -/** - * @file join_rule.hpp - * @brief Wrapper for rules extended with join funcitonality - * @author Alex Tsvetanov - * @date 2023-09-21 - ***********************************************/ - -#pragma once - -#include "rules.hpp" -#include "CRUD/utils.hpp" - -using namespace std::literals; - -namespace webframe::ORM -{ - template class JoinRule : public rule_t - { - public: - static constexpr auto mode = _mode; - using Table = _Table; - constexpr JoinRule() : rule_t() - { - } - constexpr JoinRule(rule_t a) : rule_t(a) - { - } - constexpr JoinRule(auto a, auto b) : rule_t(a, b) - { - } - - constexpr operator rule_t() - { - return this->to_rule(); - } - - constexpr rule_t to_rule() const - { - return static_cast(*this); - } - }; - - template class GroupByRule; - - template class GroupByRule<_Properties, rule_t> : public rule_t - { - public: - using Properties = _Properties; - Properties properties; - static constexpr size_t size = Properties::size; - - constexpr GroupByRule() : rule_t() - { - } - constexpr GroupByRule(Properties a, rule_t b) : rule_t(b), properties(a) - { - } - constexpr GroupByRule(Properties p, auto a, auto b) : rule_t(a, b), properties(p) - { - } - - static constexpr bool has_rule() - { - return true; - } - - constexpr operator rule_t() - { - return this->to_rule(); - } - - constexpr rule_t to_rule() const - { - return static_cast(*this); - } - }; - - template class GroupByRule<_Properties, nullptr_t> - { - public: - using Properties = _Properties; - Properties properties; - static constexpr size_t size = Properties::size; - - constexpr GroupByRule() - { - } - constexpr GroupByRule(Properties a, nullptr_t) : properties(a) - { - } - - static constexpr bool has_rule() - { - return false; - } - }; - - template class OrderBy - { - public: - static constexpr auto property = P; - static constexpr auto sort = way; - }; -} // namespace webframe::ORM diff --git a/lib/include/ORM/limits.hpp b/lib/include/ORM/limits.hpp deleted file mode 100644 index 12343b4..0000000 --- a/lib/include/ORM/limits.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @file limits.hpp - * @brief Pagification literals - * @author Alex Tsvetanov - * @date 2023-08-31 - ***********************************************/ - -#pragma once - -namespace webframe::ORM -{ - class Pagification - { - private: - unsigned long long elements_per_page; - unsigned long long number_of_page; - - protected: - class Page; - class Per_page; - - public: - unsigned long long get_elements_per_page() const; - unsigned long long get_number_of_page() const; - constexpr Pagification(unsigned long long = 0, unsigned long long = 0); - friend constexpr Pagification operator&(Per_page, Page); - friend constexpr Pagification operator&(Page, Per_page); - friend constexpr Per_page operator""_per_page(unsigned long long); - friend constexpr Page operator""_page(unsigned long long); - }; -} // namespace webframe::ORM - -#include "../../src/ORM/limits.cpp" diff --git a/lib/include/ORM/query/delete.hpp b/lib/include/ORM/query/delete.hpp new file mode 100644 index 0000000..35d26d2 --- /dev/null +++ b/lib/include/ORM/query/delete.hpp @@ -0,0 +1,192 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace webframe::ORM +{ + namespace details + { + class IDelete; + + template class GenericDeleteQuery; + template class DeleteQuery; + + class IDelete : public IQuery + { + }; + + template class GenericDeleteQuery : public IDelete + { + typename WhereClauses::tuple_equivalent rules; + typename Orders::tuple_equivalent orders; + typename Limit::tuple_equivalent limits; + + public: + using UpdatedTable = Table; + using WhereRules = WhereClauses; + using OrderingRules = Orders; + using LimitRule = Limit; + + using parameters_type = typename details::tuple_of_the_placeholders::type; + using result_type = Table; + + protected: + constexpr GenericDeleteQuery( + typename WhereRules::tuple_equivalent _rules, typename Orders::tuple_equivalent _orders, typename Limit::tuple_equivalent _limits) + : rules(_rules), orders(_orders), limits(_limits) + { + } + + public: + constexpr typename WhereClauses::tuple_equivalent get_rules() const + { + return rules; + } + + constexpr typename Orders::tuple_equivalent get_orders() const + { + return orders; + } + + constexpr typename Limit::tuple_equivalent get_limits() const + { + return limits; + } + + template