diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..f94da0a4 --- /dev/null +++ b/.clang-format @@ -0,0 +1,53 @@ +Language: Cpp +AccessModifierOffset: -2 +ConstructorInitializerIndentWidth: 4 +AlignEscapedNewlinesLeft: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AlwaysBreakTemplateDeclarations: true +AlwaysBreakBeforeMultilineStrings: false +BreakBeforeBinaryOperators: false +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BinPackParameters: false +ColumnLimit: 160 +ConstructorInitializerAllOnOneLineOrOnePerLine: true +DerivePointerAlignment: false +ExperimentalAutoDetectBinPacking: false +IndentCaseLabels: true +IndentWrappedFunctionNames: false +IndentFunctionDeclarationAfterType: false +MaxEmptyLinesToKeep: 1 +KeepEmptyLinesAtTheStartOfBlocks: false +NamespaceIndentation: All +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: false +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakString: 1000 +PenaltyBreakFirstLessLess: 120 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Left +SpacesBeforeTrailingComments: 2 +Cpp11BracedListStyle: true +Standard: Cpp11 +IndentWidth: 2 +TabWidth: 2 +UseTab: Never +BreakBeforeBraces: Allman +SpacesInParentheses: false +SpacesInAngles: false +SpaceInEmptyParentheses: false +SpacesInCStyleCastParentheses: false +SpacesInContainerLiterals: true +SpaceBeforeAssignmentOperators: true +ContinuationIndentWidth: 4 +CommentPragmas: '^ IWYU pragma:' +ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] +SpaceBeforeParens: ControlStatements +DisableFormat: false diff --git a/.travis.yml b/.travis.yml index 39ee5821..24420177 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,12 +13,20 @@ notifications: on_failure: always before_install: + # install boost 1.50 (headers only), travis currently offers 1.46 and 1.48 + - wget http://sourceforge.net/projects/boost/files/boost/1.50.0/boost_1_50_0.tar.bz2/download -O /tmp/boost.tar.bz2 + - mkdir -p temp + - cd temp + - tar jxf /tmp/boost.tar.bz2 boost_1_50_0/boost # extract headers only + - sudo mkdir -p /usr/local/include/ + - sudo ln -s $PWD/boost_1_50_0/boost /usr/local/include + - cd .. + #install g++-4.8 - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - sudo apt-get update - if [ "$CXX" = "g++" ]; then sudo apt-get install g++-4.8; fi - if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi - install: - "mkdir -p $TRAVIS_BUILD_DIR/build/scripts" - "cd $TRAVIS_BUILD_DIR/build/scripts" diff --git a/CMakeLists.txt b/CMakeLists.txt index 69ca76f5..4f5266c2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2013-2014, Roland Bock +# Copyright (c) 2013-2015, Roland Bock # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, @@ -36,7 +36,7 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set(CMAKE_CXX_FLAGS "-std=c++11 -Wall ${CMAKE_CXX_FLAGS}") endif () -set(CMAKE_CXX_FLAGS "-Wconversion -Wpedantic ${CMAKE_CXX_FLAGS}") +set(CMAKE_CXX_FLAGS "-Wconversion -Wpedantic -Wshadow ${CMAKE_CXX_FLAGS}") set(include_dir "${PROJECT_SOURCE_DIR}/include") file(GLOB_RECURSE sqlpp_headers "${include_dir}/*.h") diff --git a/LICENSE b/LICENSE index 32872e75..6e8b716d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2013-2014, Roland Bock +Copyright (c) 2013-2015, Roland Bock All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/connector_api/bind_result.h b/connector_api/bind_result.h index c3b4e233..d14de772 100644 --- a/connector_api/bind_result.h +++ b/connector_api/bind_result.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/connector_api/connection.h b/connector_api/connection.h index e3b7a4dc..9a23d8b7 100644 --- a/connector_api/connection.h +++ b/connector_api/connection.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/connector_api/interpreter.h b/connector_api/interpreter.h index 90295276..d59add96 100644 --- a/connector_api/interpreter.h +++ b/connector_api/interpreter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/connector_api/prepared_statement.h b/connector_api/prepared_statement.h index bcd67293..1524e0f0 100644 --- a/connector_api/prepared_statement.h +++ b/connector_api/prepared_statement.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index bc461a0e..33b8e65f 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,9 +1,9 @@ macro (build arg) # Add headers to sources to enable file browsing in IDEs - include_directories("${CMAKE_SOURCE_DIR}/tests") - add_executable("Sqlpp11Example${arg}" "${arg}.cpp" ${sqlpp_headers} "${CMAKE_SOURCE_DIR}/tests/MockDb.h" "${CMAKE_CURRENT_LIST_DIR}/Sample.h") - add_test("${arg}" "${CMAKE_BINARY_DIR}/examples/Sqlpp11Example${arg}") + include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../tests") + add_executable("Sqlpp11Example${arg}" "${arg}.cpp" ${sqlpp_headers} "${CMAKE_CURRENT_SOURCE_DIR}/../tests/MockDb.h" "${CMAKE_CURRENT_LIST_DIR}/Sample.h") + add_test("${arg}" "Sqlpp11Example${arg}") endmacro () #build(sample) @@ -11,6 +11,13 @@ build(insert) build(update) build(remove) build(select) +find_package(Boost 1.50) +if(Boost_FOUND) + MESSAGE(${Boost_INCLUDE_DIRS}) + include_directories(${Boost_INCLUDE_DIRS}) + build(ppgen) +endif() + #find_package(PythonInterp REQUIRED) diff --git a/examples/Sample.h b/examples/Sample.h index 43aa3dc2..01e7d92d 100644 --- a/examples/Sample.h +++ b/examples/Sample.h @@ -3,6 +3,7 @@ #include #include +#include namespace test { @@ -10,9 +11,10 @@ namespace test { struct Id { - struct _name_t + struct _alias_t { - static constexpr const char* _get_name() { return "id"; } + static constexpr const char _literal[] = "id"; + using _name_t = sqlpp::make_char_sequence; template struct _member_t { @@ -25,9 +27,10 @@ namespace test }; struct Name { - struct _name_t + struct _alias_t { - static constexpr const char* _get_name() { return "name"; } + static constexpr const char _literal[] = "name"; + using _name_t = sqlpp::make_char_sequence; template struct _member_t { @@ -40,9 +43,10 @@ namespace test }; struct Feature { - struct _name_t + struct _alias_t { - static constexpr const char* _get_name() { return "feature"; } + static constexpr const char _literal[] = "feature"; + using _name_t = sqlpp::make_char_sequence; template struct _member_t { @@ -60,9 +64,10 @@ namespace test TabPerson_::Name, TabPerson_::Feature> { - struct _name_t + struct _alias_t { - static constexpr const char* _get_name() { return "tab_person"; } + static constexpr const char _literal[] = "tab_person"; + using _name_t = sqlpp::make_char_sequence; template struct _member_t { @@ -76,9 +81,10 @@ namespace test { struct Id { - struct _name_t + struct _alias_t { - static constexpr const char* _get_name() { return "id"; } + static constexpr const char _literal[] = "id"; + using _name_t = sqlpp::make_char_sequence; template struct _member_t { @@ -91,9 +97,10 @@ namespace test }; struct Name { - struct _name_t + struct _alias_t { - static constexpr const char* _get_name() { return "name"; } + static constexpr const char _literal[] = "name"; + using _name_t = sqlpp::make_char_sequence; template struct _member_t { @@ -106,9 +113,10 @@ namespace test }; struct Fatal { - struct _name_t + struct _alias_t { - static constexpr const char* _get_name() { return "fatal"; } + static constexpr const char _literal[] = "fatal"; + using _name_t = sqlpp::make_char_sequence; template struct _member_t { @@ -126,9 +134,10 @@ namespace test TabFeature_::Name, TabFeature_::Fatal> { - struct _name_t + struct _alias_t { - static constexpr const char* _get_name() { return "tab_feature"; } + static constexpr const char _literal[] = "tab_feature"; + using _name_t = sqlpp::make_char_sequence; template struct _member_t { diff --git a/examples/TabSample.h b/examples/TabSample.h index 377f9c2f..09e7f1ea 100644 --- a/examples/TabSample.h +++ b/examples/TabSample.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/examples/insert.cpp b/examples/insert.cpp index 5c79d5f9..40d2bdf4 100644 --- a/examples/insert.cpp +++ b/examples/insert.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Roland Bock + * Copyright (c) 2014-2015 Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/examples/ppgen.cpp b/examples/ppgen.cpp new file mode 100644 index 00000000..68889893 --- /dev/null +++ b/examples/ppgen.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if 0 // syntax example +SQLPP_DECLARE_TABLE( + (table, \ + SQLPP_DROP_IF_EXISTS \ + ,SQLPP_CREATE_IF_NOT_EXISTS \ + ,SQLPP_ENGINE("InnoDB") \ + ,SQLPP_CHARACTER_SET("utf-8") \ + ,SQLPP_COMMENT("table comments") \ + ) + , + (id, int, SQLPP_NOT_NULL, SQLPP_PRIMARY_KEY, SQLPP_AUTO_INCREMENT) + (name, varchar(64), SQLPP_NOT_NULL, SQLPP_INDEX("name_index"), SQLPP_DEFAULT("any name")) + (age, int, SQLPP_NOT_NULL, SQLPP_INDEX("age_index"), SQLPP_UNIQUE, SQLPP_COMMENT("some comments")) +) +#endif + +#include +#include + +#include "MockDb.h" + +SQLPP_DECLARE_TABLE( + (tab_person) + , + (id , int , SQLPP_AUTO_INCREMENT) + (name , varchar(255), SQLPP_NOT_NULL ) + (feature, int , SQLPP_NOT_NULL ) +) + +SQLPP_DECLARE_TABLE( + (tab_feature) + , + (id , int , SQLPP_AUTO_INCREMENT) + (name , varchar(255), SQLPP_NULL ) + (fatal, bool , SQLPP_NOT_NULL ) +) + +int main() { + MockDb db; + tab_person::tab_person p; + tab_feature::tab_feature f; + + db(insert_into(f).set(f.name = "loves c++", f.fatal = false)); + + //db(insert_into(f).set(f.nahme = "loves c++", f.fatal = false)); + + //db(insert_into(f).set(f.name == "loves c++", f.fatal = false)); + + //db(insert_into(f).set(f.name = "loves c++", f.fatal = "false")); + + //db(insert_into(p).set(f.name = "loves c++", f.fatal = false)); + + //db(insert_into(f).set(f.name = "loves c++", p.feature = 7)); + + //db(insert_into(f).set(f.id = 42, f.name = "loves c++", f.fatal = false)); + + //db(insert_into(f).set(f.name = "loves c++")); + + + db(insert_into(f).default_values()); + + auto i = insert_into(p).columns(p.name, p.feature); + i.values.add(p.name = "Roland", p.feature = 1); + i.values.add(p.name = "Zaphod", p.feature = sqlpp::default_value); + db(i); + + + auto pi = db.prepare(insert_into(p).set(p.name = parameter(f.name), p.feature = parameter(p.feature))); + pi.params.name = "likes java"; + pi.params.feature = true; + + db(pi); +} diff --git a/examples/remove.cpp b/examples/remove.cpp index 49b93799..e078a1d6 100644 --- a/examples/remove.cpp +++ b/examples/remove.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Roland Bock + * Copyright (c) 2014-2015 Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/examples/sample.cpp b/examples/sample.cpp index 5328df05..f5144fd0 100644 --- a/examples/sample.cpp +++ b/examples/sample.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Roland Bock + * Copyright (c) 2014-2015 Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/examples/select.cpp b/examples/select.cpp index 48d33521..53a2f33f 100644 --- a/examples/select.cpp +++ b/examples/select.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Roland Bock + * Copyright (c) 2014-2015 Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -34,6 +34,9 @@ #include "MockDb.h" #include +static constexpr bool some_condition = true; +static constexpr bool some_other_condition = false; + SQLPP_ALIAS_PROVIDER(cheesecake) MockDb db; @@ -91,8 +94,8 @@ int main() -#if !0 - auto s = select(all_of(p)) +#if 0 + auto s = select(p.id, p.name, f.id.as(cheesecake)) .from(p, f) .where(p.name == any(select(f.name) .from(f) @@ -103,12 +106,32 @@ int main() .limit(3).offset(7); auto x = s.as(sqlpp::alias::x); - for (const auto& row : db(select(p.id, x.name) - .from(p.join(x).on(p.feature == x.feature)) + for (const auto& row : db(select(p.id, p.name, all_of(x).as(x)) + .from(p.join(x).on(p.feature == x.cheesecake)) .where(true))) { int64_t id = row.id; std::string name = row.name; + std::string x_name = row.x.name; + int cheesecake = row.x.cheesecake; + } +#endif + + + +#if !0 + auto dysel = dynamic_select(db).dynamic_columns(p.name).from(p).dynamic_where(); + + if (some_condition) + dysel.selected_columns.add(p.feature); + + if (some_other_condition) + dysel.where.add(p.id > 17); + + for (const auto& row : db(dysel)) + { + std::string name = row.name; + std::string feature = row.at("feature"); } #endif @@ -129,7 +152,5 @@ int main() - - } diff --git a/examples/update.cpp b/examples/update.cpp index 82ffa37e..59580681 100644 --- a/examples/update.cpp +++ b/examples/update.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Roland Bock + * Copyright (c) 2014-2015 Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/alias.h b/include/sqlpp11/alias.h index 61cccb04..013d2e6f 100644 --- a/include/sqlpp11/alias.h +++ b/include/sqlpp11/alias.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -36,12 +36,12 @@ namespace sqlpp struct expression_alias_t { using _traits = make_traits, tag::is_selectable, tag::is_alias>; - using _recursive_traits = make_recursive_traits; + using _nodes = detail::type_vector; static_assert(is_expression_t::value, "invalid argument for an expression alias"); static_assert(not is_alias_t::value, "cannot create an alias of an alias"); - using _name_t = typename AliasProvider::_name_t; + using _alias_t = typename AliasProvider::_alias_t; Expression _expression; }; @@ -49,14 +49,14 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = expression_alias_t; static Context& _(const T& t, Context& context) { - context << '('; - serialize(t._expression, context); - context << ") AS "; - context << T::_name_t::_get_name(); + serialize_operand(t._expression, context); + context << " AS "; + context << name_of::char_ptr(); return context; } }; diff --git a/include/sqlpp11/alias_provider.h b/include/sqlpp11/alias_provider.h index 2b1dccda..86dba643 100644 --- a/include/sqlpp11/alias_provider.h +++ b/include/sqlpp11/alias_provider.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -28,13 +28,15 @@ #define SQLPP_ALIAS_PROVIDER_H #include +#include #define SQLPP_ALIAS_PROVIDER(name) \ struct name##_t\ {\ - struct _name_t\ + struct _alias_t\ {\ - static constexpr const char* _get_name() { return #name; }\ + static constexpr const char _literal[] = #name;\ + using _name_t = sqlpp::make_char_sequence;\ template\ struct _member_t\ {\ @@ -55,7 +57,7 @@ namespace sqlpp }; template - struct is_alias_provider_t>::value, void>::type> + struct is_alias_provider_t>::value, void>::type> { static constexpr bool value = true; }; diff --git a/include/sqlpp11/all_of.h b/include/sqlpp11/all_of.h index 021da0a8..55e2c206 100644 --- a/include/sqlpp11/all_of.h +++ b/include/sqlpp11/all_of.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -51,14 +51,26 @@ namespace sqlpp return {}; } + struct assert_no_stand_alone_all_of_t + { + using type = std::false_type; + + template + static void _() + { + static_assert(wrong_t::value, "all_of(table) seems to be used outside of select"); + } + }; + template struct serializer_t> { + using _serialize_check = assert_no_stand_alone_all_of_t; using T = all_of_t; static Context& _(const T& t, const Context&) { - static_assert(wrong_t::value, "all_of(table) does not seem to be used in select"); + _serialize_check::_(); } }; diff --git a/include/sqlpp11/any.h b/include/sqlpp11/any.h index 79d6aada..8585de1d 100644 --- a/include/sqlpp11/any.h +++ b/include/sqlpp11/any.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -28,6 +28,7 @@ #define SQLPP_ANY_H #include +#include #include namespace sqlpp @@ -36,11 +37,12 @@ namespace sqlpp struct any_t { using _traits = make_traits, tag::is_multi_expression>; - using _recursive_traits = make_recursive_traits; - struct _name_t + struct _alias_t { - static constexpr const char* _get_name() { return "ANY"; } + static constexpr const char _literal[] = "any_"; + using _name_t = sqlpp::make_char_sequence; template struct _member_t { @@ -66,6 +68,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = any_t
; - using _extra_tables = detail::type_set<>; - using _tags = typename std::conditional::value, - detail::type_set, - detail::type_set<>>::type; - }; + using _nodes = detail::type_vector<>; + using _required_tables = detail::type_set
; + using _can_be_null = column_spec_can_be_null_t; using _spec_t = ColumnSpec; using _table = Table; - using _name_t = typename _spec_t::_name_t; + using _alias_t = typename _spec_t::_alias_t; template using _is_valid_operand = is_valid_operand, T>; @@ -78,9 +70,11 @@ namespace sqlpp column_t& operator=(column_t&&) = default; ~column_t() = default; - static constexpr const char* _get_name() + template + auto table() const -> _table { - return _name_t::_get_name(); + static_assert(is_table_t::value, "cannot call get_table for columns of a sub-selects or cte"); + return _table{}; } template @@ -115,11 +109,12 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = consistent_t; using T = column_t; static Context& _(const T& t, Context& context) { - context << T::_table::_name_t::_get_name() << '.' << T::_name_t::_get_name(); + context << name_of::char_ptr() << '.' << name_of::char_ptr(); return context; } }; diff --git a/include/sqlpp11/column_fwd.h b/include/sqlpp11/column_fwd.h index 634bbe0b..c6899454 100644 --- a/include/sqlpp11/column_fwd.h +++ b/include/sqlpp11/column_fwd.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/column_types.h b/include/sqlpp11/column_types.h index 79f43f8b..66d0faac 100644 --- a/include/sqlpp11/column_types.h +++ b/include/sqlpp11/column_types.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/concat.h b/include/sqlpp11/concat.h index 3c37977c..bc0ac76b 100644 --- a/include/sqlpp11/concat.h +++ b/include/sqlpp11/concat.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -28,9 +28,10 @@ #define SQLPP_CONCAT_H #include +#include #include #include -#include +#include namespace sqlpp { @@ -41,13 +42,14 @@ namespace sqlpp public alias_operators> { using _traits = make_traits, tag::is_expression, tag::is_selectable>; - using _recursive_traits = make_recursive_traits; + using _nodes = detail::type_vector; static_assert(sizeof...(Args) > 0, "concat requires two arguments at least"); - static_assert(detail::all_t::value, is_text_t::value...>::value, "at least one non-text argument detected in concat()"); - struct _name_t + static_assert(logic::all_t::value, is_text_t::value...>::value, "at least one non-text argument detected in concat()"); + struct _alias_t { - static constexpr const char* _get_name() { return "CONCAT"; } + static constexpr const char _literal[] = "concat_"; + using _name_t = sqlpp::make_char_sequence; template struct _member_t { @@ -71,6 +73,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = concat_t; static Context& _(const T& t, Context& context) diff --git a/include/sqlpp11/connection.h b/include/sqlpp11/connection.h index 7f51fd41..49b178bd 100644 --- a/include/sqlpp11/connection.h +++ b/include/sqlpp11/connection.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/count.h b/include/sqlpp11/count.h index 95f30467..7abda19f 100644 --- a/include/sqlpp11/count.h +++ b/include/sqlpp11/count.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -27,6 +27,7 @@ #ifndef SQLPP_COUNT_H #define SQLPP_COUNT_H +#include #include #include @@ -38,23 +39,16 @@ namespace sqlpp public alias_operators> { using _traits = make_traits; - struct _recursive_traits - { - using _required_tables = required_tables_of; - using _provided_tables = provided_tables_of; - using _provided_outer_tables = provided_outer_tables_of; - using _extra_tables = extra_tables_of; - using _parameters = parameters_of; - using _tags = detail::make_difference_set_t, recursive_tags_of>, - detail::type_set>; - }; + using _nodes = detail::type_vector; + using _can_be_null = std::false_type; static_assert(is_noop::value or std::is_same::value, "count() used with flag other than 'distinct'"); - struct _name_t + struct _alias_t { - static constexpr const char* _get_name() { return "COUNT"; } + static constexpr const char _literal[] = "count_"; + using _name_t = sqlpp::make_char_sequence; template struct _member_t { @@ -80,6 +74,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = count_t; static Context& _(const T& t, Context& context) @@ -89,8 +84,12 @@ namespace sqlpp { serialize(Flag(), context); context << ' '; + serialize_operand(t._expr, context); + } + else + { + serialize(t._expr, context); } - serialize(t._expr, context); context << ")"; return context; } @@ -99,6 +98,7 @@ namespace sqlpp template auto count(T t) -> count_t> { + static_assert(not contains_aggregate_function_t>::value, "count() cannot be used on an aggregate function"); static_assert(is_expression_t>::value, "count() requires an expression as argument"); return { t }; } @@ -106,6 +106,7 @@ namespace sqlpp template auto count(const distinct_t&, T t) -> count_t> { + static_assert(not contains_aggregate_function_t>::value, "count() cannot be used on an aggregate function"); static_assert(is_expression_t>::value, "count() requires an expression as argument"); return { t }; } diff --git a/include/sqlpp11/cte.h b/include/sqlpp11/cte.h new file mode 100644 index 00000000..85105317 --- /dev/null +++ b/include/sqlpp11/cte.h @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2013-2015, Roland Bock + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SQLPP_CTE_H +#define SQLPP_CTE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sqlpp +{ + template + struct cte_union_t + { + using _nodes = detail::type_vector<>; + using _required_ctes = detail::make_joined_set_t, required_ctes_of>; + using _parameters = detail::type_vector_cat_t, parameters_of>; + + cte_union_t(Lhs lhs, Rhs rhs): + _lhs(lhs), + _rhs(rhs) + {} + + cte_union_t(const cte_union_t&) = default; + cte_union_t(cte_union_t&&) = default; + cte_union_t& operator=(const cte_union_t&) = default; + cte_union_t& operator=(cte_union_t&&) = default; + ~cte_union_t() = default; + + Lhs _lhs; + Rhs _rhs; + }; + + // Interpreters + template + struct serializer_t> + { + using _serialize_check = serialize_check_of; + using T = cte_union_t; + + static Context& _(const T& t, Context& context) + { + serialize(t._lhs, context); + context << " UNION "; + serialize(Flag{}, context); + context << " "; + serialize(t._rhs, context); + return context; + } + }; + + template + struct cte_t; + + template + struct cte_ref_t; + + template + auto from_table(cte_t t) -> cte_ref_t + { + return cte_ref_t{}; + } + + template + struct from_table_impl> + { + using type = cte_ref_t; + }; + + + template + struct cte_column_spec_t + { + using _alias_t = typename FieldSpec::_alias_t; + + using _traits = make_traits, + tag::must_not_insert, + tag::must_not_update, + tag_if::value> + >; + }; + + template + struct make_cte_impl + { + using type = void; + }; + + template + struct make_cte_impl> + { + using type = cte_t; + }; + + template + using make_cte_t = typename make_cte_impl>::type; + + template + struct cte_t: public member_t, column_t>>... + { + using _traits = make_traits; // FIXME: is table? really? + using _nodes = detail::type_vector<>; + using _required_ctes = detail::make_joined_set_t, detail::type_set>; + using _parameters = parameters_of; + + using _alias_t = typename AliasProvider::_alias_t; + constexpr static bool _is_recursive = detail::is_element_of>::value; + + using _column_tuple_t = std::tuple>...>; + + template + using _check = logic::all_t::value...>; + + using _result_row_t = result_row_t; + + template + auto union_distinct(Rhs rhs) const + -> typename std::conditional<_check::value, cte_t, FieldSpecs...>, bad_statement>::type + { + static_assert(is_statement_t::value, "argument of union call has to be a statement"); + static_assert(has_policy_t::value, "argument of union call has to be a select"); + static_assert(has_result_row_t::value, "argument of a union has to be a (complete) select statement"); + + static_assert(std::is_same<_result_row_t, get_result_row_t>::value, "both select statements in a union have to have the same result columns (type and name)"); + + return _union_impl(_check{}, rhs); + } + + template + auto union_all(Rhs rhs) const + -> typename std::conditional<_check::value, cte_t, FieldSpecs...>, bad_statement>::type + { + static_assert(is_statement_t::value, "argument of union call has to be a statement"); + static_assert(has_policy_t::value, "argument of union call has to be a select"); + static_assert(has_result_row_t::value, "argument of a union has to be a (complete) select statement"); + + static_assert(std::is_same<_result_row_t, get_result_row_t>::value, "both select statements in a union have to have the same result columns (type and name)"); + + return _union_impl(_check{}, rhs); + } + + private: + template + auto _union_impl(const std::false_type&, Rhs rhs) const + -> bad_statement; + + template + auto _union_impl(const std::true_type&, Rhs rhs) const + -> cte_t, FieldSpecs...> + { + return cte_union_t{_statement, rhs}; + } + + public: + + cte_t(Statement statement): _statement(statement){} + cte_t(const cte_t&) = default; + cte_t(cte_t&&) = default; + cte_t& operator=(const cte_t&) = default; + cte_t& operator=(cte_t&&) = default; + ~cte_t() = default; + + Statement _statement; + }; + + template + struct serializer_t> + { + using _serialize_check = serialize_check_of; + using T = cte_t; + + static Context& _(const T& t, Context& context) + { + context << name_of::char_ptr() << " AS ("; + serialize(t._statement, context); + context << ")"; + return context; + } + }; + + +// The cte_t is displayed as AliasProviderName except within the with: +// - the with needs the +// AliasProviderName AS (ColumnNames) (select/union) +// The result row of the select should not have dynamic parts + template + struct cte_ref_t + { + using _traits = make_traits; // FIXME: is table? really? + using _nodes = detail::type_vector<>; + using _required_ctes = detail::make_type_set_t; + using _provided_tables = detail::type_set; + + using _alias_t = typename AliasProvider::_alias_t; + + template + auto as(Statement statement) + -> make_cte_t + { + static_assert(required_tables_of::size::value == 0, "common table expression must not use unknown tables"); + static_assert(not detail::is_element_of>::value, "common table expression must not self-reference in the first part, use union_all/union_distinct for recursion"); + static_assert(is_static_result_row_t>::value, "ctes must not have dynamically added columns"); + + return { statement }; + } + }; + + template + struct serializer_t> + { + using _serialize_check = consistent_t; + using T = cte_ref_t; + + static Context& _(const T& t, Context& context) + { + context << name_of::char_ptr(); + return context; + } + }; + + template + auto cte(const AliasProvider&) + -> cte_ref_t + { + return {}; + } + +} + +#endif diff --git a/include/sqlpp11/custom_query.h b/include/sqlpp11/custom_query.h new file mode 100644 index 00000000..1868073b --- /dev/null +++ b/include/sqlpp11/custom_query.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2013-2015, Roland Bock + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SQLPP_CUSTOM_QUERY_H +#define SQLPP_CUSTOM_QUERY_H + +#include +#include +#include +#include + +namespace sqlpp +{ + template + struct custom_query_t; + + namespace detail + { + template + struct custom_parts_t + { + using _custom_query_t = custom_query_t; + using _result_type_provider = detail::get_first_if; + using _result_methods_t = typename _result_type_provider::template _result_methods_t<_result_type_provider>; + }; + } + + template + struct custom_query_t: + private detail::custom_parts_t::_result_methods_t + { + using _methods_t = typename detail::custom_parts_t::_result_methods_t; + using _traits = make_traits; + using _nodes = detail::type_vector; + + using _parameter_check = typename std::conditional>::value == 0, + consistent_t, assert_no_parameters_t>::type; + using _run_check = detail::get_first_if; + using _prepare_check = consistent_t; + + custom_query_t(Parts... parts): + _parts(parts...) + {} + + custom_query_t(std::tuple parts): + _parts(parts) + {} + + custom_query_t(const custom_query_t&) = default; + custom_query_t(custom_query_t&&) = default; + custom_query_t& operator=(const custom_query_t&) = default; + custom_query_t& operator=(custom_query_t&&) = default; + ~custom_query_t() = default; + + template + auto _run(Db& db) const -> decltype(std::declval<_methods_t>()._run(db, *this)) + { + _run_check::_(); + return _methods_t::_run(db, *this); + } + + template + auto _prepare(Db& db) const -> decltype(std::declval<_methods_t>()._prepare(db, *this)) + { + _prepare_check::_(); + return _methods_t::_prepare(db, *this); + } + + static constexpr size_t _get_static_no_of_parameters() + { + return std::tuple_size>::value; + } + + size_t _get_no_of_parameters() const + { + return _get_static_no_of_parameters(); + } + + template + auto with_result_type_of(Part part) + -> custom_query_t + { + return {tuple_cat(std::make_tuple(part), _parts)}; + } + + std::tuple _parts; + }; + + template + struct serializer_t> + { + using _serialize_check = serialize_check_of; + using T = custom_query_t; + + static Context& _(const T& t, Context& context) + { + interpret_tuple_without_braces(t._parts, " ", context); + return context; + } + }; + + template + auto custom_query(Parts... parts) + -> custom_query_t...> + { + static_assert(sizeof...(Parts) > 0, "custom query requires at least one argument"); + return custom_query_t...>(parts...); + } + + template + auto dynamic_custom_query(const Database&, Parts... parts) + -> custom_query_t...> + { + static_assert(sizeof...(Parts) > 0, "custom query requires at least one query argument"); + static_assert(std::is_base_of::value, "Invalid database parameter"); + + return custom_query_t...>(parts...); + } +} +#endif diff --git a/include/sqlpp11/default_value.h b/include/sqlpp11/default_value.h index 495f03c2..1a71442a 100644 --- a/include/sqlpp11/default_value.h +++ b/include/sqlpp11/default_value.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -34,7 +34,7 @@ namespace sqlpp struct default_value_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits<>; + using _nodes = detail::type_vector<>; static constexpr bool _is_trivial() { return false; } }; @@ -42,6 +42,7 @@ namespace sqlpp template struct serializer_t { + using _serialize_check = consistent_t; using Operand = default_value_t; static Context& _(const Operand& t, Context& context) diff --git a/include/sqlpp11/detail/copy_tuple_args.h b/include/sqlpp11/detail/copy_tuple_args.h index fafabe7b..4f6d483a 100644 --- a/include/sqlpp11/detail/copy_tuple_args.h +++ b/include/sqlpp11/detail/copy_tuple_args.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/detail/field_index_sequence.h b/include/sqlpp11/detail/field_index_sequence.h index 22e82318..e56c74bb 100644 --- a/include/sqlpp11/detail/field_index_sequence.h +++ b/include/sqlpp11/detail/field_index_sequence.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/detail/get_first.h b/include/sqlpp11/detail/get_first.h new file mode 100644 index 00000000..7d7a4d7d --- /dev/null +++ b/include/sqlpp11/detail/get_first.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013-2015, Roland Bock + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SQLPP_DETAIL_GET_FIRST_H +#define SQLPP_DETAIL_GET_FIRST_H + +#include + +namespace sqlpp +{ + namespace detail + { + template class Predicate, typename Default, typename... T> + struct get_first_if_impl; + + template class Predicate, typename Default> + struct get_first_if_impl + { + using type = Default; + }; + + template class Predicate, typename Default, typename T, typename... Rest> + struct get_first_if_impl + { + using rest = typename get_first_if_impl::type; + using type = typename std::conditional::value, + T, + rest>::type; + }; + + template class Predicate, typename Default, typename... T> + using get_first_if = typename get_first_if_impl::type; + } +} + + +#endif diff --git a/include/sqlpp11/detail/get_last.h b/include/sqlpp11/detail/get_last.h index 02bacd4b..0783c2d1 100644 --- a/include/sqlpp11/detail/get_last.h +++ b/include/sqlpp11/detail/get_last.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/detail/index_sequence.h b/include/sqlpp11/detail/index_sequence.h index c45a992f..df9edcea 100644 --- a/include/sqlpp11/detail/index_sequence.h +++ b/include/sqlpp11/detail/index_sequence.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/detail/pick_arg.h b/include/sqlpp11/detail/pick_arg.h index 6c922516..12a7a9c6 100644 --- a/include/sqlpp11/detail/pick_arg.h +++ b/include/sqlpp11/detail/pick_arg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/detail/sum.h b/include/sqlpp11/detail/sum.h index 9296b498..6ebce4ed 100644 --- a/include/sqlpp11/detail/sum.h +++ b/include/sqlpp11/detail/sum.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/detail/type_set.h b/include/sqlpp11/detail/type_set.h index 51e732f5..cad901b8 100644 --- a/include/sqlpp11/detail/type_set.h +++ b/include/sqlpp11/detail/type_set.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -27,10 +27,9 @@ #ifndef SQLPP_DETAIL_TYPE_SET_H #define SQLPP_DETAIL_TYPE_SET_H -#include #include #include -#include +#include namespace sqlpp { @@ -40,6 +39,9 @@ namespace sqlpp template struct make_type_set; + template + using make_type_set_t = typename make_type_set::type; + template struct is_element_of; @@ -50,7 +52,7 @@ namespace sqlpp using size = std::integral_constant; using _is_type_set = std::true_type; - static_assert(std::is_same::type>::value, "use make_type_set to construct a set"); + static_assert(std::is_same>::value, "use make_type_set to construct a typeset"); template struct insert @@ -79,7 +81,7 @@ namespace sqlpp template struct is_element_of> { - static constexpr bool value = any_t::value...>::value; + static constexpr bool value = ::sqlpp::logic::any_t::value...>::value; }; template @@ -91,7 +93,7 @@ namespace sqlpp template struct joined_set, type_set> { - using type = typename make_type_set::type; + using type = make_type_set_t; }; template @@ -139,9 +141,6 @@ namespace sqlpp using type = typename make_type_set::type::template insert::type; }; - template - using make_type_set_t = typename make_type_set::type; - template class Predicate, typename... T> struct make_type_set_if; @@ -168,8 +167,11 @@ namespace sqlpp using type = typename make_type_set_if::type; }; + template class Predicate, typename... T> + using make_type_set_if_not_t = typename make_type_set_if_not::type; + template - using has_duplicates = std::integral_constant::type::size::value != sizeof...(T)>; + using has_duplicates = std::integral_constant::size::value != sizeof...(T)>; template struct make_joined_set @@ -205,7 +207,7 @@ namespace sqlpp { template using is_subtrahend = is_element_of>; - using type = typename make_type_set_if_not::type; + using type = make_type_set_if_not_t; }; template @@ -221,8 +223,8 @@ namespace sqlpp struct make_intersect_set, type_set> { template - using is_in_both = all_t>::value, is_element_of>::value>; - using type = typename make_type_set_if::type; + using is_in_both = ::sqlpp::logic::all_t>::value, is_element_of>::value>; + using type = make_type_set_if_t; }; template @@ -238,7 +240,7 @@ namespace sqlpp template class Transformation, typename... E> struct transform_set> { - using type = typename make_type_set...>::type; + using type = make_type_set_t...>; }; template class Transformation, typename T> diff --git a/include/sqlpp11/detail/type_vector.h b/include/sqlpp11/detail/type_vector.h new file mode 100644 index 00000000..7b23b8c8 --- /dev/null +++ b/include/sqlpp11/detail/type_vector.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2013-2015, Roland Bock + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SQLPP_DETAIL_TYPE_VECTOR_H +#define SQLPP_DETAIL_TYPE_VECTOR_H + +#include + +namespace sqlpp +{ + namespace detail + { + template + struct type_vector + {}; + + template + struct type_vector_cat_impl + { + static_assert(wrong_t::value, "type_vector_cat must be called with type_vector arguments"); + }; + + template<> + struct type_vector_cat_impl<> + { + using type = type_vector<>; + }; + + template + struct type_vector_cat_impl> + { + using type = type_vector; + }; + + template + struct type_vector_cat_impl, type_vector> + { + using type = type_vector; + }; + + template + struct type_vector_cat_impl, Rest...> + { + using type = typename type_vector_cat_impl, typename type_vector_cat_impl::type>::type; + }; + + template + using type_vector_cat_t = typename type_vector_cat_impl::type; + + template + struct type_vector_size + { + static_assert(wrong_t::value, "type_vector_size needs to be called with a type_vector argument"); + }; + + template + struct type_vector_size> + { + static constexpr std::size_t value = sizeof...(T); + }; + } +} + + +#endif diff --git a/include/sqlpp11/eval.h b/include/sqlpp11/eval.h index 116b19f0..e425376a 100644 --- a/include/sqlpp11/eval.h +++ b/include/sqlpp11/eval.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -40,7 +40,7 @@ namespace sqlpp static_assert(is_database::value, "Db parameter of eval has to be a database connection"); static_assert(is_expression_t::value, "Expression parameter of eval has to be an sqlpp expression or a string"); static_assert(required_tables_of::size::value == 0, "Expression cannot be used in eval because it requires tables"); - using _name_type = alias::a_t::_name_t; + using _name_type = alias::a_t::_alias_t; using _value_type = value_type_of; using _field_spec = field_spec_t<_name_type, _value_type, true, false>; using type = result_field_t<_value_type, Db, _field_spec>; diff --git a/include/sqlpp11/exception.h b/include/sqlpp11/exception.h index 8b2fc6a2..dc96e9b2 100644 --- a/include/sqlpp11/exception.h +++ b/include/sqlpp11/exception.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/exists.h b/include/sqlpp11/exists.h index d1fe3d89..be72191f 100644 --- a/include/sqlpp11/exists.h +++ b/include/sqlpp11/exists.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -27,6 +27,7 @@ #ifndef SQLPP_EXISTS_H #define SQLPP_EXISTS_H +#include #include namespace sqlpp @@ -37,13 +38,14 @@ namespace sqlpp public alias_operators> { using _traits = make_traits; - using _recursive_traits = make_recursive_traits; static_assert(is_select_t; static Context& _(const T& t, Context& context) diff --git a/include/sqlpp11/expression.h b/include/sqlpp11/expression.h index c467c603..6aeebd16 100644 --- a/include/sqlpp11/expression.h +++ b/include/sqlpp11/expression.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -44,7 +44,7 @@ namespace sqlpp public alias_operators> { using _traits = make_traits; - using _recursive_traits = make_recursive_traits; + using _nodes = detail::type_vector; using _lhs_t = Lhs; using _rhs_t = rhs_wrap_t, trivial_value_is_null_t<_lhs_t>::value>; @@ -66,12 +66,13 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = equal_to_t; static Context& _(const T& t, Context& context) { context << "("; - serialize(t._lhs, context); + serialize_operand(t._lhs, context); if (t._rhs._is_null()) { context << " IS NULL"; @@ -79,7 +80,7 @@ namespace sqlpp else { context << "="; - serialize(t._rhs, context); + serialize_operand(t._rhs, context); } context << ")"; return context; @@ -92,7 +93,7 @@ namespace sqlpp public alias_operators> { using _traits = make_traits; - using _recursive_traits = make_recursive_traits; + using _nodes = detail::type_vector; using _lhs_t = Lhs; using _rhs_t = rhs_wrap_t, trivial_value_is_null_t<_lhs_t>::value>; @@ -114,12 +115,13 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = not_equal_to_t; static Context& _(const T& t, Context& context) { context << "("; - serialize(t._lhs, context); + serialize_operand(t._lhs, context); if (t._rhs._is_null()) { context << " IS NOT NULL"; @@ -127,7 +129,7 @@ namespace sqlpp else { context << "!="; - serialize(t._rhs, context); + serialize_operand(t._rhs, context); } context << ")"; return context; @@ -140,7 +142,7 @@ namespace sqlpp public alias_operators> { using _traits = make_traits; - using _recursive_traits = make_recursive_traits; + using _nodes = detail::type_vector; unary_expression_t(Rhs rhs): _rhs(rhs) @@ -158,6 +160,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = logical_not_t; static Context& _(const T& t, Context& context) @@ -165,13 +168,13 @@ namespace sqlpp context << "("; if (trivial_value_is_null_t::value) { - serialize(t._rhs, context); + serialize_operand(t._rhs, context); context << " IS NULL "; } else { context << "NOT "; - serialize(t._rhs, context); + serialize_operand(t._rhs, context); } context << ")"; @@ -185,7 +188,7 @@ namespace sqlpp public alias_operators> { using _traits = make_traits, tag::is_expression>; - using _recursive_traits = make_recursive_traits; + using _nodes = detail::type_vector; binary_expression_t(Lhs lhs, Rhs rhs): _lhs(lhs), @@ -205,14 +208,15 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = binary_expression_t; static Context& _(const T& t, Context& context) { context << "("; - serialize(t._lhs, context); + serialize_operand(t._lhs, context); context << O::_name; - serialize(t._rhs, context); + serialize_operand(t._rhs, context); context << ")"; return context; } @@ -224,7 +228,7 @@ namespace sqlpp public alias_operators> { using _traits = make_traits, tag::is_expression>; - using _recursive_traits = make_recursive_traits; + using _nodes = detail::type_vector; unary_expression_t(Rhs rhs): _rhs(rhs) @@ -242,13 +246,14 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = unary_expression_t; static Context& _(const T& t, Context& context) { context << "("; context << O::_name; - serialize(t._rhs, context); + serialize_operand(t._rhs, context); context << ")"; return context; } diff --git a/include/sqlpp11/expression_fwd.h b/include/sqlpp11/expression_fwd.h index 5e5396a5..6562ee53 100644 --- a/include/sqlpp11/expression_fwd.h +++ b/include/sqlpp11/expression_fwd.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/extra_tables.h b/include/sqlpp11/extra_tables.h index d2fe8a73..3a60e5f6 100644 --- a/include/sqlpp11/extra_tables.h +++ b/include/sqlpp11/extra_tables.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -28,7 +28,7 @@ #define SQLPP_EXTRA_TABLES_H #include -#include +#include #include namespace sqlpp @@ -52,21 +52,9 @@ namespace sqlpp struct extra_tables_t { using _traits = make_traits; - struct _recursive_traits - { - using _parameters = std::tuple<>; - using _required_tables = detail::type_set<>; - using _provided_outer_tables = detail::type_set<>; - using _provided_tables = detail::type_set<>; - using _extra_tables = detail::type_set; - using _tags = detail::type_set<>; - }; - - // FIXME: extra_tables must not require tables! - - static_assert(sizeof...(Tables), "at least one table or join argument required in extra_tables()"); - static_assert(not detail::has_duplicates::value, "at least one duplicate argument detected in extra_tables()"); - static_assert(detail::all_t::value...>::value, "at least one argument is not a table or join in extra_tables()"); + using _nodes = detail::type_vector<>; + using _required_ctes = detail::make_joined_set_t...>; + using _extra_tables = detail::type_set; // Data using _data_t = extra_tables_data_t; @@ -78,9 +66,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = extra_tables_data_t; @@ -93,13 +81,8 @@ namespace sqlpp { return t.extra_tables; } - }; - // Additional methods for the statement - template - struct _methods_t - { - static void _check_consistency() {} + using _consistency_check = consistent_t; }; }; @@ -107,7 +90,7 @@ namespace sqlpp struct no_extra_tables_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits<>; + using _nodes = detail::type_vector<>; // Data using _data_t = no_data_t; @@ -119,9 +102,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = no_data_t; @@ -134,21 +117,42 @@ namespace sqlpp { return t.no_extra_tables; } - }; - template - struct _methods_t - { - template - using _new_statement_t = new_statement; + template + using _new_statement_t = new_statement_t; - static void _check_consistency() {} + template + using _check = logic::all_t::value...>; - template - auto extra_tables(Args...) const - -> _new_statement_t> + using _consistency_check = consistent_t; + + template + auto extra_tables(Tables... tables) const + -> _new_statement_t<_check, extra_tables_t> { - return { static_cast&>(*this), extra_tables_data_t{} }; + static_assert(_check::value, "at least one argument is not a table or join in extra_tables()"); + + return _extra_tables_impl(_check{}, tables...); + } + + private: + template + auto _extra_tables_impl(const std::false_type&, Tables... tables) const + -> bad_statement; + + template + auto _extra_tables_impl(const std::true_type&, Tables...) const + -> _new_statement_t> + { + static_assert(required_tables_of>::size::value == 0, "at least one table depends on another table in extra_tables()"); + + static constexpr std::size_t _number_of_tables = detail::sum(provided_tables_of::size::value...); + using _unique_tables = detail::make_joined_set_t...>; + using _unique_table_names = detail::transform_set_t; + static_assert(_number_of_tables == _unique_tables::size::value, "at least one duplicate table detected in extra_tables()"); + static_assert(_number_of_tables == _unique_table_names::size::value, "at least one duplicate table name detected in extra_tables()"); + + return { static_cast&>(*this), extra_tables_data_t{} }; } }; }; @@ -157,6 +161,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = extra_tables_data_t; static Context& _(const T& t, Context& context) diff --git a/include/sqlpp11/field_spec.h b/include/sqlpp11/field_spec.h index ee2ae33c..d2ed9f25 100644 --- a/include/sqlpp11/field_spec.h +++ b/include/sqlpp11/field_spec.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -38,9 +38,9 @@ namespace sqlpp tag_if, tag_if >; - using _recursive_traits = make_recursive_traits<>; + using _nodes = detail::type_vector<>; - using _name_t = NameType; + using _alias_t = NameType; }; template @@ -56,9 +56,9 @@ namespace sqlpp static constexpr bool _can_be_null = can_be_null_t::value; static constexpr bool _depends_on_outer_table = detail::make_intersect_set_t, typename Select::_used_outer_tables>::size::value > 0; - using type = field_spec_t, - detail::any_t<_can_be_null, _depends_on_outer_table>::value, + logic::any_t<_can_be_null, _depends_on_outer_table>::value, null_is_trivial_value_t::value>; }; diff --git a/include/sqlpp11/floating_point.h b/include/sqlpp11/floating_point.h index ac0915a0..2408d946 100644 --- a/include/sqlpp11/floating_point.h +++ b/include/sqlpp11/floating_point.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/from.h b/include/sqlpp11/from.h index d5a41cf7..91274bc1 100644 --- a/include/sqlpp11/from.h +++ b/include/sqlpp11/from.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -27,11 +27,12 @@ #ifndef SQLPP_FROM_H #define SQLPP_FROM_H +#include #include #include #include #include -#include +#include #include #include @@ -60,7 +61,7 @@ namespace sqlpp struct from_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits; + using _nodes = detail::type_vector; using _is_dynamic = is_database; // Data @@ -77,9 +78,11 @@ namespace sqlpp static_assert(is_table_t
::value, "invalid table argument in from::add()"); using _known_tables = detail::make_joined_set_t...>; // Hint: Joins contain more than one table using _known_table_names = detail::transform_set_t; - static_assert(not detail::is_element_of::value, "Must not use the same table name twice in from()"); + static_assert(not detail::is_element_of::value, "Must not use the same table name twice in from()"); + using _serialize_check = sqlpp::serialize_check_t; + _serialize_check::_(); - using ok = detail::all_t<_is_dynamic::value, is_table_t
::value>; + using ok = logic::all_t<_is_dynamic::value, is_table_t
::value, _serialize_check::type::value>; _add_impl(table, ok()); // dispatch to prevent compile messages after the static_assert } @@ -88,7 +91,7 @@ namespace sqlpp template void _add_impl(Table table, const std::true_type&) { - return _data._dynamic_tables.emplace_back(table); + return _data._dynamic_tables.emplace_back(from_table(table)); } template @@ -98,9 +101,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = from_data_t; @@ -113,20 +116,16 @@ namespace sqlpp { return t.from; } - }; - // Additional methods for the statement - template - struct _methods_t - { - static void _check_consistency() {} + // FIXME: We might want to check if we have too many tables define in the FROM + using _consistency_check = consistent_t; }; }; struct no_from_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits<>; + using _nodes = detail::type_vector<>; // Data using _data_t = no_data_t; @@ -138,9 +137,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = no_data_t; @@ -153,41 +152,45 @@ namespace sqlpp { return t.no_from; } - }; - // Additional methods for the statement - template - struct _methods_t - { using _database_t = typename Policies::_database_t; - template - using _new_statement_t = new_statement; - static void _check_consistency() {} + template + using _check = logic::all_t::value...>; + + template + using _new_statement_t = new_statement_t; + + using _consistency_check = consistent_t; template auto from(Tables... tables) const - -> _new_statement_t> + -> _new_statement_t<_check, from_t...>> { + static_assert(_check::value, "at least one argument is not a table or join in from()"); static_assert(sizeof...(Tables), "at least one table or join argument required in from()"); - return _from_impl(tables...); + return _from_impl(_check{}, tables...); } template auto dynamic_from(Tables... tables) const - -> _new_statement_t> + -> _new_statement_t<_check, from_t<_database_t, from_table_t...>> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_from must not be called in a static statement"); - return _from_impl<_database_t>(tables...); + static_assert(_check::value, "at least one argument is not a table or join in from()"); + return _from_impl<_database_t>(_check{}, tables...); } private: template - auto _from_impl(Tables... tables) const - -> _new_statement_t> + auto _from_impl(const std::false_type&, Tables... tables) const + -> bad_statement; + + template + auto _from_impl(const std::true_type&, Tables... tables) const + -> _new_statement_t...>> { - static_assert(detail::all_t::value...>::value, "at least one argument is not a table or join in from()"); - static_assert(required_tables_of>::size::value == 0, "at least one table depends on another table"); + static_assert(required_tables_of>::size::value == 0, "at least one table depends on another table in from()"); static constexpr std::size_t _number_of_tables = detail::sum(provided_tables_of::size::value...); using _unique_tables = detail::make_joined_set_t...>; @@ -195,7 +198,7 @@ namespace sqlpp static_assert(_number_of_tables == _unique_tables::size::value, "at least one duplicate table detected in from()"); static_assert(_number_of_tables == _unique_table_names::size::value, "at least one duplicate table name detected in from()"); - return { static_cast&>(*this), from_data_t{tables...} }; + return { static_cast&>(*this), from_data_t...>{from_table(tables)...} }; } }; @@ -205,6 +208,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = from_data_t; static Context& _(const T& t, Context& context) @@ -220,6 +224,11 @@ namespace sqlpp } }; + template + auto from(T&&... t) -> decltype(statement_t().from(std::forward(t)...)) + { + return statement_t().from(std::forward(t)...); + } } #endif diff --git a/include/sqlpp11/functions.h b/include/sqlpp11/functions.h index 75eacd90..46776612 100644 --- a/include/sqlpp11/functions.h +++ b/include/sqlpp11/functions.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -31,7 +31,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -80,7 +82,7 @@ namespace sqlpp struct value_list_t // to be used in .in() method { using _traits = make_traits, tag::is_expression>; - using _recursive_traits = make_recursive_traits<>; + using _nodes = detail::type_vector<>; using _container_t = Container; @@ -100,10 +102,16 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of>; using T = value_list_t; static Context& _(const T& t, Context& context) { + if (t._container.size() == 1) + { + return serialize(value(*begin(t._container)), context); + } + bool first = true; for (const auto& entry: t._container) { @@ -112,7 +120,7 @@ namespace sqlpp else context << ','; - serialize(value(entry), context); + serialize_operand(value(entry), context); } return context; } @@ -128,7 +136,7 @@ namespace sqlpp template constexpr const char* get_sql_name(const T&) { - return T::_name_t::_get_name(); + return name_of::char_ptr(); } diff --git a/include/sqlpp11/group_by.h b/include/sqlpp11/group_by.h index 89792311..52f9a338 100644 --- a/include/sqlpp11/group_by.h +++ b/include/sqlpp11/group_by.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -33,7 +33,7 @@ #include #include #include -#include +#include namespace sqlpp { @@ -55,21 +55,26 @@ namespace sqlpp interpretable_list_t _dynamic_expressions; }; + struct assert_no_unknown_tables_in_group_by_t + { + using type = std::false_type; + + template + static void _() + { + static_assert(wrong_t::value, "at least one group-by expression requires a table which is otherwise not known in the statement"); + } + }; + // GROUP BY template struct group_by_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits; + using _nodes = detail::type_vector; using _is_dynamic = is_database; - static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression (e.g. a column) required in group_by()"); - - static_assert(not detail::has_duplicates::value, "at least one duplicate argument detected in group_by()"); - - static_assert(detail::all_t::value...>::value, "at least one argument is not an expression in group_by()"); - // Data using _data_t = group_by_data_t; @@ -89,8 +94,10 @@ namespace sqlpp static_assert(_is_dynamic::value, "add() must not be called for static group_by"); static_assert(is_expression_t::value, "invalid expression argument in group_by::add()"); static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables::value, "expression uses tables unknown to this statement in group_by::add()"); + using _serialize_check = sqlpp::serialize_check_t; + _serialize_check::_(); - using ok = detail::all_t<_is_dynamic::value, is_expression_t::value>; + using ok = logic::all_t<_is_dynamic::value, is_expression_t::value, _serialize_check::type::value>; _add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert } @@ -108,9 +115,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = group_by_data_t; @@ -123,12 +130,10 @@ namespace sqlpp { return t.group_by; } - }; - template - struct _methods_t - { - static void _check_consistency() {} + using _consistency_check = typename std::conditional::value, + consistent_t, + assert_no_unknown_tables_in_group_by_t>::type; }; }; @@ -136,7 +141,7 @@ namespace sqlpp struct no_group_by_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits<>; + using _nodes = detail::type_vector<>; // Data using _data_t = no_data_t; @@ -148,9 +153,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = no_data_t; @@ -163,31 +168,50 @@ namespace sqlpp { return t.no_group_by; } - }; - template - struct _methods_t - { using _database_t = typename Policies::_database_t; - template - using _new_statement_t = new_statement; - static void _check_consistency() {} + template + using _check = logic::all_t::value...>; - template - auto group_by(Args... args) const - -> _new_statement_t> + template + using _new_statement_t = new_statement_t; + + using _consistency_check = consistent_t; + + template + auto group_by(Expressions... expressions) const + -> _new_statement_t<_check, group_by_t> { - return { static_cast&>(*this), group_by_data_t{args...} }; + static_assert(sizeof...(Expressions), "at least one expression (e.g. a column) required in group_by()"); + static_assert(_check::value, "at least one argument is not an expression in group_by()"); + + return _group_by_impl(_check{}, expressions...); } - template - auto dynamic_group_by(Args... args) const - -> _new_statement_t> + template + auto dynamic_group_by(Expressions... expressions) const + -> _new_statement_t<_check, group_by_t<_database_t, Expressions...>> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_group_by must not be called in a static statement"); - return { static_cast&>(*this), group_by_data_t<_database_t, Args...>{args...} }; + static_assert(_check::value, "at least one argument is not an expression in group_by()"); + + return _group_by_impl<_database_t>(_check{}, expressions...); } + + private: + template + auto _group_by_impl(const std::false_type&, Expressions... expressions) const + -> bad_statement; + + template + auto _group_by_impl(const std::true_type&, Expressions... expressions) const + -> _new_statement_t> + { + static_assert(not detail::has_duplicates::value, "at least one duplicate argument detected in group_by()"); + + return { static_cast&>(*this), group_by_data_t{expressions...} }; + } }; }; @@ -195,6 +219,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = group_by_data_t; static Context& _(const T& t, Context& context) diff --git a/include/sqlpp11/having.h b/include/sqlpp11/having.h index cd412c7c..b69b5f1a 100644 --- a/include/sqlpp11/having.h +++ b/include/sqlpp11/having.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -32,7 +32,7 @@ #include #include #include -#include +#include namespace sqlpp { @@ -54,18 +54,26 @@ namespace sqlpp interpretable_list_t _dynamic_expressions; }; + struct assert_no_unknown_tables_in_having_t + { + using type = std::false_type; + + template + static void _() + { + static_assert(wrong_t::value, "at least one having-expression requires a table which is otherwise not known in the statement"); + } + }; + // HAVING template struct having_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits; + using _nodes = detail::type_vector; using _is_dynamic = is_database; - static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in having()"); - static_assert(detail::all_t::value...>::value, "at least one argument is not an expression in having()"); - // Data using _data_t = having_data_t; @@ -85,8 +93,10 @@ namespace sqlpp static_assert(_is_dynamic::value, "having::add() can only be called for dynamic_having"); static_assert(is_expression_t::value, "invalid expression argument in having::add()"); static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables::value, "expression uses tables unknown to this statement in having::add()"); + using _serialize_check = sqlpp::serialize_check_t; + _serialize_check::_(); - using ok = detail::all_t<_is_dynamic::value, is_expression_t::value>; + using ok = logic::all_t<_is_dynamic::value, is_expression_t::value, _serialize_check::type::value>; _add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert } @@ -105,9 +115,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = having_data_t; @@ -120,13 +130,10 @@ namespace sqlpp { return t.having; } - }; - // Additional methods for the statement - template - struct _methods_t - { - static void _check_consistency() {} + using _consistency_check = typename std::conditional::value, + consistent_t, + assert_no_unknown_tables_in_having_t>::type; }; }; @@ -134,7 +141,7 @@ namespace sqlpp struct no_having_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits<>; + using _nodes = detail::type_vector<>; // Data using _data_t = no_data_t; @@ -146,9 +153,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = no_data_t; @@ -161,31 +168,48 @@ namespace sqlpp { return t.no_having; } - }; - template - struct _methods_t - { using _database_t = typename Policies::_database_t; - template - using _new_statement_t = new_statement; - static void _check_consistency() {} + template + using _check = logic::all_t::value...>; - template - auto having(Args... args) const - -> _new_statement_t> + template + using _new_statement_t = new_statement_t; + + using _consistency_check = consistent_t; + + template + auto having(Expressions... expressions) const + -> _new_statement_t<_check, having_t> { - return { static_cast&>(*this), having_data_t{args...} }; + static_assert(_check::value, "at least one argument is not an expression in having()"); + static_assert(sizeof...(Expressions), "at least one expression argument required in having()"); + + return _having_impl(_check{}, expressions...); } - template - auto dynamic_having(Args... args) const - -> _new_statement_t> + template + auto dynamic_having(Expressions... expressions) const + -> _new_statement_t<_check, having_t<_database_t, Expressions...>> { + static_assert(_check::value, "at least one argument is not an expression in having()"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_having must not be called in a static statement"); - return { static_cast&>(*this), having_data_t<_database_t, Args...>{args...} }; + return _having_impl<_database_t>(_check{}, expressions...); } + + private: + template + auto _having_impl(const std::false_type&, Expressions... expressions) const + -> bad_statement; + + template + auto _having_impl(const std::true_type&, Expressions... expressions) const + -> _new_statement_t> + { + return { static_cast&>(*this), having_data_t<_database_t, Expressions...>{expressions...} }; + } + }; }; @@ -193,6 +217,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = having_data_t; static Context& _(const T& t, Context& context) diff --git a/include/sqlpp11/hidden.h b/include/sqlpp11/hidden.h new file mode 100644 index 00000000..313ae6b8 --- /dev/null +++ b/include/sqlpp11/hidden.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2013-2015, Roland Bock + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SQLPP_HIDDEN_H +#define SQLPP_HIDDEN_H + +namespace sqlpp +{ + template + struct hidden_t: + public Part + { + hidden_t(Part part): + Part(part) + {} + + hidden_t(const hidden_t&) = default; + hidden_t(hidden_t&&) = default; + hidden_t& operator=(const hidden_t&) = default; + hidden_t& operator=(hidden_t&&) = default; + ~hidden_t() = default; + }; + + template + struct serializer_t> + { + using _serialize_check = consistent_t; + using T = hidden_t; + + static Context& _(const T& t, Context& context) + { + return context; + } + }; + + template + auto hidden(Part part) + -> hidden_t + { + return {part}; + } +} +#endif diff --git a/include/sqlpp11/in.h b/include/sqlpp11/in.h index 3d8a98a0..0176e379 100644 --- a/include/sqlpp11/in.h +++ b/include/sqlpp11/in.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -28,26 +28,27 @@ #define SQLPP_IN_H #include +#include #include #include #include namespace sqlpp { - template + template struct in_t: - public expression_operators, boolean>, - public alias_operators> + public expression_operators, boolean>, + public alias_operators> { using _traits = make_traits; - using _recursive_traits = make_recursive_traits; + using _nodes = detail::type_vector; - static constexpr bool _inverted = not NotInverted; static_assert(sizeof...(Args) > 0, "in() requires at least one argument"); - struct _name_t + struct _alias_t { - static constexpr const char* _get_name() { return _inverted ? "NOT IN" : "IN"; } + static constexpr const char _literal[] = "in_"; + using _name_t = sqlpp::make_char_sequence; template struct _member_t { @@ -70,18 +71,18 @@ namespace sqlpp std::tuple _args; }; - template - struct serializer_t> + template + struct serializer_t> { - using T = in_t; + using _serialize_check = serialize_check_of; + using T = in_t; static Context& _(const T& t, Context& context) { serialize(t._operand, context); - context << (t._inverted ? " NOT IN(" : " IN("); + context << " IN("; if (sizeof...(Args) == 1) - serialize(std::get<0>(t._args), context); // FIXME: this is a bit of a hack until there is a better overall strategy for using braces - // see https://github.com/rbock/sqlpp11/issues/18 + serialize(std::get<0>(t._args), context); else interpret_tuple(t._args, ',', context); context << ')'; diff --git a/include/sqlpp11/in_fwd.h b/include/sqlpp11/in_fwd.h index 3b464307..becbfbbe 100644 --- a/include/sqlpp11/in_fwd.h +++ b/include/sqlpp11/in_fwd.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -29,8 +29,10 @@ namespace sqlpp { - template + template struct in_t; + template + struct not_in_t; } diff --git a/include/sqlpp11/insert.h b/include/sqlpp11/insert.h index d6e1bc3a..e639be61 100644 --- a/include/sqlpp11/insert.h +++ b/include/sqlpp11/insert.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -44,41 +44,53 @@ namespace sqlpp struct insert_t: public statement_name_t { using _traits = make_traits; - struct _name_t {}; + struct _alias_t {}; - template + template struct _result_methods_t { - using _statement_t = derived_statement_t; + using _statement_t = Statement; const _statement_t& _get_statement() const { return static_cast(*this); } + // Execute + template + auto _run(Db& db, const Composite& composite) const + -> decltype(db.insert(composite)) + { + return db.insert(composite); + } + template auto _run(Db& db) const -> decltype(db.insert(this->_get_statement())) { - _statement_t::_check_consistency(); - - static_assert(_statement_t::_get_static_no_of_parameters() == 0, "cannot run insert directly with parameters, use prepare instead"); return db.insert(_get_statement()); } - template - auto _prepare(Db& db) const - -> prepared_insert_t - { - _statement_t::_check_consistency(); + // Prepare + template + auto _prepare(Db& db, const Composite& composite) const + -> prepared_insert_t + { + return {{}, db.prepare_insert(composite)}; + } - return {{}, db.prepare_insert(_get_statement())}; - } + template + auto _prepare(Db& db) const + -> prepared_insert_t + { + return {{}, db.prepare_insert(_get_statement())}; + } }; }; template struct serializer_t { + using _serialize_check = consistent_t; using T = insert_name_t; static Context& _(const T& t, Context& context) diff --git a/include/sqlpp11/insert_value.h b/include/sqlpp11/insert_value.h index 061bbd82..c7436884 100644 --- a/include/sqlpp11/insert_value.h +++ b/include/sqlpp11/insert_value.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -50,7 +50,7 @@ namespace sqlpp struct type { using _traits = make_traits; - using _recursive_traits = make_recursive_traits<>; + using _nodes = detail::type_vector<>; }; }; } @@ -103,6 +103,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = insert_value_t; static Context& _(const T& t, Context& context) @@ -115,7 +116,7 @@ namespace sqlpp else if (t._is_default) context << "DEFAULT"; else - serialize(t._value, context); + serialize_operand(t._value, context); return context; } }; diff --git a/include/sqlpp11/insert_value_list.h b/include/sqlpp11/insert_value_list.h index 8f07b51e..5ea72f78 100644 --- a/include/sqlpp11/insert_value_list.h +++ b/include/sqlpp11/insert_value_list.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -28,7 +28,7 @@ #define SQLPP_INSERT_VALUE_LIST_H #include -#include +#include #include #include #include @@ -41,20 +41,20 @@ namespace sqlpp { namespace detail { - template - struct first_arg_impl + template + struct have_all_required_columns { - static_assert(wrong_t::value, "At least one argument required"); + static constexpr bool value = false; }; - template - struct first_arg_impl + template + struct have_all_required_columns { - using type = T; + using _table = typename First::_table; + using required_columns = typename _table::_required_insert_columns; + using set_columns = detail::make_type_set_t; + static constexpr bool value = detail::is_subset_of::value; }; - - template - using first_arg_t = typename first_arg_impl::type; } struct insert_default_values_data_t @@ -64,7 +64,7 @@ namespace sqlpp struct insert_default_values_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits<>; + using _nodes = detail::type_vector<>; // Data using _data_t = insert_default_values_data_t; @@ -76,9 +76,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = insert_default_values_data_t; @@ -91,12 +91,8 @@ namespace sqlpp { return t.default_values; } - }; - template - struct _methods_t - { - static void _check_consistency() {} + using _consistency_check = consistent_t; }; }; @@ -122,11 +118,22 @@ namespace sqlpp interpretable_list_t _dynamic_values; }; + struct assert_no_unknown_tables_in_insert_assignments_t + { + using type = std::false_type; + + template + static void _() + { + static_assert(wrong_t::value, "at least one insert assignment requires a table which is otherwise not known in the statement"); + } + }; + template struct insert_list_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits..., rhs_t...>; + using _nodes = detail::type_vector..., rhs_t...>; using _is_dynamic = is_database; @@ -157,10 +164,13 @@ namespace sqlpp static_assert(not detail::is_element_of, _assigned_columns>::value, "Must not assign value to column twice"); static_assert(not must_not_insert_t>::value, "add() argument must not be used in insert"); static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables::value, "add() contains a column from a foreign table"); + using _serialize_check = sqlpp::serialize_check_t; + _serialize_check::_(); - using ok = detail::all_t< + using ok = logic::all_t< _is_dynamic::value, - is_assignment_t::value>; + is_assignment_t::value, + _serialize_check::type::value>; _add_impl(assignment, ok()); // dispatch to prevent compile messages after the static_assert } @@ -179,9 +189,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = insert_list_data_t; @@ -194,13 +204,10 @@ namespace sqlpp { return t.insert_list; } - }; - // Additional methods for the statement - template - struct _methods_t - { - static void _check_consistency() {} + using _consistency_check = typename std::conditional::value, + consistent_t, + assert_no_unknown_tables_in_insert_assignments_t>::type; }; }; @@ -223,11 +230,22 @@ namespace sqlpp std::vector<_value_tuple_t> _insert_values; }; + struct assert_no_unknown_tables_in_column_list_t + { + using type = std::false_type; + + template + static void _() + { + static_assert(wrong_t::value, "at least one column requires a table which is otherwise not known in the statement"); + } + }; + template struct column_list_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits; + using _nodes = detail::type_vector; using _value_tuple_t = typename column_list_data_t::_value_tuple_t; @@ -242,13 +260,13 @@ namespace sqlpp template void add(Assignments... assignments) { - static_assert(detail::all_t::value...>::value, "add_values() arguments have to be assignments"); + static_assert(logic::all_t::value...>::value, "add_values() arguments have to be assignments"); using _arg_value_tuple = std::tuple>...>; using _args_correct = std::is_same<_arg_value_tuple, _value_tuple_t>; static_assert(_args_correct::value, "add_values() arguments do not match columns() arguments"); - using ok = detail::all_t< - detail::all_t::value...>::value, + using ok = logic::all_t< + logic::all_t::value...>::value, _args_correct::value>; _add_impl(ok(), assignments...); // dispatch to prevent compile messages after the static_assert @@ -267,9 +285,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = column_list_data_t; @@ -282,21 +300,29 @@ namespace sqlpp { return t.values; } - }; - // Additional methods for the statement - template - struct _methods_t - { - static void _check_consistency() {} + using _consistency_check = typename std::conditional::value, + consistent_t, + assert_no_unknown_tables_in_column_list_t>::type; }; }; + struct assert_insert_values_t + { + using type = std::false_type; + + template + static void _() + { + static_assert(wrong_t::value, "insert values required, e.g. set(...) or default_values()"); + } + }; + // NO INSERT COLUMNS/VALUES YET struct no_insert_value_list_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits<>; + using _nodes = detail::type_vector<>; // Data using _data_t = no_data_t; @@ -308,9 +334,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = no_data_t; @@ -323,78 +349,90 @@ namespace sqlpp { return t.no_insert_values; } - }; - template - struct _methods_t - { using _database_t = typename Policies::_database_t; - template - using _new_statement_t = new_statement; - static void _check_consistency() - { - static_assert(wrong_t<_methods_t>::value, "insert values required, e.g. set(...) or default_values()"); - } + template + using _column_check = logic::all_t::value...>; + + template + using _assignment_check = logic::all_t::value...>; + + template + using _new_statement_t = new_statement_t; + + using _consistency_check = assert_insert_values_t; auto default_values() const - -> _new_statement_t + -> _new_statement_t { return { static_cast&>(*this), insert_default_values_data_t{} }; } template auto columns(Columns... columns) const - -> _new_statement_t> + -> _new_statement_t<_column_check, column_list_t> { + static_assert(logic::all_t::value...>::value, "at least one argument is not a column in columns()"); static_assert(sizeof...(Columns), "at least one column required in columns()"); - static_assert(not detail::has_duplicates::value, "at least one duplicate argument detected in columns()"); - static_assert(detail::all_t::value...>::value, "at least one argument is not a column in columns()"); - static_assert(detail::none_t::value...>::value, "at least one column argument has a must_not_insert tag in its definition"); - using _column_required_tables = detail::make_joined_set_t...>; - static_assert(_column_required_tables::size::value == 1, "columns() contains columns from several tables"); - using _table = typename detail::first_arg_t::_table; - using required_columns = typename _table::_required_insert_columns; - using set_columns = detail::make_type_set_t; - static_assert(detail::is_subset_of::value, "At least one required column is missing in columns()"); - - return { static_cast&>(*this), column_list_data_t{columns...} }; + return _columns_impl(_column_check{}, columns...); } template auto set(Assignments... assignments) const - -> _new_statement_t> + -> _new_statement_t<_assignment_check, insert_list_t> { + static_assert(_assignment_check::value, "at least one argument is not an assignment in set()"); static_assert(sizeof...(Assignments), "at least one assignment expression required in set()"); - static_assert(detail::all_t::value...>::value, "at least one argument is not an assignment in set()"); - using _table = typename lhs_t>::_table; - using required_columns = typename _table::_required_insert_columns; - using columns = detail::make_type_set_t...>; - static_assert(detail::is_subset_of::value, "At least one required column is missing in set()"); - return _set_impl(assignments...); + return _set_impl(_assignment_check{}, assignments...); } template auto dynamic_set(Assignments... assignments) const - -> _new_statement_t> + -> _new_statement_t<_assignment_check, insert_list_t<_database_t, Assignments...>> { + static_assert(_assignment_check::value, "at least one argument is not an assignment in set()"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_set must not be called in a static statement"); - static_assert(detail::all_t::value...>::value, "at least one argument is not an assignment in set()"); - return _set_impl<_database_t>(assignments...); + + return _set_impl<_database_t>(_assignment_check{}, assignments...); } private: + template + auto _columns_impl(const std::false_type&, Columns... columns) const + -> bad_statement; + + template + auto _columns_impl(const std::true_type&, Columns... columns) const + -> _new_statement_t> + { + static_assert(not detail::has_duplicates::value, "at least one duplicate argument detected in columns()"); + static_assert(logic::none_t::value...>::value, "at least one column argument has a must_not_insert tag in its definition"); + using _column_required_tables = detail::make_joined_set_t...>; + static_assert(_column_required_tables::size::value == 1, "columns() contains columns from several tables"); + + static_assert(detail::have_all_required_columns::value, "At least one required column is missing in columns()"); + + return { static_cast&>(*this), column_list_data_t{columns...} }; + } + template - auto _set_impl(Assignments... assignments) const - -> _new_statement_t> + auto _set_impl(const std::false_type&, Assignments... assignments) const + -> bad_statement; + + template + auto _set_impl(const std::true_type&, Assignments... assignments) const + -> _new_statement_t> { static_assert(not detail::has_duplicates...>::value, "at least one duplicate column detected in set()"); - static_assert(detail::none_t>::value...>::value, "at least one assignment is prohibited by its column definition in set()"); + static_assert(logic::none_t>::value...>::value, "at least one assignment is prohibited by its column definition in set()"); using _column_required_tables = detail::make_joined_set_t>...>; static_assert(sizeof...(Assignments) ? (_column_required_tables::size::value == 1) : true, "set() contains assignments for columns from several tables"); + static_assert(not std::is_same<_database_t, void>::value or detail::have_all_required_columns...>::value, "At least one required column is missing in set()"); + return { static_cast&>(*this), insert_list_data_t{assignments...} }; } }; @@ -404,6 +442,7 @@ namespace sqlpp template struct serializer_t { + using _serialize_check = consistent_t; using T = insert_default_values_data_t; static Context& _(const T& t, Context& context) @@ -416,6 +455,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = column_list_data_t; static Context& _(const T& t, Context& context) @@ -443,6 +483,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = insert_list_data_t; static Context& _(const T& t, Context& context) diff --git a/include/sqlpp11/integral.h b/include/sqlpp11/integral.h index e5123f45..e3a426df 100644 --- a/include/sqlpp11/integral.h +++ b/include/sqlpp11/integral.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/interpret.h b/include/sqlpp11/interpret.h index 4d1b2c20..ed12051f 100644 --- a/include/sqlpp11/interpret.h +++ b/include/sqlpp11/interpret.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/interpret_tuple.h b/include/sqlpp11/interpret_tuple.h index 44c61bd8..bc022f34 100644 --- a/include/sqlpp11/interpret_tuple.h +++ b/include/sqlpp11/interpret_tuple.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -34,20 +34,19 @@ namespace sqlpp { - template - static void interpret_tuple_element(const Element& element, const Separator& separator, Context& context, size_t index) + template + static void interpret_tuple_element(const Element& element, const Separator& separator, Context& context, const UseBraces&, size_t index) { if (index) context << separator; - if (requires_braces_t::value) - context << "("; - serialize(element, context); - if (requires_braces_t::value) - context << ")"; + if (UseBraces::value) + serialize_operand(element, context); + else + serialize(element, context); } - template - auto interpret_tuple_impl(const Tuple& t, const Separator& separator, Context& context, const detail::index_sequence&) + template + auto interpret_tuple_impl(const Tuple& t, const Separator& separator, Context& context, const UseBraces& useBraces, const detail::index_sequence&) -> Context& { // Note: A braced-init-list does guarantee the order of evaluation according to 12.6.1 [class.explicit.init] paragraph 2 and 8.5.4 [dcl.init.list] paragraph 4. @@ -57,7 +56,7 @@ namespace sqlpp using swallow = int[]; (void) swallow{ 0, //workaround against -Wpedantic GCC warning "zero-size array 'int [0]'" - (interpret_tuple_element(std::get(t), separator, context, Is), 0)...}; + (interpret_tuple_element(std::get(t), separator, context, useBraces, Is), 0)...}; return context; } @@ -65,7 +64,14 @@ namespace sqlpp auto interpret_tuple(const Tuple& t, const Separator& separator, Context& context) -> Context& { - return interpret_tuple_impl(t, separator, context, detail::make_index_sequence::value>{}); + return interpret_tuple_impl(t, separator, context, std::true_type{}, detail::make_index_sequence::value>{}); + } + + template + auto interpret_tuple_without_braces(const Tuple& t, const Separator& separator, Context& context) + -> Context& + { + return interpret_tuple_impl(t, separator, context, std::false_type{}, detail::make_index_sequence::value>{}); } } diff --git a/include/sqlpp11/interpretable.h b/include/sqlpp11/interpretable.h index d89075be..393ca855 100644 --- a/include/sqlpp11/interpretable.h +++ b/include/sqlpp11/interpretable.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -43,6 +43,7 @@ namespace sqlpp template interpretable_t(T t): + _requires_braces(requires_braces_t::value), _impl(std::make_shared<_impl_t>(t)) {} @@ -71,6 +72,8 @@ namespace sqlpp return _impl->interpret(context); } + bool _requires_braces; + private: struct _impl_base { @@ -114,11 +117,20 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = consistent_t; using T = interpretable_t; static Context& _(const T& t, Context& context) { - t.serialize(context); + if (t._requires_braces) + { + context << '('; + t.serialize(context); + context << ')'; + } + else + t.serialize(context); + return context; } }; diff --git a/include/sqlpp11/interpretable_list.h b/include/sqlpp11/interpretable_list.h index 59457bd5..8a5d1ea2 100644 --- a/include/sqlpp11/interpretable_list.h +++ b/include/sqlpp11/interpretable_list.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/interpreter.h b/include/sqlpp11/interpreter.h index 17ea9ffa..2560bd17 100644 --- a/include/sqlpp11/interpreter.h +++ b/include/sqlpp11/interpreter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/into.h b/include/sqlpp11/into.h index cff8fb35..4e05b9c4 100644 --- a/include/sqlpp11/into.h +++ b/include/sqlpp11/into.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -27,6 +27,7 @@ #ifndef SQLPP_INTO_H #define SQLPP_INTO_H +#include #include #include #include @@ -58,14 +59,11 @@ namespace sqlpp struct into_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits
; - - static_assert(is_table_t
::value, "argument has to be a table"); - static_assert(required_tables_of
::size::value == 0, "table depends on another table"); + using _nodes = detail::type_vector
; using _data_t = into_data_t; - struct _name_t {}; + struct _alias_t {}; // Member implementation with data and methods template @@ -74,9 +72,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = into_data_t; @@ -89,22 +87,28 @@ namespace sqlpp { return t.into; } - }; - // Additional methods for the statement - template - struct _methods_t - { - static void _check_consistency() {} + using _consistency_check = consistent_t; }; }; + struct assert_into_t + { + using type = std::false_type; + + template + static void _() + { + static_assert(wrong_t::value, "into() required"); + } + }; + // NO INTO YET struct no_into_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits<>; + using _nodes = detail::type_vector<>; // Data using _data_t = no_data_t; @@ -116,9 +120,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = no_data_t; @@ -131,25 +135,37 @@ namespace sqlpp { return t.no_into; } - }; - template - struct _methods_t - { using _database_t = typename Policies::_database_t; + template - using _new_statement_t = new_statement; + using _check = logic::all_t::value>; - static void _check_consistency() - { - static_assert(wrong_t<_methods_t>::value, "into() required"); - } + template + using _new_statement_t = new_statement_t; - template - auto into(Args... args) const - -> _new_statement_t> + using _consistency_check = assert_into_t; + + template + auto into(Table table) const + -> _new_statement_t<_check
, into_t> { - return { static_cast&>(*this), into_data_t{args...} }; + static_assert(_check
::value, "argument is not a table in into()"); + return _into_impl(_check
{}, table); + } + + private: + template + auto _into_impl(const std::false_type&, Table table) const + -> bad_statement; + + template + auto _into_impl(const std::true_type&, Table table) const + -> _new_statement_t> + { + static_assert(required_tables_of>::size::value == 0, "argument depends on another table in into()"); + + return { static_cast&>(*this), into_data_t{table} }; } }; }; @@ -158,6 +174,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = into_data_t; static Context& _(const T& t, Context& context) @@ -168,6 +185,11 @@ namespace sqlpp } }; + template + auto into(T&& t) -> decltype(statement_t().into(std::forward(t))) + { + return statement_t().into(std::forward(t)); + } } #endif diff --git a/include/sqlpp11/is_not_null.h b/include/sqlpp11/is_not_null.h new file mode 100644 index 00000000..78e49123 --- /dev/null +++ b/include/sqlpp11/is_not_null.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2013-2015, Roland Bock + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SQLPP_IS_NOT_NULL_H +#define SQLPP_IS_NOT_NULL_H + +#include +#include +#include +#include + +namespace sqlpp +{ + template + struct is_not_null_t: + public expression_operators, boolean>, + public alias_operators> + { + using _traits = make_traits; + using _nodes = detail::type_vector; + + struct _alias_t + { + static constexpr const char _literal[] = "is_not_null_"; + using _name_t = sqlpp::make_char_sequence; + template + struct _member_t + { + T is_not_null; + }; + }; + + is_not_null_t(Operand operand): + _operand(operand) + {} + + is_not_null_t(const is_not_null_t&) = default; + is_not_null_t(is_not_null_t&&) = default; + is_not_null_t& operator=(const is_not_null_t&) = default; + is_not_null_t& operator=(is_not_null_t&&) = default; + ~is_not_null_t() = default; + + Operand _operand; + }; + + template + struct serializer_t> + { + using _serialize_check = serialize_check_of; + using T = is_not_null_t; + + static Context& _(const T& t, Context& context) + { + serialize_operand(t._operand, context); + context << " IS NOT NULL"; + return context; + } + }; + +} + +#endif diff --git a/include/sqlpp11/is_null.h b/include/sqlpp11/is_null.h index ecc06bd5..0a798067 100644 --- a/include/sqlpp11/is_null.h +++ b/include/sqlpp11/is_null.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -29,27 +29,27 @@ #include #include +#include #include namespace sqlpp { - template + template struct is_null_t: - public expression_operators, boolean>, - public alias_operators> + public expression_operators, boolean>, + public alias_operators> { using _traits = make_traits; - using _recursive_traits = make_recursive_traits; + using _nodes = detail::type_vector; - static constexpr bool _inverted = not NotInverted; - - struct _name_t + struct _alias_t { - static constexpr const char* _get_name() { return _inverted ? "IS NOT NULL" : "IS NULL"; } + static constexpr const char _literal[] = "is_nnull_"; + using _name_t = sqlpp::make_char_sequence; template struct _member_t { - T in; + T is_null; }; }; @@ -66,15 +66,16 @@ namespace sqlpp Operand _operand; }; - template - struct serializer_t> + template + struct serializer_t> { - using T = is_null_t; + using _serialize_check = serialize_check_of; + using T = is_null_t; static Context& _(const T& t, Context& context) { - serialize(t._operand, context); - context << (t._inverted ? " IS NOT NULL" : " IS NULL"); + serialize_operand(t._operand, context); + context << " IS NULL"; return context; } }; diff --git a/include/sqlpp11/is_null_fwd.h b/include/sqlpp11/is_null_fwd.h index 8d53cc01..155f3922 100644 --- a/include/sqlpp11/is_null_fwd.h +++ b/include/sqlpp11/is_null_fwd.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -29,8 +29,10 @@ namespace sqlpp { - template + template struct is_null_t; + template + struct is_not_null_t; } #endif diff --git a/include/sqlpp11/join.h b/include/sqlpp11/join.h index e7b444a7..8e2578d6 100644 --- a/include/sqlpp11/join.h +++ b/include/sqlpp11/join.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -66,16 +66,8 @@ namespace sqlpp struct join_t { using _traits = make_traits; - struct _recursive_traits - { - using _required_tables = detail::make_joined_set_t, required_tables_of>; - using _provided_tables = detail::make_joined_set_t, provided_tables_of>; - using _provided_outer_tables = typename JoinType::template _provided_outer_tables; - using _extra_tables = detail::make_joined_set_t, extra_tables_of>; - using _parameters = detail::make_parameter_tuple_t, parameters_of>; - using _tags = detail::type_set<>; - }; - + using _nodes = detail::type_vector; + using _can_be_null = std::false_type; static_assert(is_table_t::value, "lhs argument for join() has to be a table or join"); static_assert(is_table_t::value, "rhs argument for join() has to be a table"); @@ -84,7 +76,7 @@ namespace sqlpp static_assert(detail::is_disjunct_from, provided_tables_of>::value, "joined tables must not be identical"); - static_assert(_recursive_traits::_required_tables::size::value == 0, "joined tables must not depend on other tables"); + static_assert(required_tables_of::size::value == 0, "joined tables must not depend on other tables"); template using set_on_t = join_t; @@ -94,7 +86,7 @@ namespace sqlpp -> set_on_t> { static_assert(is_noop::value, "cannot call on() twice for a single join()"); - static_assert(detail::all_t::value...>::value, "at least one argument is not an expression in on()"); + static_assert(logic::all_t::value...>::value, "at least one argument is not an expression in on()"); return { _lhs, _rhs, @@ -145,6 +137,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = join_t; static Context& _(const T& t, Context& context) diff --git a/include/sqlpp11/like.h b/include/sqlpp11/like.h index 2a73baa3..02adeba0 100644 --- a/include/sqlpp11/like.h +++ b/include/sqlpp11/like.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -29,6 +29,7 @@ #include #include +#include #include namespace sqlpp @@ -39,11 +40,12 @@ namespace sqlpp public alias_operators> { using _traits = make_traits; - using _recursive_traits = make_recursive_traits; + using _nodes = detail::type_vector; - struct _name_t + struct _alias_t { - static constexpr const char* _get_name() { return "LIKE"; } + static constexpr const char _literal[] = "like_"; + using _name_t = sqlpp::make_char_sequence; template struct _member_t { @@ -71,11 +73,12 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = like_t; static Context& _(const T& t, Context& context) { - serialize(t._operand, context); + serialize_operand(t._operand, context); context << " LIKE("; serialize(t._pattern, context); context << ")"; diff --git a/include/sqlpp11/limit.h b/include/sqlpp11/limit.h index 40b756ce..c740c8dc 100644 --- a/include/sqlpp11/limit.h +++ b/include/sqlpp11/limit.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -55,9 +55,7 @@ namespace sqlpp struct limit_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits; - - static_assert(is_integral_t::value, "limit requires an integral value or integral parameter"); + using _nodes = detail::type_vector; // Data using _data_t = limit_data_t; @@ -69,9 +67,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = limit_data_t; @@ -84,12 +82,8 @@ namespace sqlpp { return t.limit; } - }; - template - struct _methods_t - { - static void _check_consistency() {} + using _consistency_check = consistent_t; }; }; @@ -124,7 +118,7 @@ namespace sqlpp struct dynamic_limit_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits<>; + using _nodes = detail::type_vector<>; // Data using _data_t = dynamic_limit_data_t; @@ -138,6 +132,7 @@ namespace sqlpp { // FIXME: Make sure that Limit does not require external tables? Need to read up on SQL using arg_t = wrap_operand_t; + static_assert(is_integral_t::value, "limit requires an integral value or integral parameter"); _data._value = arg_t{value}; _data._initialized = true; } @@ -145,9 +140,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = dynamic_limit_data_t; @@ -160,20 +155,15 @@ namespace sqlpp { return t.limit; } - }; - // Additional methods for the statement - template - struct _methods_t - { - static void _check_consistency() {} + using _consistency_check = consistent_t; }; }; struct no_limit_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits<>; + using _nodes = detail::type_vector<>; // Data using _data_t = no_data_t; @@ -185,9 +175,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = no_data_t; @@ -200,30 +190,43 @@ namespace sqlpp { return t.no_limit; } - }; - template - struct _methods_t - { using _database_t = typename Policies::_database_t; - template - using _new_statement_t = new_statement; - static void _check_consistency() {} + template + using _check = is_integral_t>; + + template + using _new_statement_t = new_statement_t; + + using _consistency_check = consistent_t; template auto limit(Arg arg) const - -> _new_statement_t>> + -> _new_statement_t<_check, limit_t>> { - return { static_cast&>(*this), limit_data_t>{{arg}} }; + static_assert(_check::value, "limit requires an integral value or integral parameter"); + return _limit_impl(_check{}, wrap_operand_t{arg}); } auto dynamic_limit() const - -> _new_statement_t> + -> _new_statement_t> { - static_assert(not std::is_same<_database_t, void>::value, "dynamic_limit must not be called in a static statement"); return { static_cast&>(*this), dynamic_limit_data_t<_database_t>{} }; } + + private: + template + auto _limit_impl(const std::false_type&, Arg arg) const + -> bad_statement; + + template + auto _limit_impl(const std::true_type&, Arg arg) const + -> _new_statement_t> + { + return { static_cast&>(*this), limit_data_t{arg} }; + } + }; }; @@ -231,6 +234,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = consistent_t; using T = dynamic_limit_data_t; static Context& _(const T& t, Context& context) @@ -247,12 +251,13 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = limit_data_t; static Context& _(const T& t, Context& context) { context << " LIMIT "; - serialize(t._value, context); + serialize_operand(t._value, context); return context; } }; diff --git a/include/sqlpp11/detail/logic.h b/include/sqlpp11/logic.h similarity index 97% rename from include/sqlpp11/detail/logic.h rename to include/sqlpp11/logic.h index 11366ae9..1db03db4 100644 --- a/include/sqlpp11/detail/logic.h +++ b/include/sqlpp11/logic.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -32,7 +32,7 @@ namespace sqlpp { - namespace detail + namespace logic { template struct logic_helper; diff --git a/include/sqlpp11/max.h b/include/sqlpp11/max.h index 440d1f31..f2011988 100644 --- a/include/sqlpp11/max.h +++ b/include/sqlpp11/max.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -28,6 +28,7 @@ #define SQLPP_MAX_H #include +#include namespace sqlpp { @@ -37,11 +38,12 @@ namespace sqlpp public alias_operators> { using _traits = make_traits, tag::is_expression, tag::is_selectable>; - using _recursive_traits = make_recursive_traits; + using _nodes = detail::type_vector; - struct _name_t + struct _alias_t { - static constexpr const char* _get_name() { return "MAX"; } + static constexpr const char _literal[] = "max_"; + using _name_t = sqlpp::make_char_sequence; template struct _member_t { @@ -67,6 +69,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = max_t; static Context& _(const T& t, Context& context) @@ -81,6 +84,7 @@ namespace sqlpp template auto max(T t) -> max_t> { + static_assert(not contains_aggregate_function_t>::value, "max() cannot be used on an aggregate function"); static_assert(is_expression_t>::value, "max() requires an expression as argument"); return { t }; } diff --git a/include/sqlpp11/min.h b/include/sqlpp11/min.h index e5387d37..7f885c07 100644 --- a/include/sqlpp11/min.h +++ b/include/sqlpp11/min.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -28,6 +28,7 @@ #define SQLPP_MIN_H #include +#include namespace sqlpp { @@ -37,11 +38,12 @@ namespace sqlpp public alias_operators> { using _traits = make_traits, tag::is_expression, tag::is_selectable>; - using _recursive_traits = make_recursive_traits; + using _nodes = detail::type_vector; - struct _name_t + struct _alias_t { - static constexpr const char* _get_name() { return "MIN"; } + static constexpr const char _literal[] = "min_"; + using _name_t = sqlpp::make_char_sequence; template struct _member_t { @@ -67,6 +69,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = min_t; static Context& _(const T& t, Context& context) @@ -81,6 +84,7 @@ namespace sqlpp template auto min(T t) -> min_t> { + static_assert(not contains_aggregate_function_t>::value, "min() cannot be used on an aggregate function"); static_assert(is_expression_t>::value, "min() requires an expression as argument"); return { t }; } diff --git a/include/sqlpp11/multi_column.h b/include/sqlpp11/multi_column.h index 44288b83..8147d3c2 100644 --- a/include/sqlpp11/multi_column.h +++ b/include/sqlpp11/multi_column.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -28,7 +28,7 @@ #define SQLPP_MULTI_COLUMN_H #include -#include +#include #include #include @@ -42,9 +42,9 @@ namespace sqlpp struct multi_column_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits; + using _nodes = detail::type_vector; - static_assert(detail::all_t::value...>::value, "multi_column parameters need to be named expressions"); + static_assert(logic::all_t::value...>::value, "multi_column parameters need to be named expressions"); multi_column_t(std::tuple columns): _columns(columns) @@ -73,11 +73,11 @@ namespace sqlpp struct multi_column_alias_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits; + using _nodes = detail::type_vector; - static_assert(detail::all_t::value...>::value, "multi_column parameters need to be named expressions"); + static_assert(logic::all_t::value...>::value, "multi_column parameters need to be named expressions"); - using _name_t = typename AliasProvider::_name_t; + using _alias_t = typename AliasProvider::_alias_t; multi_column_alias_t(multi_column_t multi_column): _columns(multi_column._columns) @@ -103,6 +103,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = multi_column_t; static void _(const T& t, Context& context) @@ -114,6 +115,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = multi_column_alias_t; static Context& _(const T& t, Context& context) diff --git a/include/sqlpp11/named_interpretable.h b/include/sqlpp11/named_interpretable.h index 5ba0f044..079b19bf 100644 --- a/include/sqlpp11/named_interpretable.h +++ b/include/sqlpp11/named_interpretable.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -30,6 +30,7 @@ #include #include #include +#include namespace sqlpp { @@ -41,6 +42,7 @@ namespace sqlpp template named_interpretable_t(T t): + _requires_braces(requires_braces_t::value), _impl(std::make_shared<_impl_t>(t)) {} @@ -74,6 +76,8 @@ namespace sqlpp return _impl->_get_name(); } + bool _requires_braces; + private: struct _impl_base { @@ -111,7 +115,7 @@ namespace sqlpp std::string _get_name() const { - return T::_name_t::_get_name(); + return name_of::char_ptr(); } T _t; @@ -123,11 +127,20 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = consistent_t; using T = named_interpretable_t; static Context& _(const T& t, Context& context) { - t.serialize(context); + if (t._requires_braces) + { + context << '('; + t.serialize(context); + context << ')'; + } + else + t.serialize(context); + return context; } }; diff --git a/include/sqlpp11/no_data.h b/include/sqlpp11/no_data.h index e94a9289..f90f4377 100644 --- a/include/sqlpp11/no_data.h +++ b/include/sqlpp11/no_data.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -37,6 +37,7 @@ namespace sqlpp template struct serializer_t { + using _serialize_check = consistent_t; using T = no_data_t; static Context& _(const T& t, Context& context) diff --git a/include/sqlpp11/no_value.h b/include/sqlpp11/no_value.h index be1877d1..bf31ad5a 100644 --- a/include/sqlpp11/no_value.h +++ b/include/sqlpp11/no_value.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/noop.h b/include/sqlpp11/noop.h index 5d6afae2..0a023b80 100644 --- a/include/sqlpp11/noop.h +++ b/include/sqlpp11/noop.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -30,24 +30,61 @@ #include #include #include +#include namespace sqlpp { struct noop { using _traits = make_traits; - using _recursive_traits = make_recursive_traits<>; + using _nodes = detail::type_vector<>; - struct _name_t {}; + struct _alias_t {}; - template + template struct _result_methods_t - {}; + { + using _statement_t = Statement; + + const _statement_t& _get_statement() const + { + return static_cast(*this); + } + + // Execute + template + auto _run(Db& db, const Composite& composite) const -> void + { + return db.execute(composite); + } + + template + auto _run(Db& db) const -> void + { + return db.execute(_get_statement()); + } + + // Prepare + template + auto _prepare(Db& db, const Composite& composite) const + -> prepared_execute_t + { + return {{}, db.prepare_execute(composite)}; + } + + template + auto _prepare(Db& db) const + -> prepared_execute_t + { + return {{}, db.prepare_execute(_get_statement())}; + } + }; }; template struct serializer_t { + using _serialize_check = consistent_t; using T = noop; static Context& _(const T& t, Context& context) diff --git a/include/sqlpp11/noop_fwd.h b/include/sqlpp11/noop_fwd.h index 0c87c75e..a07caba2 100644 --- a/include/sqlpp11/noop_fwd.h +++ b/include/sqlpp11/noop_fwd.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/not_in.h b/include/sqlpp11/not_in.h new file mode 100644 index 00000000..cddfc119 --- /dev/null +++ b/include/sqlpp11/not_in.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2013-2015, Roland Bock + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SQLPP_NOT_IN_H +#define SQLPP_NOT_IN_H + +#include +#include +#include +#include +#include + +namespace sqlpp +{ + template + struct not_in_t: + public expression_operators, boolean>, + public alias_operators> + { + using _traits = make_traits; + using _nodes = detail::type_vector; + + static_assert(sizeof...(Args) > 0, "not_in() requires at least one argument"); + + struct _alias_t + { + static constexpr const char _literal[] = "not_in_"; + using _name_t = sqlpp::make_char_sequence; + template + struct _member_t + { + T not_in; + }; + }; + + not_in_t(Operand operand, Args... args): + _operand(operand), + _args(args...) + {} + + not_in_t(const not_in_t&) = default; + not_in_t(not_in_t&&) = default; + not_in_t& operator=(const not_in_t&) = default; + not_in_t& operator=(not_in_t&&) = default; + ~not_in_t() = default; + + Operand _operand; + std::tuple _args; + }; + + template + struct serializer_t> + { + using _serialize_check = serialize_check_of; + using T = not_in_t; + + static Context& _(const T& t, Context& context) + { + serialize_operand(t._operand, context); + context << " NOT IN("; + if (sizeof...(Args) == 1) + serialize(std::get<0>(t._args), context); + else + interpret_tuple(t._args, ',', context); + context << ')'; + return context; + } + }; + +} + +#endif diff --git a/include/sqlpp11/null.h b/include/sqlpp11/null.h index 93e0706b..9b01b69e 100644 --- a/include/sqlpp11/null.h +++ b/include/sqlpp11/null.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -34,12 +34,13 @@ namespace sqlpp struct null_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits<>; + using _nodes = detail::type_vector<>; }; template struct serializer_t { + using _serialize_check = consistent_t; using Operand = null_t; static Context& _(const Operand& t, Context& context) diff --git a/include/sqlpp11/offset.h b/include/sqlpp11/offset.h index 5d0b4b3b..bb9b1406 100644 --- a/include/sqlpp11/offset.h +++ b/include/sqlpp11/offset.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -55,7 +55,7 @@ namespace sqlpp struct offset_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits; + using _nodes = detail::type_vector; static_assert(is_integral_t::value, "offset requires an integral value or integral parameter"); @@ -69,9 +69,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = offset_data_t; @@ -84,12 +84,8 @@ namespace sqlpp { return t.offset; } - }; - template - struct _methods_t - { - static void _check_consistency() {} + using _consistency_check = consistent_t; }; }; @@ -124,7 +120,7 @@ namespace sqlpp struct dynamic_offset_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits<>; + using _nodes = detail::type_vector<>; // Data using _data_t = dynamic_offset_data_t; @@ -138,6 +134,7 @@ namespace sqlpp { // FIXME: Make sure that Offset does not require external tables? Need to read up on SQL using arg_t = wrap_operand_t; + static_assert(is_integral_t::value, "offset requires an integral value or integral parameter"); _data._value = arg_t{value}; _data._initialized = true; } @@ -145,9 +142,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = dynamic_offset_data_t; @@ -160,12 +157,8 @@ namespace sqlpp { return t.offset; } - }; - template - struct _methods_t - { - static void _check_consistency() {} + using _consistency_check = consistent_t; template void set_offset(Offset value) @@ -184,7 +177,7 @@ namespace sqlpp struct no_offset_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits<>; + using _nodes = detail::type_vector<>; // Data using _data_t = no_data_t; @@ -196,9 +189,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = no_data_t; @@ -211,30 +204,44 @@ namespace sqlpp { return t.no_offset; } - }; - template - struct _methods_t - { using _database_t = typename Policies::_database_t; - template - using _new_statement_t = new_statement; - static void _check_consistency() {} + template + using _check = is_integral_t>; + + template + using _new_statement_t = new_statement_t; + + using _consistency_check = consistent_t; template auto offset(Arg arg) const - -> _new_statement_t>> + -> _new_statement_t<_check, offset_t>> { - return { static_cast&>(*this), offset_data_t>{{arg}} }; + static_assert(_check::value, "offset requires an integral value or integral parameter"); + return _offset_impl(_check{}, wrap_operand_t{arg}); } auto dynamic_offset() const - -> _new_statement_t> + -> _new_statement_t> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_offset must not be called in a static statement"); return { static_cast&>(*this), dynamic_offset_data_t<_database_t>{} }; } + + private: + template + auto _offset_impl(const std::false_type&, Arg arg) const + -> bad_statement; + + template + auto _offset_impl(const std::true_type&, Arg arg) const + -> _new_statement_t> + { + return { static_cast&>(*this), offset_data_t{arg} }; + } + }; }; @@ -242,12 +249,13 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = offset_data_t; static Context& _(const T& t, Context& context) { context << " OFFSET "; - serialize(t._value, context); + serialize_operand(t._value, context); return context; } }; @@ -255,6 +263,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = consistent_t; using T = dynamic_offset_data_t; static Context& _(const T& t, Context& context) diff --git a/include/sqlpp11/on.h b/include/sqlpp11/on.h index 2a88eafb..81cff460 100644 --- a/include/sqlpp11/on.h +++ b/include/sqlpp11/on.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -30,43 +30,61 @@ #include #include #include -#include +#include namespace sqlpp { - template + template struct on_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits; + using _nodes = detail::type_vector; using _is_dynamic = is_database; - static_assert(_is_dynamic::value or sizeof...(Expr), "at least one expression argument required in on()"); + static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in on()"); - template - void add(E expr) + template + void add(Expr expr) { - static_assert(is_expression_t::value, "invalid expression argument in add_on()"); - _dynamic_expressions.emplace_back(expr); + static_assert(_is_dynamic::value, "on::add() must not be called for static on()"); + static_assert(is_expression_t::value, "invalid expression argument in on::add()"); + using _serialize_check = sqlpp::serialize_check_t; + _serialize_check::_(); + + using ok = logic::all_t<_is_dynamic::value, is_expression_t::value, _serialize_check::type::value>; + + _add_impl(expr, ok()); // dispatch to prevent compile messages after the static_assert } - std::tuple _expressions; + private: + template + void _add_impl(Expr expr, const std::true_type&) + { + return _dynamic_expressions.emplace_back(expr); + } + + template + void _add_impl(Expr expr, const std::false_type&); + + public: + std::tuple _expressions; interpretable_list_t _dynamic_expressions; }; - template - struct serializer_t> + template + struct serializer_t> { - using T = on_t; + using _serialize_check = serialize_check_of; + using T = on_t; static Context& _(const T& t, Context& context) { - if (sizeof...(Expr) == 0 and t._dynamic_expressions.empty()) + if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty()) return context; context << " ON "; interpret_tuple(t._expressions, " AND ", context); - if (sizeof...(Expr) and not t._dynamic_expressions.empty()) + if (sizeof...(Expressions) and not t._dynamic_expressions.empty()) context << " AND "; interpret_list(t._dynamic_expressions, " AND ", context); return context; diff --git a/include/sqlpp11/order_by.h b/include/sqlpp11/order_by.h index 8d761989..bc85d708 100644 --- a/include/sqlpp11/order_by.h +++ b/include/sqlpp11/order_by.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include namespace sqlpp @@ -55,21 +55,26 @@ namespace sqlpp interpretable_list_t _dynamic_expressions; }; + struct assert_no_unknown_tables_in_order_by_t + { + using type = std::false_type; + + template + static void _() + { + static_assert(wrong_t::value, "at least one order-by expression requires a table which is otherwise not known in the statement"); + } + }; + // ORDER BY template struct order_by_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits; + using _nodes = detail::type_vector; using _is_dynamic = is_database; - static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression (e.g. a column) required in order_by()"); - - static_assert(not detail::has_duplicates::value, "at least one duplicate argument detected in order_by()"); - - static_assert(detail::all_t::value...>::value, "at least one argument is not an expression in order_by()"); - // Data using _data_t = order_by_data_t; @@ -87,10 +92,12 @@ namespace sqlpp void add(Expression expression) { static_assert(_is_dynamic::value, "add() must not be called for static order_by"); - static_assert(is_expression_t::value, "invalid expression argument in order_by::add()"); + static_assert(is_sort_order_t::value, "invalid expression argument in order_by::add()"); static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables::value, "expression uses tables unknown to this statement in order_by::add()"); + using _serialize_check = sqlpp::serialize_check_t; + _serialize_check::_(); - using ok = detail::all_t<_is_dynamic::value, is_expression_t::value>; + using ok = logic::all_t<_is_dynamic::value, is_sort_order_t::value, _serialize_check::type::value>; _add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert } @@ -108,9 +115,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = order_by_data_t; @@ -123,12 +130,10 @@ namespace sqlpp { return t.order_by; } - }; - template - struct _methods_t - { - static void _check_consistency() {} + using _consistency_check = typename std::conditional::value, + consistent_t, + assert_no_unknown_tables_in_order_by_t>::type; }; }; @@ -136,7 +141,7 @@ namespace sqlpp struct no_order_by_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits<>; + using _nodes = detail::type_vector<>; // Data using _data_t = no_data_t; @@ -148,9 +153,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = no_data_t; @@ -163,31 +168,50 @@ namespace sqlpp { return t.no_order_by; } - }; - template - struct _methods_t - { using _database_t = typename Policies::_database_t; - template - using _new_statement_t = new_statement; - static void _check_consistency() {} + template + using _check = logic::all_t::value...>; - template - auto order_by(Args... args) const - -> _new_statement_t> + template + using _new_statement_t = new_statement_t; + + using _consistency_check = consistent_t; + + template + auto order_by(Expressions... expressions) const + -> _new_statement_t<_check, order_by_t> { - return { static_cast&>(*this), order_by_data_t{args...} }; + static_assert(sizeof...(Expressions), "at least one expression (e.g. a column) required in order_by()"); + static_assert(_check::value, "at least one argument is not a sort order in order_by()"); + + return _order_by_impl(_check{}, expressions...); } - template - auto dynamic_order_by(Args... args) const - -> _new_statement_t> + template + auto dynamic_order_by(Expressions... expressions) const + -> _new_statement_t<_check, order_by_t<_database_t, Expressions...>> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_order_by must not be called in a static statement"); - return { static_cast&>(*this), order_by_data_t<_database_t, Args...>{args...} }; + static_assert(_check::value, "at least one argument is not a sort order in order_by()"); + + return _order_by_impl<_database_t>(_check{}, expressions...); } + + private: + template + auto _order_by_impl(const std::false_type&, Expressions... expressions) const + -> bad_statement; + + template + auto _order_by_impl(const std::true_type&, Expressions... expressions) const + -> _new_statement_t> + { + static_assert(not detail::has_duplicates::value, "at least one duplicate argument detected in order_by()"); + + return { static_cast&>(*this), order_by_data_t{expressions...} }; + } }; }; @@ -195,6 +219,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = order_by_data_t; static Context& _(const T& t, Context& context) diff --git a/include/sqlpp11/parameter.h b/include/sqlpp11/parameter.h index 687096b3..13447233 100644 --- a/include/sqlpp11/parameter.h +++ b/include/sqlpp11/parameter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -38,15 +38,10 @@ namespace sqlpp public expression_operators, ValueType> { using _traits = make_traits; - struct _recursive_traits - { - using _parameters = std::tuple; - using _provided_tables = detail::type_set<>; - using _provided_outer_tables = detail::type_set<>; - using _required_tables = detail::type_set<>; - using _extra_tables = detail::type_set<>; - using _tags = detail::type_set; - }; + + using _nodes = detail::type_vector<>; + using _parameters = detail::type_vector; + using _can_be_null = std::true_type; using _instance_t = member_t>; @@ -63,6 +58,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = consistent_t; using T = parameter_t; static Context& _(const T& t, Context& context) diff --git a/include/sqlpp11/parameter_list.h b/include/sqlpp11/parameter_list.h index c4aeba51..eaace254 100644 --- a/include/sqlpp11/parameter_list.h +++ b/include/sqlpp11/parameter_list.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -37,11 +37,11 @@ namespace sqlpp template struct parameter_list_t { - static_assert(wrong_t::value, "Template parameter for parameter_list_t has to be a tuple"); + static_assert(wrong_t::value, "Template parameter for parameter_list_t has to be a type_vector"); }; template - struct parameter_list_t>: public Parameter::_instance_t... + struct parameter_list_t>: public Parameter::_instance_t... { using _member_tuple_t = std::tuple; using size = std::integral_constant; diff --git a/include/sqlpp11/policy_update.h b/include/sqlpp11/policy_update.h index 1afd9c24..3a8f3a56 100644 --- a/include/sqlpp11/policy_update.h +++ b/include/sqlpp11/policy_update.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -28,6 +28,7 @@ #define SQLPP_POLICY_UPDATE_H #include +#include namespace sqlpp { @@ -53,6 +54,21 @@ namespace sqlpp template using new_statement = typename Policies::template _new_statement_t; + template + struct new_statement_impl + { + using type = typename Policies::template _new_statement_t; + }; + + template + struct new_statement_impl + { + using type = bad_statement; + }; + + template + using new_statement_t = typename new_statement_impl::type; + } #endif diff --git a/include/sqlpp11/ppgen.h b/include/sqlpp11/ppgen.h new file mode 100644 index 00000000..50141bc1 --- /dev/null +++ b/include/sqlpp11/ppgen.h @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _sqlpp__ppgen_h +#define _sqlpp__ppgen_h + +#include + +// enable the Clang support +#if defined(__clang__) && !BOOST_PP_VARIADICS +# undef BOOST_PP_VARIADICS +# define BOOST_PP_VARIADICS 1 +#endif // defined(__clang__) + +// tools +#include +#include + +// table props +#include +#include + +// col props +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// boost.preprocessor +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/***************************************************************************/ +// tools + +#define SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table) \ + BOOST_PP_TUPLE_ELEM(0, BOOST_PP_EXPAND table) + +#define SQLPP_DECLARE_TABLE_GET_TABLE_PROPS(table) \ + SQLPP_BOOST_PP_TUPLE_POP_FRONT(BOOST_PP_EXPAND table) + +#define SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(col) \ + BOOST_PP_TUPLE_ELEM(0, col) + +#define SQLPP_DECLARE_TABLE_ENUM_COLUMNS(unused, table, elem) \ + ,table::SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(elem) + +/***************************************************************************/ +// columns + +#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_AUX(unused, size, idx, elem) \ + BOOST_PP_CAT( \ + SQLPP_DECLARE_COLUMN_GEN_TRAITS_ \ + ,BOOST_PP_CAT(SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_, elem) \ + )(elem) \ + BOOST_PP_COMMA_IF(BOOST_PP_LESS(BOOST_PP_ADD(idx, 1), size)) + +#define SQLPP_DECLARE_COLUMN_GEN_TRAITS(props) \ + BOOST_PP_SEQ_FOR_EACH_I( \ + SQLPP_DECLARE_COLUMN_GEN_TRAITS_AUX \ + ,BOOST_PP_TUPLE_SIZE(props) \ + ,BOOST_PP_TUPLE_TO_SEQ(props) \ + ) + +#define SQLPP_DECLARE_COLUMN(unused, data, elem) \ + struct SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(elem) { \ + struct _alias_t { \ + static constexpr const char _literal[] = \ + BOOST_PP_STRINGIZE(SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(elem)); \ + using _name_t = sqlpp::make_char_sequence; \ + \ + template \ + struct _member_t { \ + T SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(elem); \ + \ + T& operator()() { return SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(elem); } \ + const T& operator()() const { return SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(elem); } \ + }; /* struct _member_t */ \ + }; /* struct _alias_t */ \ + \ + using _traits = sqlpp::make_traits< \ + SQLPP_DECLARE_COLUMN_GEN_TRAITS(SQLPP_BOOST_PP_TUPLE_POP_FRONT(elem)) \ + >; \ + \ + }; /* struct SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(elem) */ + +/***************************************************************************/ +// table props + +#define SQLPP_DECLARE_TABLE_GEN_PROPS_AUX(unused1, unused2, elem) \ + BOOST_PP_CAT( \ + SQLPP_DECLARE_TABLE_GEN_ \ + ,BOOST_PP_CAT(SQLPP_DECLARE_TABLE_GET_PROC_LAZY_, elem) \ + )(elem) + +#define SQLPP_DECLARE_TABLE_GEN_PROPS(table) \ + BOOST_PP_SEQ_FOR_EACH( \ + SQLPP_DECLARE_TABLE_GEN_PROPS_AUX \ + ,~ \ + ,BOOST_PP_TUPLE_TO_SEQ(SQLPP_BOOST_PP_TUPLE_POP_FRONT(table)) \ + ) + +/***************************************************************************/ +// main + +#define SQLPP_DECLARE_TABLE_IMPL(table, cols) \ + namespace SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table) { \ + namespace BOOST_PP_CAT(SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table), _) { \ + BOOST_PP_SEQ_FOR_EACH( \ + SQLPP_DECLARE_COLUMN \ + ,~ \ + ,cols \ + ) \ + } /* namespace BOOST_PP_CAT(SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table), _) */ \ + \ + struct SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table) \ + : sqlpp::table_t< \ + SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table) \ + BOOST_PP_SEQ_FOR_EACH( \ + SQLPP_DECLARE_TABLE_ENUM_COLUMNS \ + ,BOOST_PP_CAT(SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table), _) \ + ,cols \ + ) \ + > \ + { \ + BOOST_PP_IF( \ + BOOST_PP_LESS(BOOST_PP_TUPLE_SIZE(table), 2) \ + ,BOOST_PP_TUPLE_EAT() \ + ,SQLPP_DECLARE_TABLE_GEN_PROPS \ + )(BOOST_PP_EXPAND table) \ + \ + struct _alias_t { \ + static constexpr const char _literal[] = \ + BOOST_PP_STRINGIZE(SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table)); \ + using _name_t = sqlpp::make_char_sequence; \ + \ + template \ + struct _member_t { \ + T SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table); \ + \ + T& operator()() { return SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table); } \ + const T& operator()() const { return SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table); } \ + \ + }; /* struct _member_t */ \ + \ + }; /* struct _alias_t */ \ + \ + }; /* struct SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table) */ \ + \ + } + +/***************************************************************************/ + +#define SQLPP_DECLARE_TABLE(table, cols) \ + SQLPP_DECLARE_TABLE_IMPL( \ + BOOST_PP_CAT(SQLPP_WRAP_SEQUENCE_X table, 0) \ + ,BOOST_PP_CAT(SQLPP_WRAP_SEQUENCE_X cols, 0) \ + ) + +/***************************************************************************/ + +#endif // _sqlpp__ppgen_h diff --git a/include/sqlpp11/ppgen/colops/auto_increment.h b/include/sqlpp11/ppgen/colops/auto_increment.h new file mode 100644 index 00000000..7f88a5ec --- /dev/null +++ b/include/sqlpp11/ppgen/colops/auto_increment.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _sqlpp__ppgen__colops__auto_increment_h +#define _sqlpp__ppgen__colops__auto_increment_h + +#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_SQLPP_AUTO_INCREMENT \ + PROC_SQLPP_AUTO_INCREMENT +#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_SQLPP_AUTO_INCREMENT(...) \ + sqlpp::tag::must_not_update + +#endif // _sqlpp__ppgen__colops__auto_increment_h diff --git a/include/sqlpp11/ppgen/colops/blob.h b/include/sqlpp11/ppgen/colops/blob.h new file mode 100644 index 00000000..26c124e6 --- /dev/null +++ b/include/sqlpp11/ppgen/colops/blob.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _sqlpp__ppgen__colops__blob_h +#define _sqlpp__ppgen__colops__blob_h + +#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_tinyblob \ + PROC_tinyblob +#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_tinyblob(...) \ + sqlpp::blob + +#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_blob \ + PROC_blob +#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_blob(...) \ + sqlpp::blob + +#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_mediumblob \ + PROC_mediumblob +#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_mediumblob(...) \ + sqlpp::blob + +#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_longblob \ + PROC_longblob +#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_longblob(...) \ + sqlpp::blob + +#endif // _sqlpp__ppgen__colops__blob_h diff --git a/include/sqlpp11/ppgen/colops/bool.h b/include/sqlpp11/ppgen/colops/bool.h new file mode 100644 index 00000000..08521bd3 --- /dev/null +++ b/include/sqlpp11/ppgen/colops/bool.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _sqlpp__ppgen__colops__bool_h +#define _sqlpp__ppgen__colops__bool_h + +#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_bool \ + PROC_bool +#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_bool(...) \ + sqlpp::boolean + +#endif // _sqlpp__ppgen__colops__bool_h diff --git a/include/sqlpp11/ppgen/colops/comment.h b/include/sqlpp11/ppgen/colops/comment.h new file mode 100644 index 00000000..f019b732 --- /dev/null +++ b/include/sqlpp11/ppgen/colops/comment.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _sqlpp__ppgen__colops__comment_h +#define _sqlpp__ppgen__colops__comment_h + +#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_SQLPP_COMMENT(str) \ + PROC_SQLPP_COMMENT +#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_SQLPP_COMMENT(str) \ + [COMMENT is not implemented] + +#endif // _sqlpp__ppgen__colops__comment_h diff --git a/include/sqlpp11/ppgen/colops/datetime.h b/include/sqlpp11/ppgen/colops/datetime.h new file mode 100644 index 00000000..aec6bb04 --- /dev/null +++ b/include/sqlpp11/ppgen/colops/datetime.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _sqlpp__ppgen__colops__datetime_h +#define _sqlpp__ppgen__colops__datetime_h + +#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_datetime \ + PROC_datetime +#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_datetime(...) \ + [datetime is not implemented] + +#endif // _sqlpp__ppgen__colops__datetime_h diff --git a/include/sqlpp11/ppgen/colops/default.h b/include/sqlpp11/ppgen/colops/default.h new file mode 100644 index 00000000..b7fbdeeb --- /dev/null +++ b/include/sqlpp11/ppgen/colops/default.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _sqlpp__ppgen__colops__default_h +#define _sqlpp__ppgen__colops__default_h + +#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_SQLPP_DEFAULT(value) \ + PROC_SQLPP_DEFAULT +#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_SQLPP_DEFAULT(...) \ + [DEFAULT is not implemented] + +#endif // _sqlpp__ppgen__colops__default_h diff --git a/include/sqlpp11/ppgen/colops/floating_point.h b/include/sqlpp11/ppgen/colops/floating_point.h new file mode 100644 index 00000000..ea25560c --- /dev/null +++ b/include/sqlpp11/ppgen/colops/floating_point.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _sqlpp__ppgen__colops__floating_point_h +#define _sqlpp__ppgen__colops__floating_point_h + +#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_float \ + PROC_float +#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_float(...) \ + sqlpp::floating_point + +#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_double \ + PROC_double +#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_double(...) \ + sqlpp::floating_point + +#endif // _sqlpp__ppgen__colops__floating_point_h diff --git a/include/sqlpp11/ppgen/colops/index.h b/include/sqlpp11/ppgen/colops/index.h new file mode 100644 index 00000000..37a1fee1 --- /dev/null +++ b/include/sqlpp11/ppgen/colops/index.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _sqlpp__ppgen__colops__index_h +#define _sqlpp__ppgen__colops__index_h + +#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_SQLPP_INDEX(name) \ + PROC_SQLPP_INDEX +#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_SQLPP_INDEX(name) \ + [INDEX is not implemented] + +#endif // _sqlpp__ppgen__colops__index_h diff --git a/include/sqlpp11/ppgen/colops/integer.h b/include/sqlpp11/ppgen/colops/integer.h new file mode 100644 index 00000000..d913e441 --- /dev/null +++ b/include/sqlpp11/ppgen/colops/integer.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _sqlpp__ppgen__colops__integer_h +#define _sqlpp__ppgen__colops__integer_h + +#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_tinyint \ + PROC_tinyint +#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_tinyint(...) \ + sqlpp::tinyint + +#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_smallint \ + PROC_smallint +#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_smallint(...) \ + sqlpp::smallint + +#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_int \ + PROC_int +#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_int(...) \ + sqlpp::integer + +#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_bigint \ + PROC_bigint +#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_bigint(...) \ + sqlpp::bigint + +#endif // _sqlpp__ppgen__colops__integer_h diff --git a/include/sqlpp11/ppgen/colops/key.h b/include/sqlpp11/ppgen/colops/key.h new file mode 100644 index 00000000..1791c30c --- /dev/null +++ b/include/sqlpp11/ppgen/colops/key.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _sqlpp__ppgen__colops__key_h +#define _sqlpp__ppgen__colops__key_h + +#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_SQLPP_KEY(name) \ + PROC_SQLPP_KEY +#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_SQLPP_KEY(name) \ + [KEY is not implemented] + +#endif // _sqlpp__ppgen__colops__key_h diff --git a/include/sqlpp11/ppgen/colops/not_null.h b/include/sqlpp11/ppgen/colops/not_null.h new file mode 100644 index 00000000..0a2b029e --- /dev/null +++ b/include/sqlpp11/ppgen/colops/not_null.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _sqlpp__ppgen__colops__not_null_h +#define _sqlpp__ppgen__colops__not_null_h + +#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_SQLPP_NOT_NULL \ + PROC_SQLPP_NOT_NULL +#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_SQLPP_NOT_NULL(...) \ + sqlpp::tag::require_insert + +#endif // _sqlpp__ppgen__colops__not_null_h diff --git a/include/sqlpp11/ppgen/colops/null.h b/include/sqlpp11/ppgen/colops/null.h new file mode 100644 index 00000000..bd7d33d6 --- /dev/null +++ b/include/sqlpp11/ppgen/colops/null.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _sqlpp__ppgen__colops__null_h +#define _sqlpp__ppgen__colops__null_h + +#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_SQLPP_NULL \ + PROC_SQLPP_NULL +#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_SQLPP_NULL(...) \ + sqlpp::tag::can_be_null + +#endif // _sqlpp__ppgen__colops__null_h diff --git a/include/sqlpp11/ppgen/colops/primary_key.h b/include/sqlpp11/ppgen/colops/primary_key.h new file mode 100644 index 00000000..916f752b --- /dev/null +++ b/include/sqlpp11/ppgen/colops/primary_key.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _sqlpp__ppgen__colops__primary_key_h +#define _sqlpp__ppgen__colops__primary_key_h + +#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_SQLPP_PRIMARY_KEY \ + PROC_SQLPP_PRIMARY_KEY +#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_SQLPP_PRIMARY_KEY(...) \ + [PRIMARY_KEY is not implemented] + +#endif // _sqlpp__ppgen__colops__primary_key_h diff --git a/include/sqlpp11/ppgen/colops/text.h b/include/sqlpp11/ppgen/colops/text.h new file mode 100644 index 00000000..7329a986 --- /dev/null +++ b/include/sqlpp11/ppgen/colops/text.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _sqlpp__ppgen__colops__text_h +#define _sqlpp__ppgen__colops__text_h + +#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_text \ + PROC_text +#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_text(...) \ + sqlpp::text + +#endif // _sqlpp__ppgen__colops__text_h diff --git a/include/sqlpp11/ppgen/colops/timestamp.h b/include/sqlpp11/ppgen/colops/timestamp.h new file mode 100644 index 00000000..130e005b --- /dev/null +++ b/include/sqlpp11/ppgen/colops/timestamp.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _sqlpp__ppgen__colops__timestamp_h +#define _sqlpp__ppgen__colops__timestamp_h + +#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_timestamp \ + PROC_timestamp +#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_timestamp(...) \ + [timestamp is not implemented] + +#endif // _sqlpp__ppgen__colops__timestamp_h diff --git a/include/sqlpp11/ppgen/colops/unique.h b/include/sqlpp11/ppgen/colops/unique.h new file mode 100644 index 00000000..34b43792 --- /dev/null +++ b/include/sqlpp11/ppgen/colops/unique.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _sqlpp__ppgen__colops__unique_h +#define _sqlpp__ppgen__colops__unique_h + +#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_SQLPP_UNIQUE \ + PROC_SQLPP_UNIQUE +#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_SQLPP_UNIQUE(...) \ + [UNIQUE is not implemented] + +#endif // _sqlpp__ppgen__colops__unique_h diff --git a/include/sqlpp11/ppgen/colops/varchar.h b/include/sqlpp11/ppgen/colops/varchar.h new file mode 100644 index 00000000..c4de3235 --- /dev/null +++ b/include/sqlpp11/ppgen/colops/varchar.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _sqlpp__ppgen__colops__varchar_h +#define _sqlpp__ppgen__colops__varchar_h + +#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_varchar(str) \ + PROC_varchar +#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_varchar(str) \ + sqlpp::varchar + +#endif // _sqlpp__ppgen__colops__varchar_h diff --git a/include/sqlpp11/ppgen/tblops/character_set.h b/include/sqlpp11/ppgen/tblops/character_set.h new file mode 100644 index 00000000..8b5026b2 --- /dev/null +++ b/include/sqlpp11/ppgen/tblops/character_set.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _sqlpp__ppgen__tblops__character_set_h +#define _sqlpp__ppgen__tblops__character_set_h + +#define SQLPP_DECLARE_TABLE_GET_PROC_LAZY_SQLPP_CHARACTER_SET(str) \ + PROC_SQLPP_CHARACTER_SET +#define SQLPP_DECLARE_TABLE_GEN_PROC_SQLPP_CHARACTER_SET(str) \ + [CHARACTER_SET is not implemented] + +#endif // _sqlpp__ppgen__tblops__character_set_h diff --git a/include/sqlpp11/ppgen/tblops/comment.h b/include/sqlpp11/ppgen/tblops/comment.h new file mode 100644 index 00000000..6df2784b --- /dev/null +++ b/include/sqlpp11/ppgen/tblops/comment.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _sqlpp__ppgen__tblops__comment_h +#define _sqlpp__ppgen__tblops__comment_h + +#define SQLPP_DECLARE_TABLE_GET_TRAITS_LAZY_SQLPP_COMMENT(str) \ + PROC_SQLPP_COMMENT +#define SQLPP_DECLARE_TABLE_GEN_TRAITS_PROC_SQLPP_COMMENT(str) \ + [COMMENT is not implemented] + +#endif // _sqlpp__ppgen__tblops__comment_h diff --git a/include/sqlpp11/ppgen/tblops/default.h b/include/sqlpp11/ppgen/tblops/default.h new file mode 100644 index 00000000..7e70bf8f --- /dev/null +++ b/include/sqlpp11/ppgen/tblops/default.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _sqlpp__ppgen__tblops__default_h +#define _sqlpp__ppgen__tblops__default_h + +#define SQLPP_DECLARE_TABLE_GET_TRAITS_LAZY_SQLPP_DEFAULT(value) \ + PROC_SQLPP_DEFAULT +#define SQLPP_DECLARE_TABLE_GEN_TRAITS_PROC_SQLPP_DEFAULT(...) \ + [DEFAULT is not implemented] + +#endif // _sqlpp__ppgen__tblops__default_h diff --git a/include/sqlpp11/ppgen/tblops/engine.h b/include/sqlpp11/ppgen/tblops/engine.h new file mode 100644 index 00000000..24b2e8aa --- /dev/null +++ b/include/sqlpp11/ppgen/tblops/engine.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _sqlpp__ppgen__tblops__engine_h +#define _sqlpp__ppgen__tblops__engine_h + +#define SQLPP_DECLARE_TABLE_GET_PROC_LAZY_SQLPP_ENGINE(str) \ + PROC_SQLPP_ENGINE +#define SQLPP_DECLARE_TABLE_GEN_PROC_SQLPP_ENGINE(str) \ + [ENGINE is not implemented] + +#endif // _sqlpp__ppgen__tblops__engine_h diff --git a/include/sqlpp11/ppgen/tools/tuple_pop_front.h b/include/sqlpp11/ppgen/tools/tuple_pop_front.h new file mode 100644 index 00000000..c958fb89 --- /dev/null +++ b/include/sqlpp11/ppgen/tools/tuple_pop_front.h @@ -0,0 +1,44 @@ +/* ************************************************************************** + * * + * (C) Copyright Edward Diener 2013. + * Distributed under the Boost Software License, Version 1.0. (See + * accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * * + ************************************************************************** */ + +/* See http://www.boost.org for most recent version. */ + +# ifndef SQLPP_BOOST_PREPROCESSOR_TUPLE_POP_FRONT_HPP +# define SQLPP_BOOST_PREPROCESSOR_TUPLE_POP_FRONT_HPP + +# include + +# if BOOST_PP_VARIADICS + +# include +# include +# include +# include +# include +# include + + +/* BOOST_PP_TUPLE_POP_FRONT */ +# define SQLPP_BOOST_PP_TUPLE_POP_FRONT(tuple) \ + BOOST_PP_IIF \ + ( \ + BOOST_PP_GREATER(BOOST_PP_TUPLE_SIZE(tuple),1), \ + SQLPP_BOOST_PP_TUPLE_POP_FRONT_EXEC, \ + SQLPP_BOOST_PP_TUPLE_POP_FRONT_RETURN \ + ) \ + (tuple) + +# define SQLPP_BOOST_PP_TUPLE_POP_FRONT_EXEC(tuple) \ + BOOST_PP_ARRAY_TO_TUPLE(BOOST_PP_ARRAY_POP_FRONT(BOOST_PP_TUPLE_TO_ARRAY(tuple))) + +# define SQLPP_BOOST_PP_TUPLE_POP_FRONT_RETURN(tuple) tuple + +# endif // BOOST_PP_VARIADICS + +# endif // SQLPP_BOOST_PREPROCESSOR_TUPLE_POP_FRONT_HPP diff --git a/include/sqlpp11/ppgen/tools/wrap_seq.h b/include/sqlpp11/ppgen/tools/wrap_seq.h new file mode 100644 index 00000000..9f9451f9 --- /dev/null +++ b/include/sqlpp11/ppgen/tools/wrap_seq.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _sqlpp__ppgen__tools__wrap_seq_h +#define _sqlpp__ppgen__tools__wrap_seq_h + +#define SQLPP_WRAP_SEQUENCE_X(...) \ + ((__VA_ARGS__)) SQLPP_WRAP_SEQUENCE_Y +#define SQLPP_WRAP_SEQUENCE_Y(...) \ + ((__VA_ARGS__)) SQLPP_WRAP_SEQUENCE_X + +#define SQLPP_WRAP_SEQUENCE_X0 +#define SQLPP_WRAP_SEQUENCE_Y0 + +#endif // _sqlpp__ppgen__tools__wrap_seq_h diff --git a/include/sqlpp11/prepared_execute.h b/include/sqlpp11/prepared_execute.h new file mode 100644 index 00000000..7027bbc0 --- /dev/null +++ b/include/sqlpp11/prepared_execute.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2013-2015, Roland Bock + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SQLPP_PREPARED_EXECUTE_H +#define SQLPP_PREPARED_EXECUTE_H + +#include +#include +#include + +namespace sqlpp +{ + template + struct prepared_execute_t + { + using _traits = make_traits; + using _nodes = detail::type_vector<>; + + using _parameter_list_t = make_parameter_list_t; + using _prepared_statement_t = typename Db::_prepared_statement_t; + + using _run_check = consistent_t; + + auto _run(Db& db) const + -> void + { + return db.run_prepared_execute(*this); + } + + void _bind_params() const + { + params._bind(_prepared_statement); + } + + _parameter_list_t params; + mutable _prepared_statement_t _prepared_statement; + }; + +} + +#endif diff --git a/include/sqlpp11/prepared_insert.h b/include/sqlpp11/prepared_insert.h index e32c73c8..416b46de 100644 --- a/include/sqlpp11/prepared_insert.h +++ b/include/sqlpp11/prepared_insert.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -29,15 +29,21 @@ #include #include +#include namespace sqlpp { template struct prepared_insert_t { + using _traits = make_traits; + using _nodes = detail::type_vector<>; + using _parameter_list_t = make_parameter_list_t; using _prepared_statement_t = typename Db::_prepared_statement_t; + using _run_check = consistent_t; + auto _run(Db& db) const -> size_t { diff --git a/include/sqlpp11/prepared_remove.h b/include/sqlpp11/prepared_remove.h index 672ab5a6..3d75c9e0 100644 --- a/include/sqlpp11/prepared_remove.h +++ b/include/sqlpp11/prepared_remove.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -29,15 +29,21 @@ #include #include +#include namespace sqlpp { template struct prepared_remove_t { + using _traits = make_traits; + using _nodes = detail::type_vector<>; + using _parameter_list_t = make_parameter_list_t; using _prepared_statement_t = typename Db::_prepared_statement_t; + using _run_check = consistent_t; + auto _run(Db& db) const -> size_t { diff --git a/include/sqlpp11/prepared_select.h b/include/sqlpp11/prepared_select.h index 2c74e9a2..5d5893f5 100644 --- a/include/sqlpp11/prepared_select.h +++ b/include/sqlpp11/prepared_select.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -29,17 +29,23 @@ #include #include +#include namespace sqlpp { - template + template struct prepared_select_t { - using _result_row_t = typename Select::template _result_row_t; - using _parameter_list_t = make_parameter_list_t
; + using _nodes = detail::type_vector
; static_assert(is_table_t
::value, "argument has to be a table"); static_assert(required_tables_of
::size::value == 0, "table depends on another table"); using _data_t = single_table_data_t; - struct _name_t {}; + struct _alias_t {}; // Member implementation with data and methods template @@ -74,9 +74,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = single_table_data_t; @@ -89,13 +89,8 @@ namespace sqlpp { return t.from; } - }; - // Additional methods for the statement - template - struct _methods_t - { - static void _check_consistency() {} + using _consistency_check = consistent_t; }; }; @@ -104,7 +99,7 @@ namespace sqlpp struct no_single_table_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits<>; + using _nodes = detail::type_vector<>; // Data using _data_t = no_data_t; @@ -116,9 +111,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = no_data_t; @@ -131,22 +126,36 @@ namespace sqlpp { return t.no_from; } - }; - template - struct _methods_t - { using _database_t = typename Policies::_database_t; template - using _new_statement_t = new_statement; + using _check = logic::all_t::value>; - static void _check_consistency() {} + template + using _new_statement_t = new_statement_t; - template - auto from(Args... args) const - -> _new_statement_t> + using _consistency_check = consistent_t; + + template + auto single_table(Table table) const + -> _new_statement_t<_check
, single_table_t> { - return { static_cast&>(*this), single_table_data_t{args...} }; + static_assert(_check
::value, "argument is not a table in single_table()"); + return _single_table_impl(_check
{}, table); + } + + private: + template + auto _single_table_impl(const std::false_type&, Table table) const + -> bad_statement; + + template + auto _single_table_impl(const std::true_type&, Table table) const + -> _new_statement_t> + { + static_assert(required_tables_of>::size::value == 0, "argument depends on another table in single_table()"); + + return { static_cast&>(*this), single_table_data_t{table} }; } }; }; @@ -155,6 +164,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = single_table_data_t; static Context& _(const T& t, Context& context) diff --git a/include/sqlpp11/some.h b/include/sqlpp11/some.h index 00dfb755..1800e974 100644 --- a/include/sqlpp11/some.h +++ b/include/sqlpp11/some.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -29,6 +29,7 @@ #include #include +#include namespace sqlpp { @@ -36,11 +37,12 @@ namespace sqlpp struct some_t { using _traits = make_traits, tag::is_multi_expression>; - using _recursive_traits = make_recursive_traits; - struct _name_t + struct _alias_t { - static constexpr const char* _get_name() { return "SOME"; } + static constexpr const char _literal[] = "some_"; + using _name_t = sqlpp::make_char_sequence; template struct _member_t { @@ -66,6 +68,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = some_t
; - using _provided_outer_tables = detail::type_set<>; - using _extra_tables = detail::type_set<>; - using _tags = detail::type_set<>; - }; + using _nodes = detail::type_vector<>; + using _provided_tables = detail::type_set
; static_assert(sizeof...(ColumnSpec), "at least one column required per table"); using _required_insert_columns = typename detail::make_type_set_if...>::type; @@ -108,11 +101,12 @@ namespace sqlpp template struct serializer_t::value and not is_pseudo_table_t::value, void>::type> { + using _serialize_check = consistent_t; using T = X; static Context& _(const T& t, Context& context) { - context << T::_name_t::_get_name(); + context << name_of::char_ptr(); return context; } }; diff --git a/include/sqlpp11/table_alias.h b/include/sqlpp11/table_alias.h index d35245be..2452ec6c 100644 --- a/include/sqlpp11/table_alias.h +++ b/include/sqlpp11/table_alias.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -42,19 +42,13 @@ namespace sqlpp //FIXME: Need to add join functionality using _traits = make_traits, tag::is_table, tag::is_alias, tag_if::value>>; - struct _recursive_traits - { - using _parameters = std::tuple<>; - using _required_tables = detail::type_set<>; - using _provided_tables = detail::type_set; - using _provided_outer_tables = detail::type_set<>; - using _extra_tables = detail::type_set<>; - using _tags = detail::type_set<>; - }; + using _nodes = detail::type_vector<>; + using _required_ctes = required_ctes_of
; + using _provided_tables = detail::type_set; static_assert(required_tables_of
::size::value == 0, "table aliases must not depend on external tables"); - using _name_t = typename AliasProvider::_name_t; + using _alias_t = typename AliasProvider::_alias_t; using _column_tuple_t = std::tuple...>; table_alias_t(Table table): @@ -67,13 +61,17 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = table_alias_t; static Context& _(const T& t, Context& context) { - context << "("; + if (requires_braces_t::value) + context << "("; serialize(t._table, context); - context << ") AS " << T::_name_t::_get_name(); + if (requires_braces_t::value) + context << ")"; + context << " AS " << name_of::char_ptr(); return context; } }; diff --git a/include/sqlpp11/table_ref.h b/include/sqlpp11/table_ref.h new file mode 100644 index 00000000..fa3b0fe4 --- /dev/null +++ b/include/sqlpp11/table_ref.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013-2015, Roland Bock + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SQLPP_TABLE_REF_H +#define SQLPP_TABLE_REF_H + +#include + +namespace sqlpp +{ + template + auto from_table(T t) -> T + { + return t; + } + + template + struct from_table_impl + { + using type = T; + }; + template + using from_table_t = typename from_table_impl::type; + + template + auto table_ref(T t) -> T + { + return t; + } +} + +#endif diff --git a/include/sqlpp11/text.h b/include/sqlpp11/text.h index c42dea5d..9604a43c 100644 --- a/include/sqlpp11/text.h +++ b/include/sqlpp11/text.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -237,6 +237,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = consistent_t; using T = result_field_t; static Context& _(const T& t, Context& context) diff --git a/include/sqlpp11/transaction.h b/include/sqlpp11/transaction.h index c140d168..ee844373 100644 --- a/include/sqlpp11/transaction.h +++ b/include/sqlpp11/transaction.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/tvin.h b/include/sqlpp11/tvin.h index fe289149..9c4b3c1a 100644 --- a/include/sqlpp11/tvin.h +++ b/include/sqlpp11/tvin.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -40,7 +40,7 @@ namespace sqlpp struct tvin_arg_t { using _traits = make_traits, tag::is_expression>; - using _recursive_traits = make_recursive_traits; + using _nodes = detail::type_vector; using _operand_t = Operand; @@ -56,14 +56,26 @@ namespace sqlpp _operand_t _value; }; + struct assert_tvin_with_correct_operator_t + { + using type = std::false_type; + + template + static void _() + { + static_assert(wrong_t::value, "tvin may only be used with operators =, == and !="); + } + }; + template struct serializer_t> { + using _serialize_check = assert_tvin_with_correct_operator_t; using T = tvin_arg_t; static Context& _(const T& t, Context& context) { - static_assert(wrong_t::value, "tvin may only be used with operators =, == and !="); + _serialize_check::_(); } }; @@ -90,7 +102,7 @@ namespace sqlpp struct tvin_t { using _traits = make_traits, tag::is_expression>; - using _recursive_traits = make_recursive_traits; + using _nodes = detail::type_vector; using _operand_t = Operand; @@ -135,6 +147,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = tvin_t; static Context& _(const T& t, Context& context) diff --git a/include/sqlpp11/type_traits.h b/include/sqlpp11/type_traits.h index 6160b15c..8610532a 100644 --- a/include/sqlpp11/type_traits.h +++ b/include/sqlpp11/type_traits.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -28,36 +28,19 @@ #define SQLPP_TYPE_TRAITS_H #include +#include +#include +#include #include +#include namespace sqlpp { namespace tag { struct can_be_null{}; - struct contains_aggregate_function{}; } - namespace detail - { - template - struct can_be_null_impl { using type = std::false_type; }; - template - struct can_be_null_impl::value>::type> { using type = std::true_type; }; - } - template - using can_be_null_t = typename detail::can_be_null_impl::type; - - namespace detail - { - template - struct contains_aggregate_function_impl { using type = std::false_type; }; - template - struct contains_aggregate_function_impl::value>::type> { using type = std::true_type; }; - } - template - using contains_aggregate_function_t = typename detail::contains_aggregate_function_impl::type; - namespace detail { template @@ -68,23 +51,6 @@ namespace sqlpp template using column_spec_can_be_null_t = typename detail::column_spec_can_be_null_impl::type; - namespace tag - { - struct is_expression{}; - } - namespace detail - { - template - struct is_expression_impl { using type = std::false_type; }; - template - struct is_expression_impl::value - and not detail::is_element_of::value - >::type> { using type = std::true_type; }; - } - template - using is_expression_t = typename detail::is_expression_impl::type; - #define SQLPP_VALUE_TRAIT_GENERATOR(name) \ namespace tag\ {\ @@ -106,15 +72,18 @@ namespace sqlpp SQLPP_VALUE_TRAIT_GENERATOR(is_integral) SQLPP_VALUE_TRAIT_GENERATOR(is_floating_point) template - using is_numeric_t = detail::any_t< + using is_numeric_t = logic::any_t< detail::is_element_of::value, detail::is_element_of::value>; + SQLPP_VALUE_TRAIT_GENERATOR(is_text) SQLPP_VALUE_TRAIT_GENERATOR(is_wrapped_value) SQLPP_VALUE_TRAIT_GENERATOR(is_selectable) + SQLPP_VALUE_TRAIT_GENERATOR(is_expression) SQLPP_VALUE_TRAIT_GENERATOR(is_multi_expression) SQLPP_VALUE_TRAIT_GENERATOR(is_alias) SQLPP_VALUE_TRAIT_GENERATOR(is_select_flag) + SQLPP_VALUE_TRAIT_GENERATOR(is_union_flag) SQLPP_VALUE_TRAIT_GENERATOR(is_result_field) SQLPP_VALUE_TRAIT_GENERATOR(must_not_insert) @@ -123,6 +92,11 @@ namespace sqlpp SQLPP_VALUE_TRAIT_GENERATOR(trivial_value_is_null) SQLPP_VALUE_TRAIT_GENERATOR(null_is_trivial_value) + SQLPP_VALUE_TRAIT_GENERATOR(is_statement) + SQLPP_VALUE_TRAIT_GENERATOR(is_prepared_statement) + SQLPP_VALUE_TRAIT_GENERATOR(is_union) + SQLPP_VALUE_TRAIT_GENERATOR(is_with) + SQLPP_VALUE_TRAIT_GENERATOR(is_cte) SQLPP_VALUE_TRAIT_GENERATOR(is_noop) SQLPP_VALUE_TRAIT_GENERATOR(is_missing) SQLPP_VALUE_TRAIT_GENERATOR(is_return_value) @@ -166,37 +140,92 @@ namespace sqlpp template using is_database = typename std::conditional::value, std::false_type, std::true_type>::type; - namespace detail - { - template - using make_parameter_tuple_t = decltype(std::tuple_cat(std::declval()...)); - } template using value_type_of = typename T::_traits::_value_type; template using cpp_value_type_of = typename value_type_of::_cpp_value_type; - template - using required_tables_of = typename T::_recursive_traits::_required_tables; +#define SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(trait) \ + namespace detail\ + {\ + template\ + struct trait##_of_impl\ + {\ + using type = typename trait##_of_impl::type;\ + };\ + template\ + struct trait##_of_impl::value>::type>\ + {\ + using type = typename T::_##trait;\ + };\ + template\ + struct trait##_of_impl, void>\ + {\ + using type = detail::make_joined_set_t::type...>;\ + };\ + }\ + template\ + using trait##_of = typename detail::trait##_of_impl::type; + + SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(required_ctes) + SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(provided_ctes) + SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(required_tables) + SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(provided_tables) + SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(provided_outer_tables) + SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(extra_tables) + +#define SQLPP_RECURSIVE_TRAIT_GENERATOR(trait) \ + namespace detail\ + {\ + template\ + struct trait##_impl\ + {\ + using type = typename trait##_impl::type;\ + };\ + template\ + struct trait##_impl::value>::type>\ + {\ + using type = typename T::_##trait;\ + };\ + template\ + struct trait##_impl, void>\ + {\ + using type = logic::any_t::type::value...>;\ + };\ + }\ + template\ + using trait##_t = typename detail::trait##_impl::type; + + SQLPP_RECURSIVE_TRAIT_GENERATOR(can_be_null) + SQLPP_RECURSIVE_TRAIT_GENERATOR(contains_aggregate_function) + + namespace detail + { + template + struct parameters_of_impl + { + using type = typename parameters_of_impl::type; + }; + template + struct parameters_of_impl::value>::type> + { + using type = typename T::_parameters; + }; + template + struct parameters_of_impl, void> + { + using type = detail::type_vector_cat_t::type...>; + }; + } + template\ + using parameters_of = typename detail::parameters_of_impl::type; template - using provided_tables_of = typename T::_recursive_traits::_provided_tables; + using alias_of = typename T::_alias_t; template - using provided_outer_tables_of = typename T::_recursive_traits::_provided_outer_tables; - - template - using extra_tables_of = typename T::_recursive_traits::_extra_tables; - - template - using parameters_of = typename T::_recursive_traits::_parameters; - - template - using recursive_tags_of = typename T::_recursive_traits::_tags; - - template - using name_of = typename T::_name_t; + using name_of = typename T::_alias_t::_name_t; template struct make_traits @@ -205,39 +234,165 @@ namespace sqlpp using _tags = detail::make_type_set_t; }; - template - struct make_recursive_traits - { - using _required_tables = detail::make_joined_set_t...>; - using _provided_tables = detail::make_joined_set_t...>; - using _provided_outer_tables = detail::make_joined_set_t...>; - using _extra_tables = detail::make_joined_set_t...>; - using _parameters = detail::make_parameter_tuple_t...>; - using _tags = detail::make_joined_set_t...>; - }; - - template - struct recursive_tags - { - using _required_tables = detail::type_set<>; - using _provided_tables = detail::type_set<>; - using _provided_outer_tables = detail::type_set<>; - using _extra_tables = detail::type_set<>; - using _parameters = std::tuple<>; - using _tags = detail::type_set; - }; - struct aggregate_function { - struct _traits { using _value_type = void; using _tags = detail::type_set<>; }; - using _recursive_traits = recursive_tags; + using _nodes = detail::type_vector<>; + using _contains_aggregate_function = std::true_type; }; template - using member_t = typename NameProvider::_name_t::template _member_t; + using member_t = typename NameProvider::_alias_t::template _member_t; template using derived_statement_t = typename Policies::_statement_t; + + struct consistent_t + { + using type = std::true_type; + + static void _() {}; + }; + + template + using is_inconsistent_t = typename std::conditional::value, std::false_type, std::true_type>::type; + + template + using serialize_check_of = detail::get_first_if::_serialize_check...>; + + struct assert_run_statement_or_prepared_t + { + using type = std::false_type; + + template + static void _() + { + static_assert(wrong_t::value, "connection cannot run something that is neither statement nor prepared statement"); + } + }; + + struct assert_prepare_statement_t + { + using type = std::false_type; + + template + static void _() + { + static_assert(wrong_t::value, "connection cannot prepare something that is not a statement"); + } + }; + + template + struct consistency_check + { + using type = assert_run_statement_or_prepared_t; + }; + + template + struct consistency_check::value or is_prepared_statement_t::value>::type> + { + using type = typename T::_consistency_check; + }; + + template + using consistency_check_t = typename consistency_check::type; + + template + struct run_check + { + using type = assert_run_statement_or_prepared_t; + }; + + template + struct run_check::value or is_prepared_statement_t::value>::type> + { + using type = typename T::_run_check; + }; + + template + using run_check_t = typename run_check::type; + + template + struct prepare_check + { + using type = assert_prepare_statement_t; + }; + + template + struct prepare_check::value>::type> + { + using type = typename T::_prepare_check; + }; + + template + using prepare_check_t = typename prepare_check::type; + + + template + struct serialize_check + { + using type = serialize_check_of; + }; + + template + struct serialize_check::value>::type> + { + using type = consistent_t; // this is already serialized + }; + + template + using serialize_check_t = typename serialize_check::type; + + template + struct has_result_row_impl + { + using type = std::false_type; + }; + + template + struct has_result_row_impl::template _result_row_t>::value, + void>::type> + { + using type = std::true_type; + }; + + template + using has_result_row_t = typename has_result_row_impl::type; + + template + struct get_result_row_impl + { + using type = void; + }; + + template + struct get_result_row_impl::template _result_row_t>::value, + void>::type> + { + using type = typename Statement::template _result_methods_t::template _result_row_t; + }; + + template + using get_result_row_t = typename get_result_row_impl::type; + + template class Predicate, typename Enable=void> + struct has_policy_impl + { + using type = std::false_type; + }; + + template class Predicate> + struct has_policy_impl::value>::type> + { + using type = std::true_type; + }; + + template class Predicate> + using has_policy_t = typename has_policy_impl::type; + } #endif diff --git a/include/sqlpp11/union.h b/include/sqlpp11/union.h new file mode 100644 index 00000000..f8daf2f2 --- /dev/null +++ b/include/sqlpp11/union.h @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2013-2015, Roland Bock + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SQLPP_UNION_H +#define SQLPP_UNION_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sqlpp +{ + struct no_union_t; + + using blank_union_t = statement_t; + // There is no order by or limit or offset in union, use it as a pseudo table to do that. + + template + struct union_statement_impl + { + using type = statement_t; + }; + + template + struct union_statement_impl + { + using type = bad_statement; + }; + + template + using union_statement_t = typename union_statement_impl::type; + + // UNION(EXPR) + template + struct union_t + { + using _traits = make_traits; + using _nodes = detail::type_vector; + + using _alias_t = struct{}; + + // Data + using _data_t = union_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + public: + _data_t _data; + }; + + // Base template to be inherited by the statement + template + struct _base_t + { + using _data_t = union_data_t; + + _impl_t union_; + _impl_t& operator()() { return union_; } + const _impl_t& operator()() const { return union_; } + + using _selected_columns_t = typename std::decay::type; + _selected_columns_t& get_selected_columns() { return union_._data._lhs.get_selected_columns(); } + const _selected_columns_t& get_selected_columns() const { return union_._data._lhs.get_selected_columns(); } + + template + static auto _get_member(T t) -> decltype(t.union_) + { + return t.union_; + } + + using _consistency_check = detail::get_first_if; + }; + + template + using _result_methods_t = typename Lhs::template _result_methods_t; + }; + + // NO UNION YET + struct no_union_t + { + using _traits = make_traits; + using _nodes = detail::type_vector<>; + + // Data + using _data_t = no_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + _data_t _data; + }; + + // Base template to be inherited by the statement + template + struct _base_t + { + using _data_t = no_data_t; + + _impl_t no_union; + _impl_t& operator()() { return no_union; } + const _impl_t& operator()() const { return no_union; } + + template + static auto _get_member(T t) -> decltype(t.no_union) + { + return t.no_union; + } + + using _database_t = typename Policies::_database_t; + + template + using _check = logic::all_t::value...>; + + template + using _new_statement_t = union_statement_t; + + using _consistency_check = consistent_t; + + template + auto union_distinct(Rhs rhs) const + -> _new_statement_t<_check, union_t, Rhs>> + { + static_assert(is_statement_t::value, "argument of union call has to be a statement"); + static_assert(has_policy_t::value, "argument of union call has to be a select"); + static_assert(has_result_row_t::value, "argument of a union has to be a complete select statement"); + static_assert(has_result_row_t>::value, "left hand side argument of a union has to be a complete select statement or union"); + + using _result_row_t = get_result_row_t; + static_assert(std::is_same>, _result_row_t>::value, "both arguments in a union have to have the same result columns (type and name)"); + static_assert(is_static_result_row_t<_result_row_t>::value, "unions must not have dynamically added columns"); + + return _union_impl(_check, Rhs>{}, rhs); + } + + template + auto union_all(Rhs rhs) const + -> _new_statement_t<_check, union_t, Rhs>> + { + static_assert(is_statement_t::value, "argument of union call has to be a statement"); + static_assert(has_policy_t::value, "argument of union call has to be a select"); + static_assert(has_result_row_t::value, "argument of a union has to be a (complete) select statement"); + static_assert(has_result_row_t>::value, "left hand side argument of a union has to be a (complete) select statement"); + + using _result_row_t = get_result_row_t; + static_assert(std::is_same>, _result_row_t>::value, "both arguments in a union have to have the same result columns (type and name)"); + static_assert(is_static_result_row_t<_result_row_t>::value, "unions must not have dynamically added columns"); + + return _union_impl(_check, Rhs>{}, rhs); + } + + private: + template + auto _union_impl(const std::false_type&, Rhs rhs) const + -> bad_statement; + + template + auto _union_impl(const std::true_type&, Rhs rhs) const + -> _new_statement_t, Rhs>> + { + return { blank_union_t{}, + union_data_t<_database_t, Flag, derived_statement_t, Rhs>{static_cast&>(*this), rhs} }; + } + + }; + }; + +} + +#endif diff --git a/include/sqlpp11/union_data.h b/include/sqlpp11/union_data.h new file mode 100644 index 00000000..f1c02f4a --- /dev/null +++ b/include/sqlpp11/union_data.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2013-2015, Roland Bock + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SQLPP_UNION_DATA_H +#define SQLPP_UNION_DATA_H + +#include + +namespace sqlpp +{ + template + struct union_data_t + { + union_data_t(Lhs lhs, Rhs rhs): + _lhs(lhs), + _rhs(rhs) + {} + + union_data_t(const union_data_t&) = default; + union_data_t(union_data_t&&) = default; + union_data_t& operator=(const union_data_t&) = default; + union_data_t& operator=(union_data_t&&) = default; + ~union_data_t() = default; + + Lhs _lhs; + Rhs _rhs; + }; + + // Interpreters + template + struct serializer_t> + { + using _serialize_check = serialize_check_of; + using T = union_data_t; + + static Context& _(const T& t, Context& context) + { + serialize(t._lhs, context); + context << " UNION "; + serialize(Flag{}, context); + context << " "; + serialize(t._rhs, context); + return context; + } + }; + +} + +#endif diff --git a/include/sqlpp11/union_flags.h b/include/sqlpp11/union_flags.h new file mode 100644 index 00000000..9d2ded02 --- /dev/null +++ b/include/sqlpp11/union_flags.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2013-2015, Roland Bock + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SQLPP_UNION_FLAGS_H +#define SQLPP_UNION_FLAGS_H + +#include +#include +#include +#include + +namespace sqlpp +{ + // standard select flags + struct union_all_t + { + using _traits = make_traits; + using _nodes = detail::type_vector<>; + }; + + template + struct serializer_t + { + using _serialize_check = consistent_t; + + static Context& _(const union_all_t&, Context& context) + { + context << "ALL"; + return context; + } + }; + + struct union_distinct_t + { + using _traits = make_traits; + using _nodes = detail::type_vector<>; + }; + + template + struct serializer_t + { + using _serialize_check = consistent_t; + + static Context& _(const union_distinct_t&, Context& context) + { + return context; + } + }; + +} + +#endif diff --git a/include/sqlpp11/update.h b/include/sqlpp11/update.h index 492f0791..1f3019f9 100644 --- a/include/sqlpp11/update.h +++ b/include/sqlpp11/update.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -44,35 +44,46 @@ namespace sqlpp struct update_t: public statement_name_t { using _traits = make_traits; - struct _name_t {}; + struct _alias_t {}; - template + template struct _result_methods_t { - using _statement_t = derived_statement_t; + using _statement_t = Statement; const _statement_t& _get_statement() const { return static_cast(*this); } + // Execute + template + auto _run(Db& db, const Composite& composite) const + -> decltype(db.update(composite)) + { + return db.update(composite); + } + template auto _run(Db& db) const -> decltype(db.update(this->_get_statement())) { - _statement_t::_check_consistency(); - - static_assert(_statement_t::_get_static_no_of_parameters() == 0, "cannot run update directly with parameters, use prepare instead"); return db.update(_get_statement()); } - template - auto _prepare(Db& db) const - -> prepared_update_t - { - _statement_t::_check_consistency(); + // Prepare + template + auto _prepare(Db& db, const Composite& composite) const + -> prepared_update_t + { + return {{}, db.prepare_update(composite)}; + } - return {{}, db.prepare_update(_get_statement())}; - } + template + auto _prepare(Db& db) const + -> prepared_update_t + { + return {{}, db.prepare_update(_get_statement())}; + } }; }; @@ -80,6 +91,7 @@ namespace sqlpp template struct serializer_t { + using _serialize_check = consistent_t; using T = update_name_t; static Context& _(const T& t, Context& context) @@ -100,17 +112,17 @@ namespace sqlpp template constexpr auto update(Table table) - -> decltype(blank_update_t().from(table)) + -> decltype(blank_update_t().single_table(table)) { - return { blank_update_t().from(table) }; + return { blank_update_t().single_table(table) }; } template constexpr auto dynamic_update(const Database&, Table table) - -> decltype(blank_update_t().from(table)) + -> decltype(blank_update_t().single_table(table)) { static_assert(std::is_base_of::value, "Invalid database parameter"); - return { blank_update_t().from(table) }; + return { blank_update_t().single_table(table) }; } } diff --git a/include/sqlpp11/update_list.h b/include/sqlpp11/update_list.h index 425b8b8f..d2e3cd9e 100644 --- a/include/sqlpp11/update_list.h +++ b/include/sqlpp11/update_list.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -52,12 +52,23 @@ namespace sqlpp interpretable_list_t _dynamic_assignments; }; + struct assert_no_unknown_tables_in_update_assignments_t + { + using type = std::false_type; + + template + static void _() + { + static_assert(wrong_t::value, "at least one update assignment requires a table which is otherwise not known in the statement"); + } + }; + // UPDATE ASSIGNMENTS template struct update_list_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits; + using _nodes = detail::type_vector; using _is_dynamic = is_database; // Data @@ -80,12 +91,15 @@ namespace sqlpp static_assert(is_assignment_t::value, "invalid assignment argument in add()"); using _assigned_columns = detail::make_type_set_t...>; static_assert(not detail::is_element_of, _assigned_columns>::value, "Must not assign value to column twice"); - static_assert(detail::not_t>::value, "add() argument must not be updated"); + static_assert(logic::not_t>::value, "add() argument must not be updated"); static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables::value, "assignment uses tables unknown to this statement in add()"); + using _serialize_check = sqlpp::serialize_check_t; + _serialize_check::_(); - using ok = detail::all_t< + using ok = logic::all_t< _is_dynamic::value, - is_assignment_t::value>; + is_assignment_t::value, + _serialize_check::type::value>; _add_impl(assignment, ok()); // dispatch to prevent compile messages after the static_assert } @@ -103,9 +117,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = update_list_data_t; @@ -118,20 +132,28 @@ namespace sqlpp { return t.assignments; } - }; - // Additional methods for the statement - template - struct _methods_t - { - static void _check_consistency() {} + using _consistency_check = typename std::conditional::value, + consistent_t, + assert_no_unknown_tables_in_update_assignments_t>::type; }; }; + struct assert_update_assignments_t + { + using type = std::false_type; + + template + static void _() + { + static_assert(wrong_t::value, "update assignments required, i.e. set(...)"); + } + }; + struct no_update_list_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits<>; + using _nodes = detail::type_vector<>; // Data using _data_t = no_data_t; @@ -143,9 +165,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = no_data_t; @@ -158,44 +180,48 @@ namespace sqlpp { return t.no_assignments; } - }; - template - struct _methods_t - { using _database_t = typename Policies::_database_t; - template - using _new_statement_t = new_statement; - static void _check_consistency() - { - static_assert(wrong_t<_methods_t>::value, "update assignments required, i.e. set(...)"); - } + template + using _check = logic::all_t::value...>; + + template + using _new_statement_t = new_statement_t; + + using _consistency_check = assert_update_assignments_t; template auto set(Assignments... assignments) const - -> _new_statement_t> + -> _new_statement_t<_check, update_list_t> { static_assert(sizeof...(Assignments), "at least one assignment expression required in set()"); - return _set_impl(assignments...); + static_assert(_check::value, "at least one argument is not an assignment in set()"); + + return _set_impl(_check{}, assignments...); } template auto dynamic_set(Assignments... assignments) const - -> _new_statement_t> + -> _new_statement_t<_check, update_list_t<_database_t, Assignments...>> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_set() must not be called in a static statement"); - return _set_impl<_database_t>(assignments...); + static_assert(_check::value, "at least one argument is not an assignment in set()"); + + return _set_impl<_database_t>(_check{}, assignments...); } private: template - auto _set_impl(Assignments... assignments) const - -> _new_statement_t> + auto _set_impl(const std::false_type&, Assignments... assignments) const + -> bad_statement; + + template + auto _set_impl(const std::true_type&, Assignments... assignments) const + -> _new_statement_t> { - static_assert(detail::all_t::value...>::value, "at least one argument is not an assignment in set()"); static_assert(not detail::has_duplicates...>::value, "at least one duplicate column detected in set()"); - static_assert(detail::none_t>::value...>::value, "at least one assignment is prohibited by its column definition in set()"); + static_assert(logic::none_t>::value...>::value, "at least one assignment is prohibited by its column definition in set()"); using _column_required_tables = detail::make_joined_set_t>...>; static_assert(sizeof...(Assignments) ? (_column_required_tables::size::value == 1) : true, "set() contains assignments for columns from more than one table"); @@ -209,6 +235,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = update_list_data_t; static Context& _(const T& t, Context& context) diff --git a/include/sqlpp11/using.h b/include/sqlpp11/using.h index c704dfc4..10018e14 100644 --- a/include/sqlpp11/using.h +++ b/include/sqlpp11/using.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -58,16 +58,10 @@ namespace sqlpp struct using_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits; + using _nodes = detail::type_vector; using _is_dynamic = is_database; - static_assert(_is_dynamic::value or sizeof...(Tables), "at least one table argument required in using()"); - - static_assert(not detail::has_duplicates::value, "at least one duplicate argument detected in using()"); - - static_assert(detail::all_t::value...>::value, "at least one argument is not an table in using()"); - // Data using _data_t = using_data_t; @@ -80,8 +74,10 @@ namespace sqlpp { static_assert(_is_dynamic::value, "add must not be called for static using()"); static_assert(is_table_t
::value, "invalid table argument in add()"); + using _serialize_check = sqlpp::serialize_check_t; + _serialize_check::_(); - using ok = detail::all_t<_is_dynamic::value, is_table_t
::value>; + using ok = logic::all_t<_is_dynamic::value, is_table_t
::value, _serialize_check::type::value>; _add_impl(table, ok()); // dispatch to prevent compile messages after the static_assert } @@ -100,9 +96,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = using_data_t; @@ -115,13 +111,9 @@ namespace sqlpp { return t.using_; } - }; - // Additional methods for the statement - template - struct _methods_t - { - static void _check_consistency() {} + // FIXME: Maybe check for unused tables, similar to from + using _consistency_check = consistent_t; }; }; @@ -129,7 +121,7 @@ namespace sqlpp struct no_using_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits<>; + using _nodes = detail::type_vector<>; // Data using _data_t = no_data_t; @@ -141,9 +133,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = no_data_t; @@ -156,31 +148,51 @@ namespace sqlpp { return t.no_using; } - }; - template - struct _methods_t - { using _database_t = typename Policies::_database_t; - template - using _new_statement_t = new_statement; - static void _check_consistency() {} + template + using _check = logic::all_t::value...>; + + template + using _new_statement_t = new_statement_t; + + using _consistency_check = consistent_t; template auto using_(Args... args) const - -> _new_statement_t> + -> _new_statement_t<_check, using_t> { - return { static_cast&>(*this), using_data_t{args...} }; + static_assert(not detail::has_duplicates::value, "at least one duplicate argument detected in using()"); + static_assert(sizeof...(Args), "at least one table required in using()"); + static_assert(_check::value, "at least one argument is not an table in using()"); + + return { _using_impl(_check{}, args...) }; } template auto dynamic_using(Args... args) const - -> _new_statement_t> + -> _new_statement_t<_check, using_t<_database_t, Args...>> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_using must not be called in a static statement"); - return { static_cast&>(*this), using_data_t<_database_t, Args...>{args...} }; + static_assert(_check::value, "at least one argument is not an table in using()"); + + return { _using_impl<_database_t>(_check{}, args...) }; } + + private: + template + auto _using_impl(const std::false_type&, Args... args) const + -> bad_statement; + + template + auto _using_impl(const std::true_type&, Args... args) const + -> _new_statement_t> + { + static_assert(not detail::has_duplicates::value, "at least one duplicate argument detected in using()"); + + return { static_cast&>(*this), using_data_t{args...} }; + } }; }; @@ -188,6 +200,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = using_data_t; static Context& _(const T& t, Context& context) diff --git a/include/sqlpp11/value_or_null.h b/include/sqlpp11/value_or_null.h index 68ce8c83..ab8fb6a7 100644 --- a/include/sqlpp11/value_or_null.h +++ b/include/sqlpp11/value_or_null.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -51,7 +51,7 @@ namespace sqlpp using _cpp_value_type = typename ValueType::_cpp_value_type; using _traits = make_traits; - using _recursive_traits = make_recursive_traits<>; + using _nodes = detail::type_vector<>; value_or_null_t(_cpp_value_type value): _value(value), diff --git a/include/sqlpp11/value_type.h b/include/sqlpp11/value_type.h index 2fa3bee1..ab7f1e1f 100644 --- a/include/sqlpp11/value_type.h +++ b/include/sqlpp11/value_type.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/value_type_fwd.h b/include/sqlpp11/value_type_fwd.h index 805e5662..30d824d4 100644 --- a/include/sqlpp11/value_type_fwd.h +++ b/include/sqlpp11/value_type_fwd.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/verbatim.h b/include/sqlpp11/verbatim.h index d1b43006..4ea31b51 100644 --- a/include/sqlpp11/verbatim.h +++ b/include/sqlpp11/verbatim.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -27,6 +27,7 @@ #ifndef SQLPP_VERBATIM_H #define SQLPP_VERBATIM_H +#include #include #include @@ -38,10 +39,8 @@ namespace sqlpp public alias_operators> { using _traits = make_traits; - struct _recursive_traits : public make_recursive_traits<> - { - using _tags = detail::type_set; // since we do not know what's going on inside the verbatim, we assume it can be null - }; + using _nodes = detail::type_vector<>; + using _can_be_null = std::true_type; // since we do not know what's going on inside the verbatim, we assume it can be null verbatim_t(std::string verbatim): _verbatim(verbatim) {} verbatim_t(const verbatim_t&) = default; @@ -56,6 +55,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = consistent_t; using T = verbatim_t; static Context& _(const T& t, Context& context) @@ -71,6 +71,11 @@ namespace sqlpp return { s }; } + inline auto verbatim(std::string s) -> verbatim_t + { + return { s }; + } + } #endif diff --git a/include/sqlpp11/verbatim_table.h b/include/sqlpp11/verbatim_table.h index fc53af7f..9247d3a6 100644 --- a/include/sqlpp11/verbatim_table.h +++ b/include/sqlpp11/verbatim_table.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -35,8 +35,10 @@ namespace sqlpp { struct unusable_pseudo_column_t { - struct _name_t + struct _alias_t { + static constexpr const char _literal[] = "pseudo_column"; + using _name_t = sqlpp::make_char_sequence; template struct _member_t { @@ -48,12 +50,13 @@ namespace sqlpp struct verbatim_table_t: public table_t { - struct _recursive_traits: public table_t::_recursive_traits - { - using _provided_outer_tables = detail::type_set; - }; + using _nodes = detail::type_vector<>; - struct _name_t {}; + struct _alias_t + { + static constexpr const char _literal[] = "verbatim_table"; // FIXME need to use alias for verbatim table + using _name_t = sqlpp::make_char_sequence; + }; verbatim_table_t(std::string representation): _representation(representation) @@ -72,6 +75,7 @@ namespace sqlpp template struct serializer_t { + using _serialize_check = consistent_t; using T = verbatim_table_t; static Context& _(const T& t, Context& context) diff --git a/include/sqlpp11/where.h b/include/sqlpp11/where.h index 7fb09551..e3828696 100644 --- a/include/sqlpp11/where.h +++ b/include/sqlpp11/where.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -27,12 +27,13 @@ #ifndef SQLPP_WHERE_H #define SQLPP_WHERE_H +#include #include #include #include #include #include -#include +#include namespace sqlpp { @@ -54,19 +55,26 @@ namespace sqlpp interpretable_list_t _dynamic_expressions; }; + struct assert_no_unknown_tables_in_where_t + { + using type = std::false_type; + + template + static void _() + { + static_assert(wrong_t::value, "at least one expression in where() requires a table which is otherwise not known in the statement"); + } + }; + // WHERE(EXPR) template struct where_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits; + using _nodes = detail::type_vector; using _is_dynamic = is_database; - static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in where()"); - static_assert(detail::none_t::value...>::value, "at least one argument is an assignment in where()"); - static_assert(detail::all_t::value...>::value, "at least one argument is not valid expression in where()"); - // Data using _data_t = where_data_t; @@ -86,8 +94,10 @@ namespace sqlpp static_assert(_is_dynamic::value, "where::add() can only be called for dynamic_where"); static_assert(is_expression_t::value, "invalid expression argument in where::add()"); static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables::value, "expression uses tables unknown to this statement in where::add()"); + using _serialize_check = sqlpp::serialize_check_t; + _serialize_check::_(); - using ok = detail::all_t<_is_dynamic::value, is_expression_t::value>; + using ok = logic::all_t<_is_dynamic::value, is_expression_t::value, _serialize_check::type::value>; _add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert } @@ -106,9 +116,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = where_data_t; @@ -121,13 +131,10 @@ namespace sqlpp { return t.where; } - }; - // Additional methods for the statement - template - struct _methods_t - { - static void _check_consistency() {} + using _consistency_check = typename std::conditional::value, + consistent_t, + assert_no_unknown_tables_in_where_t>::type; }; }; @@ -142,7 +149,7 @@ namespace sqlpp struct where_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits<>; + using _nodes = detail::type_vector<>; // Data using _data_t = where_data_t; @@ -154,9 +161,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = where_data_t; @@ -169,23 +176,29 @@ namespace sqlpp { return t.where; } - }; - // Additional methods for the statement - template - struct _methods_t - { - static void _check_consistency() {} + using _consistency_check = consistent_t; }; }; + struct assert_where_t + { + using type = std::false_type; + + template + static void _() + { + static_assert(wrong_t::value, "where expression required, e.g. where(true)"); + } + }; + // NO WHERE YET template struct no_where_t { using _traits = make_traits; - using _recursive_traits = make_recursive_traits<>; + using _nodes = detail::type_vector<>; // Data using _data_t = no_data_t; @@ -197,9 +210,9 @@ namespace sqlpp _data_t _data; }; - // Member template for adding the named member to a statement + // Base template to be inherited by the statement template - struct _member_t + struct _base_t { using _data_t = no_data_t; @@ -212,37 +225,57 @@ namespace sqlpp { return t.no_where; } - }; - // Additional methods for the statement - template - struct _methods_t - { using _database_t = typename Policies::_database_t; - template - using _new_statement_t = new_statement; - static void _check_consistency() - { - static constexpr bool _tables_provided = (Policies::_all_provided_tables::size::value > 0); - static constexpr bool _required = WhereRequired and _tables_provided; - static_assert(not _required, "where expression required, e.g. where(true)"); - } + template + using _check = logic::all_t::value...>; - template - auto where(Args... args) const - -> _new_statement_t> + template + using _new_statement_t = new_statement_t; + + using _consistency_check = typename std::conditional< + WhereRequired and (Policies::_all_provided_tables::size::value > 0), + assert_where_t, + consistent_t>::type; + + auto where(bool b) const + -> _new_statement_t> { - return { static_cast&>(*this), where_data_t{args...} }; + return { static_cast&>(*this), where_data_t{b} }; } - template - auto dynamic_where(Args... args) const - -> _new_statement_t> + template + auto where(Expressions... expressions) const + -> _new_statement_t<_check, where_t> { + static_assert(_check::value, "at least one argument is not an expression in where()"); + static_assert(sizeof...(Expressions), "at least one expression argument required in where()"); + + return _where_impl(_check{}, expressions...); + } + + template + auto dynamic_where(Expressions... expressions) const + -> _new_statement_t<_check, where_t<_database_t, Expressions...>> + { + static_assert(_check::value, "at least one argument is not an expression in where()"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_where must not be called in a static statement"); - return { static_cast&>(*this), where_data_t<_database_t, Args...>{args...} }; + return _where_impl<_database_t>(_check{}, expressions...); } + + private: + template + auto _where_impl(const std::false_type&, Expressions... expressions) const + -> bad_statement; + + template + auto _where_impl(const std::true_type&, Expressions... expressions) const + -> _new_statement_t> + { + return { static_cast&>(*this), where_data_t<_database_t, Expressions...>{expressions...} }; + } + }; }; @@ -250,6 +283,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = serialize_check_of; using T = where_data_t; static Context& _(const T& t, Context& context) @@ -268,6 +302,7 @@ namespace sqlpp template struct serializer_t> { + using _serialize_check = consistent_t; using T = where_data_t; static Context& _(const T& t, Context& context) @@ -278,6 +313,11 @@ namespace sqlpp } }; + template + auto where(T&&... t) -> decltype(statement_t>().where(std::forward(t)...)) + { + return statement_t>().where(std::forward(t)...); + } } #endif diff --git a/include/sqlpp11/with.h b/include/sqlpp11/with.h new file mode 100644 index 00000000..c2e0a725 --- /dev/null +++ b/include/sqlpp11/with.h @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2013-2015, Roland Bock + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SQLPP_WITH_H +#define SQLPP_WITH_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include + +namespace sqlpp +{ + template + struct with_data_t + { + using _is_recursive = logic::any_t; + + with_data_t(Expressions... expressions): + _expressions(expressions...) + {} + + with_data_t(const with_data_t&) = default; + with_data_t(with_data_t&&) = default; + with_data_t& operator=(const with_data_t&) = default; + with_data_t& operator=(with_data_t&&) = default; + ~with_data_t() = default; + + std::tuple _expressions; + }; + + template + struct with_t + { + using _traits = make_traits; + using _nodes = detail::type_vector<>; + using _provided_ctes = detail::make_joined_set_t...>; // WITH provides common table expressions + using _parameters = detail::type_vector_cat_t...>; + + using _is_dynamic = is_database; + + // Data + using _data_t = with_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + public: + _data_t _data; + }; + + // Base template to be inherited by the statement + template + struct _base_t + { + using _data_t = with_data_t; + + _impl_t with; + _impl_t& operator()() { return with; } + const _impl_t& operator()() const { return with; } + + template + static auto _get_member(T t) -> decltype(t.with) + { + return t.with; + } + + // FIXME: Need real checks here + using _consistency_check = consistent_t; + }; + }; + + + struct no_with_t + { + using _traits = make_traits; + using _nodes = detail::type_vector<>; + + // Data + using _data_t = no_data_t; + + // Member implementation with data and methods + template + struct _impl_t + { + _data_t _data; + }; + + // Base template to be inherited by the statement + template + struct _base_t + { + using _data_t = no_data_t; + + _impl_t no_with; + _impl_t& operator()() { return no_with; } + const _impl_t& operator()() const { return no_with; } + + template + static auto _get_member(T t) -> decltype(t.no_with) + { + return t.no_with; + } + + using _consistency_check = consistent_t; + + }; + }; + + template + struct blank_with_t + { + with_data_t _data; + + template + auto operator()(Statement statement) + -> new_statement_t> + { + // FIXME need checks here + // check that no cte refers to any of the ctes to the right + return { statement, _data }; + } + }; + + // Interpreters + template + struct serializer_t> + { + using _serialize_check = serialize_check_of; + using T = with_data_t; + + static Context& _(const T& t, Context& context) + { + // FIXME: If there is a recursive CTE, add a "RECURSIVE" here + context << " WITH "; + if (T::_is_recursive::value) + context << "RECURSIVE "; + interpret_tuple(t._expressions, ',', context); + context << ' '; + return context; + } + }; + + template + auto with(Expressions... cte) + -> blank_with_t + { + static_assert(logic::all_t::value...>::value, "at least one expression in with is not a common table expression"); + static_assert(logic::none_t::value...>::value, "at least one expression in with is an incomplete common table expression"); + return { {cte...} }; + } +} + +#endif diff --git a/include/sqlpp11/wrap_operand.h b/include/sqlpp11/wrap_operand.h index 7be274c2..f8a4fc77 100644 --- a/include/sqlpp11/wrap_operand.h +++ b/include/sqlpp11/wrap_operand.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -43,7 +43,7 @@ namespace sqlpp struct boolean_operand: public alias_operators { using _traits = make_traits; - using _recursive_traits = make_recursive_traits<>; + using _nodes = detail::type_vector<>; using _value_t = bool; @@ -69,6 +69,7 @@ namespace sqlpp template struct serializer_t { + using _serialize_check = consistent_t; using Operand = boolean_operand; static Context& _(const Operand& t, Context& context) @@ -81,7 +82,7 @@ namespace sqlpp struct integral_operand: public alias_operators { using _traits = make_traits; - using _recursive_traits = make_recursive_traits<>; + using _nodes = detail::type_vector<>; using _value_t = int64_t; @@ -107,6 +108,7 @@ namespace sqlpp template struct serializer_t { + using _serialize_check = consistent_t; using Operand = integral_operand; static Context& _(const Operand& t, Context& context) @@ -120,7 +122,7 @@ namespace sqlpp struct floating_point_operand: public alias_operators { using _traits = make_traits; - using _recursive_traits = make_recursive_traits<>; + using _nodes = detail::type_vector<>; using _value_t = double; @@ -146,6 +148,7 @@ namespace sqlpp template struct serializer_t { + using _serialize_check = consistent_t; using Operand = floating_point_operand; static Context& _(const Operand& t, Context& context) @@ -158,7 +161,7 @@ namespace sqlpp struct text_operand: public alias_operators { using _traits = make_traits; - using _recursive_traits = make_recursive_traits<>; + using _nodes = detail::type_vector<>; using _value_t = std::string; @@ -184,6 +187,7 @@ namespace sqlpp template struct serializer_t { + using _serialize_check = consistent_t; using Operand = text_operand; static Context& _(const Operand& t, Context& context) diff --git a/include/sqlpp11/wrap_operand_fwd.h b/include/sqlpp11/wrap_operand_fwd.h index f7f60def..633df0ac 100644 --- a/include/sqlpp11/wrap_operand_fwd.h +++ b/include/sqlpp11/wrap_operand_fwd.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/wrong.h b/include/sqlpp11/wrong.h index 9249673e..cfaf1d32 100644 --- a/include/sqlpp11/wrong.h +++ b/include/sqlpp11/wrong.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/scripts/ddl2cpp b/scripts/ddl2cpp index dd09cf86..80e0063b 100755 --- a/scripts/ddl2cpp +++ b/scripts/ddl2cpp @@ -1,7 +1,7 @@ #!/usr/bin/env python ## - # Copyright (c) 2013-2014, Roland Bock + # Copyright (c) 2013-2015, Roland Bock # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, @@ -118,6 +118,7 @@ print('#define '+get_include_guard_name(namespace, pathToHeader), file=header) print('', file=header) print('#include <' + INCLUDE + '/table.h>', file=header) print('#include <' + INCLUDE + '/column_types.h>', file=header) +print('#include <' + INCLUDE + '/char_sequence.h>', file=header) print('', file=header) print('namespace ' + namespace, file=header) print('{', file=header) @@ -143,9 +144,10 @@ for tableCreation in tableCreations: columnCanBeNull = not column.notNull print(' struct ' + columnClass, file=header) print(' {', file=header) - print(' struct _name_t', file=header) + print(' struct _alias_t', file=header) print(' {', file=header) - print(' static constexpr const char* _get_name() { return "' + sqlColumnName + '"; }', file=header) + print(' static constexpr const char _literal[] = "' + sqlColumnName + '";', file=header) + print(' using _name_t = sqlpp::make_char_sequence;', file=header) print(' template', file=header) print(' struct _member_t', file=header) print(' {', file=header) @@ -154,7 +156,6 @@ for tableCreation in tableCreations: print(' const T& operator()() const { return ' + columnMember + '; }', file=header) print(' };', file=header) print(' };', file=header) - #print(sqlColumnType) traitslist = [NAMESPACE + '::' + types[sqlColumnType]]; requireInsert = True if column.hasAutoValue: @@ -175,9 +176,10 @@ for tableCreation in tableCreations: print(' struct ' + tableClass + ': ' + NAMESPACE + '::table_t<' + tableTemplateParameters + '>', file=header) print(' {', file=header) - print(' struct _name_t', file=header) + print(' struct _alias_t', file=header) print(' {', file=header) - print(' static constexpr const char* _get_name() { return "' + sqlTableName + '"; }', file=header) + print(' static constexpr const char _literal[] = "' + sqlTableName + '";', file=header) + print(' using _name_t = sqlpp::make_char_sequence;', file=header) print(' template', file=header) print(' struct _member_t', file=header) print(' {', file=header) diff --git a/test_constraints/CMakeLists.txt b/test_constraints/CMakeLists.txt index 2281b371..20e699d9 100644 --- a/test_constraints/CMakeLists.txt +++ b/test_constraints/CMakeLists.txt @@ -1,4 +1,4 @@ -include_directories("${CMAKE_SOURCE_DIR}/tests") +include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../tests") add_custom_target(test_sqlpp_constraints COMMAND true) @@ -24,8 +24,8 @@ function(test_constraint name pattern) endfunction(test_constraint) -test_constraint(count_of_count "requires an expression as argument") -test_constraint(max_of_max "requires an expression as argument") +test_constraint(count_of_count "count() cannot be used on an aggregate function") +test_constraint(max_of_max "max() cannot be used on an aggregate function") test_constraint(no_conversion_operator_if_null_not_trivial "int i = row.alpha") test_constraint(require_insert "required column is missing") test_constraint(must_not_insert "one assignment is prohibited") diff --git a/test_constraints/count_of_count.cpp b/test_constraints/count_of_count.cpp index 95f089db..11fdf455 100644 --- a/test_constraints/count_of_count.cpp +++ b/test_constraints/count_of_count.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/test_constraints/max_of_max.cpp b/test_constraints/max_of_max.cpp index 96483e9b..0cf08f56 100644 --- a/test_constraints/max_of_max.cpp +++ b/test_constraints/max_of_max.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/test_constraints/must_not_insert.cpp b/test_constraints/must_not_insert.cpp index be6d4ee1..262eb0ea 100644 --- a/test_constraints/must_not_insert.cpp +++ b/test_constraints/must_not_insert.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/test_constraints/must_not_update.cpp b/test_constraints/must_not_update.cpp index 42f9ac04..8e8a4ef2 100644 --- a/test_constraints/must_not_update.cpp +++ b/test_constraints/must_not_update.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/test_constraints/no_conversion_operator_if_null_not_trivial.cpp b/test_constraints/no_conversion_operator_if_null_not_trivial.cpp index 7b995626..64952b80 100644 --- a/test_constraints/no_conversion_operator_if_null_not_trivial.cpp +++ b/test_constraints/no_conversion_operator_if_null_not_trivial.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/test_constraints/require_insert.cpp b/test_constraints/require_insert.cpp index 6fc641ac..701cb699 100644 --- a/test_constraints/require_insert.cpp +++ b/test_constraints/require_insert.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/tests/BooleanExpressionTest.cpp b/tests/BooleanExpressionTest.cpp index 6f0892b9..4e1d49c9 100644 --- a/tests/BooleanExpressionTest.cpp +++ b/tests/BooleanExpressionTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 022a55ab..4461ce0d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -7,6 +7,7 @@ macro (build_and_run arg) endmacro () build_and_run(BooleanExpressionTest) +build_and_run(CustomQueryTest) build_and_run(InterpretTest) build_and_run(InsertTest) build_and_run(RemoveTest) @@ -17,6 +18,8 @@ build_and_run(FunctionTest) build_and_run(PreparedTest) build_and_run(Minimalistic) build_and_run(ResultTest) +build_and_run(UnionTest) +build_and_run(WithTest) # if you want to use the generator, you can do something like this: #find_package(PythonInterp REQUIRED) diff --git a/tests/CustomQueryTest.cpp b/tests/CustomQueryTest.cpp new file mode 100644 index 00000000..2d926cc0 --- /dev/null +++ b/tests/CustomQueryTest.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2013-2015, Roland Bock + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "Sample.h" +#include "MockDb.h" +#include +#include + +MockDb db = {}; +MockDb::_serializer_context_t printer; + +int main() +{ + test::TabFoo f; + test::TabBar t; + + // A void custom query + printer.reset(); + auto x = custom_query(sqlpp::verbatim("PRAGMA writeable_schema = "), true); + std::cerr << serialize(x, printer).str() << std::endl; + db(x); + + // Syntactically, it is possible to use this void query as a prepared statement, too, not sure, whether this makes sense very often... + db(db.prepare(x)); + + // A prepared custom select + // The return type of the custom query is determined from the first argument which does have a return type, in this case the select + auto p = db.prepare(custom_query(select(all_of(t)).from(t), where(t.alpha > sqlpp::parameter(t.alpha)))); + p.params.alpha = 8; + for (const auto& row : db(p)) + { + std::cerr << row.alpha << std::endl; + } + + // A custom (select ... into) with adjusted return type + // The first argument with a return type is the select, but the custom query is really an insert. Thus, we tell it so. + printer.reset(); + auto c = custom_query(select(all_of(t)).from(t), into(f)).with_result_type_of(insert_into(f)); + std::cerr << serialize(c, printer).str() << std::endl; + auto i = db(c); + static_assert(std::is_integral::value, "insert yields an integral value"); + + return 0; +} diff --git a/tests/FunctionTest.cpp b/tests/FunctionTest.cpp index bde10db5..ba9e166f 100644 --- a/tests/FunctionTest.cpp +++ b/tests/FunctionTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/tests/InsertTest.cpp b/tests/InsertTest.cpp index a8dfe96c..99a2d0c5 100644 --- a/tests/InsertTest.cpp +++ b/tests/InsertTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/tests/InterpretTest.cpp b/tests/InterpretTest.cpp index c3813a24..3aa3487c 100644 --- a/tests/InterpretTest.cpp +++ b/tests/InterpretTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/tests/MockDb.h b/tests/MockDb.h index 2db57106..7516dd77 100644 --- a/tests/MockDb.h +++ b/tests/MockDb.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -27,6 +27,7 @@ #define SQLPP_MOCK_DB_H #include +#include #include #include @@ -107,16 +108,41 @@ struct MockDbT: public sqlpp::connection // Directly executed statements start here template - auto operator() (const T& t) -> decltype(t._run(*this)) + auto _run(const T& t, const std::true_type&) -> decltype(t._run(*this)) { return t._run(*this); } + template + auto _run(const T& t, const std::false_type&) -> decltype(t._run(*this)); + + template + auto operator() (const T& t) -> decltype(t._run(*this)) + { + sqlpp::run_check_t::_(); + sqlpp::serialize_check_t<_serializer_context_t, T>::_(); + using _ok = sqlpp::logic::all_t::type::value, + sqlpp::serialize_check_t<_serializer_context_t, T>::type::value>; + return _run(t, _ok{}); + } + + void execute(const std::string& command); + + template::value, void>::type> + void execute(const Statement& x) + { + _serializer_context_t context; + ::sqlpp::serialize(x, context); + std::cout << "Running execute call with\n" << context.str() << std::endl; + } + template size_t insert(const Insert& x) { _serializer_context_t context; ::sqlpp::serialize(x, context); + std::cout << "Running insert call with\n" << context.str() << std::endl; return 0; } @@ -125,6 +151,7 @@ struct MockDbT: public sqlpp::connection { _serializer_context_t context; ::sqlpp::serialize(x, context); + std::cout << "Running update call with\n" << context.str() << std::endl; return 0; } @@ -133,6 +160,7 @@ struct MockDbT: public sqlpp::connection { _serializer_context_t context; ::sqlpp::serialize(x, context); + std::cout << "Running remove call with\n" << context.str() << std::endl; return 0; } @@ -141,6 +169,7 @@ struct MockDbT: public sqlpp::connection { _serializer_context_t context; ::sqlpp::serialize(x, context); + std::cout << "Running select call with\n" << context.str() << std::endl; return {}; } @@ -148,20 +177,48 @@ struct MockDbT: public sqlpp::connection using _prepared_statement_t = std::nullptr_t; template - auto prepare(const T& t) -> decltype(t._prepare(*this)) + auto _prepare(const T& t, const std::true_type&) -> decltype(t._prepare(*this)) { return t._prepare(*this); } + template + auto _prepare(const T& t, const std::false_type&) -> decltype(t._prepare(*this)); + + template + auto prepare(const T& t) -> decltype(t._prepare(*this)) + { + sqlpp::prepare_check_t::_(); + sqlpp::serialize_check_t<_serializer_context_t, T>::_(); + using _ok = sqlpp::logic::all_t::type::value, + sqlpp::serialize_check_t<_serializer_context_t, T>::type::value>; + return _prepare(t, _ok{}); + } + + + template + _prepared_statement_t prepare_execute(Statement& x) + { + _serializer_context_t context; + ::sqlpp::serialize(x, context); + std::cout << "Running prepare execute call with\n" << context.str() << std::endl; + return nullptr; + } template _prepared_statement_t prepare_insert(Insert& x) { _serializer_context_t context; ::sqlpp::serialize(x, context); + std::cout << "Running prepare insert call with\n" << context.str() << std::endl; return nullptr; } + template + void run_prepared_execute(const PreparedExecute& x) + { + } + template size_t run_prepared_insert(const PreparedInsert& x) { @@ -173,6 +230,7 @@ struct MockDbT: public sqlpp::connection { _serializer_context_t context; ::sqlpp::serialize(x, context); + std::cout << "Running prepare select call with\n" << context.str() << std::endl; return nullptr; } diff --git a/tests/PreparedTest.cpp b/tests/PreparedTest.cpp index 27a5832e..82c7fe4e 100644 --- a/tests/PreparedTest.cpp +++ b/tests/PreparedTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -40,47 +40,55 @@ int main() // empty parameter lists { - using T = sqlpp::parameters_of; - static_assert(std::is_same>::value, "type requirement"); + using P = sqlpp::make_parameter_list_t; + static_assert(P::size::value == 0, "type requirement"); } // single parameter { - using T = sqlpp::parameters_of; - static_assert(std::is_same>::value, "type requirement"); + using P = sqlpp::make_parameter_list_t; + static_assert(P::size::value == 1, "type requirement"); + auto p = P{}; + p.alpha = 7; } // single parameter { - using T = sqlpp::parameters_of; - static_assert(std::is_same>::value, "type requirement"); + using P = sqlpp::make_parameter_list_t; + static_assert(P::size::value == 1, "type requirement"); + auto p = P{}; + p.beta = "cheesecake"; } // single parameter in expression { - using T = sqlpp::parameters_of; - static_assert(std::is_same>::value, "type requirement"); + using P = sqlpp::make_parameter_list_t; + static_assert(P::size::value == 1, "type requirement"); + auto p = P{}; + p.alpha = 7; } // single parameter in larger expression { - using T = sqlpp::parameters_of; - static_assert(std::is_same>::value, "type requirement"); + using P = sqlpp::make_parameter_list_t; + static_assert(P::size::value == 1, "type requirement"); + auto p = P{}; + p.alpha = 7; } // three parameters in expression { - using T = sqlpp::parameters_of; - static_assert(std::tuple_size::value == 3, "type requirement"); - static_assert(std::is_same>::value, "type requirement"); + using P = sqlpp::parameters_of; + // FIXME: make some test, that does not depend on detail namespace, but still checks the correct order of the parameters + static_assert(std::is_same>::value, "type requirement"); } // OK, fine, now create a named parameter list from an expression { using Exp = decltype((t.beta.like(parameter(t.beta)) and t.alpha == parameter(t.alpha)) or t.gamma != parameter(t.gamma)); - using T = sqlpp::make_parameter_list_t; - T npl; + using P = sqlpp::make_parameter_list_t; + P npl; static_assert(std::is_same>, decltype(npl.alpha)>::value, "type requirement"); static_assert(std::is_same>, decltype(npl.beta)>::value, "type requirement"); static_assert(std::is_same>, decltype(npl.gamma)>::value, "type requirement"); @@ -93,8 +101,8 @@ int main() p.params.alpha = 7; p.params.alpha = sqlpp::tvin(0); using S = decltype(s); - using T = sqlpp::make_parameter_list_t; - T npl; + using P = sqlpp::make_parameter_list_t; + P npl; static_assert(std::is_same>, decltype(npl.alpha)>::value, "type requirement"); static_assert(std::is_same>, decltype(npl.beta)>::value, "type requirement"); diff --git a/tests/RemoveTest.cpp b/tests/RemoveTest.cpp index 0ea34df1..a89ee285 100644 --- a/tests/RemoveTest.cpp +++ b/tests/RemoveTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/tests/ResultTest.cpp b/tests/ResultTest.cpp index 21ca2f82..1763868f 100644 --- a/tests/ResultTest.cpp +++ b/tests/ResultTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -47,7 +47,7 @@ int main() { static_assert(sqlpp::can_be_null_t::value, "row.alpha can be null"); static_assert(sqlpp::null_is_trivial_value_t::value, "row.alpha interprets null_is_trivial"); - static_assert(std::is_member_function_pointer::value, "Yikes"); + static_assert(std::is_same::value, "Yikes"); using T = sqlpp::wrap_operand_t; static_assert(sqlpp::can_be_null_t::value, "row.alpha can be null"); static_assert(sqlpp::is_result_field_t::value, "result_fields are not wrapped"); diff --git a/tests/Sample.h b/tests/Sample.h index 5f1bf1de..2fa909e5 100644 --- a/tests/Sample.h +++ b/tests/Sample.h @@ -3,6 +3,7 @@ #include #include +#include namespace test { @@ -10,9 +11,10 @@ namespace test { struct Delta { - struct _name_t + struct _alias_t { - static constexpr const char* _get_name() { return "delta"; } + static constexpr const char _literal[] = "delta"; + using _name_t = sqlpp::make_char_sequence; template struct _member_t { @@ -25,9 +27,10 @@ namespace test }; struct Epsilon { - struct _name_t + struct _alias_t { - static constexpr const char* _get_name() { return "epsilon"; } + static constexpr const char _literal[] = "epsilon"; + using _name_t = sqlpp::make_char_sequence; template struct _member_t { @@ -40,9 +43,10 @@ namespace test }; struct Omega { - struct _name_t + struct _alias_t { - static constexpr const char* _get_name() { return "omega"; } + static constexpr const char _literal[] = "omega"; + using _name_t = sqlpp::make_char_sequence; template struct _member_t { @@ -60,9 +64,10 @@ namespace test TabFoo_::Epsilon, TabFoo_::Omega> { - struct _name_t + struct _alias_t { - static constexpr const char* _get_name() { return "tab_foo"; } + static constexpr const char _literal[] = "tab_foo"; + using _name_t = sqlpp::make_char_sequence; template struct _member_t { @@ -76,9 +81,10 @@ namespace test { struct Alpha { - struct _name_t + struct _alias_t { - static constexpr const char* _get_name() { return "alpha"; } + static constexpr const char _literal[] = "alpha"; + using _name_t = sqlpp::make_char_sequence; template struct _member_t { @@ -91,9 +97,10 @@ namespace test }; struct Beta { - struct _name_t + struct _alias_t { - static constexpr const char* _get_name() { return "beta"; } + static constexpr const char _literal[] = "beta"; + using _name_t = sqlpp::make_char_sequence; template struct _member_t { @@ -106,9 +113,10 @@ namespace test }; struct Gamma { - struct _name_t + struct _alias_t { - static constexpr const char* _get_name() { return "gamma"; } + static constexpr const char _literal[] = "gamma"; + using _name_t = sqlpp::make_char_sequence; template struct _member_t { @@ -121,9 +129,10 @@ namespace test }; struct Delta { - struct _name_t + struct _alias_t { - static constexpr const char* _get_name() { return "delta"; } + static constexpr const char _literal[] = "delta"; + using _name_t = sqlpp::make_char_sequence; template struct _member_t { @@ -142,9 +151,10 @@ namespace test TabBar_::Gamma, TabBar_::Delta> { - struct _name_t + struct _alias_t { - static constexpr const char* _get_name() { return "tab_bar"; } + static constexpr const char _literal[] = "tab_bar"; + using _name_t = sqlpp::make_char_sequence; template struct _member_t { diff --git a/tests/SelectTest.cpp b/tests/SelectTest.cpp index bbf9a3e5..ba5f9bec 100644 --- a/tests/SelectTest.cpp +++ b/tests/SelectTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -36,12 +36,23 @@ MockDb db = {}; MockDb::_serializer_context_t printer; +template +int64_t getColumn(const Column& column) +{ + auto result = db(select(column.as(sqlpp::alias::a)).from(column.table()).where(true)); + if (not result.empty()) + return result.front().a; + else + return 0; +} + int main() { test::TabFoo f; test::TabBar t; - sqlpp::select(t.alpha).flags(sqlpp::all).from(t); + getColumn(t.alpha); + for (const auto& row : db(select(all_of(t)).from(t).where(true))) { int64_t a = row.alpha; diff --git a/tests/SelectTypeTest.cpp b/tests/SelectTypeTest.cpp index b59496ee..2c599d51 100644 --- a/tests/SelectTypeTest.cpp +++ b/tests/SelectTypeTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, Roland Bock + * Copyright (c) 2013-2015, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -300,7 +300,7 @@ int main() multi_column(all_of(t)).as(alias::right), // index 8 (including 8, 9, 10, 11) t.alpha.as(alias::a) // index 12 ).from(t).where(true)); // next index is 13 - using ResultRow = typename Select::_result_methods_t::template _result_row_t; + using ResultRow = typename Select::_result_methods_t