diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index d101fdf2..d40ff72b 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -58,8 +58,8 @@ namespace sqlpp > struct select_helper_t { - static_assert(is_noop_t::value or sqlpp::is_select_column_list_t::value, "Yikes"); - static_assert(is_noop_t::value or sqlpp::is_from_t::value, "Yikes"); + static_assert(is_noop_t::value or sqlpp::is_select_column_list_t::value, "column list of select is neither naught nor a valid column list"); + static_assert(is_noop_t::value or sqlpp::is_from_t::value, "from() part of select is neither naught nor a valid from()"); using _value_type = typename std::conditional< sqlpp::is_from_t::value, typename ColumnList::_value_type, @@ -497,6 +497,9 @@ namespace sqlpp template struct can_run_t { + static_assert(column_list::_table_set::template is_subset_t<_from_t::_table_set>::value + subset_of_t sollte ein eigenes template sein, das macht so etwas wie obiges sicher einfacher lesbar + also: use any and all instead of and_t and or_t //static_assert(is_where_t::value, "cannot select select without having a where condition, use .where(true) to remove all rows"); //static_assert(not vendor::is_noop::value, "cannot run select without having selected anything"); //static_assert(is_from_t::value, "cannot run select without a from()"); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 8d04a9e3..350602ec 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -11,6 +11,7 @@ build_and_run(InsertTest) build_and_run(RemoveTest) build_and_run(UpdateTest) build_and_run(SelectTest) +build_and_run(SelectTypeTest) build_and_run(FunctionTest) build_and_run(PreparedTest) diff --git a/tests/RemoveTest.cpp b/tests/RemoveTest.cpp index 21dd4108..48485886 100644 --- a/tests/RemoveTest.cpp +++ b/tests/RemoveTest.cpp @@ -64,5 +64,7 @@ int main() r.add_where(t.beta != "transparent"); serialize(r, printer).str(); + db(r); + return 0; } diff --git a/tests/SelectTest.cpp b/tests/SelectTest.cpp index fbe41a62..194cd800 100644 --- a/tests/SelectTest.cpp +++ b/tests/SelectTest.cpp @@ -49,328 +49,26 @@ int main() test::TabFoo f; test::TabBar t; - // Test a table - { - using T = decltype(t); - static_assert(not sqlpp::is_numeric_t::value, "type requirement"); - static_assert(not sqlpp::is_integral_t::value, "type requirement"); - static_assert(not sqlpp::is_floating_point_t::value, "type requirement"); - static_assert(not sqlpp::is_expression_t::value, "type requirement"); - static_assert(not sqlpp::is_named_expression_t::value, "type requirement"); - static_assert(not sqlpp::require_insert_t::value, "type requirement"); - static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); - static_assert(not sqlpp::must_not_update_t::value, "type requirement"); - static_assert(not sqlpp::is_boolean_t::value, "type requirement"); - static_assert(not sqlpp::is_text_t::value, "type requirement"); - static_assert(not sqlpp::is_alias_t::value, "type requirement"); - static_assert(sqlpp::is_table_t::value, "type requirement"); - static_assert(sqlpp::is_regular::value, "type requirement"); - } - - // Test an alias of table - { - using T = decltype(t.as(alias::a)); - static_assert(not sqlpp::is_numeric_t::value, "type requirement"); - static_assert(not sqlpp::is_integral_t::value, "type requirement"); - static_assert(not sqlpp::is_floating_point_t::value, "type requirement"); - static_assert(not sqlpp::is_expression_t::value, "type requirement"); - static_assert(not sqlpp::is_named_expression_t::value, "type requirement"); - static_assert(not sqlpp::require_insert_t::value, "type requirement"); - static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); - static_assert(not sqlpp::must_not_update_t::value, "type requirement"); - static_assert(not sqlpp::is_boolean_t::value, "type requirement"); - static_assert(not sqlpp::is_text_t::value, "type requirement"); - static_assert(sqlpp::is_alias_t::value, "type requirement"); - static_assert(sqlpp::is_table_t::value, "type requirement"); - static_assert(sqlpp::is_regular::value, "type requirement"); - } - - // Test an integral column of an alias of table - { - using T = decltype(t.as(alias::a).alpha); - static_assert(sqlpp::is_numeric_t::value, "type requirement"); - static_assert(sqlpp::is_integral_t::value, "type requirement"); - static_assert(not sqlpp::is_floating_point_t::value, "type requirement"); - static_assert(sqlpp::is_expression_t::value, "type requirement"); - static_assert(sqlpp::is_named_expression_t::value, "type requirement"); - static_assert(not sqlpp::require_insert_t::value, "type requirement"); - static_assert(sqlpp::must_not_insert_t::value, "type requirement"); - static_assert(sqlpp::must_not_update_t::value, "type requirement"); - static_assert(not sqlpp::is_boolean_t::value, "type requirement"); - static_assert(not sqlpp::is_text_t::value, "type requirement"); - static_assert(not sqlpp::is_alias_t::value, "type requirement"); - static_assert(not sqlpp::is_table_t::value, "type requirement"); - static_assert(sqlpp::is_regular::value, "type requirement"); - } - - - // Test an integral table column - { - using T = decltype(t.alpha); - static_assert(sqlpp::is_numeric_t::value, "type requirement"); - static_assert(sqlpp::is_integral_t::value, "type requirement"); - static_assert(not sqlpp::is_floating_point_t::value, "type requirement"); - static_assert(sqlpp::is_expression_t::value, "type requirement"); - static_assert(sqlpp::is_named_expression_t::value, "type requirement"); - static_assert(not sqlpp::require_insert_t::value, "type requirement"); - static_assert(sqlpp::must_not_insert_t::value, "type requirement"); - static_assert(sqlpp::must_not_update_t::value, "type requirement"); - static_assert(not sqlpp::is_boolean_t::value, "type requirement"); - static_assert(not sqlpp::is_text_t::value, "type requirement"); - static_assert(not sqlpp::is_alias_t::value, "type requirement"); - static_assert(not sqlpp::is_table_t::value, "type requirement"); - static_assert(sqlpp::is_regular::value, "type requirement"); - } - - // Test a floating point table column - { - using T = decltype(f.omega); - static_assert(sqlpp::is_numeric_t::value, "type requirement"); - static_assert(not sqlpp::is_integral_t::value, "type requirement"); - static_assert(sqlpp::is_floating_point_t::value, "type requirement"); - static_assert(sqlpp::is_expression_t::value, "type requirement"); - static_assert(sqlpp::is_named_expression_t::value, "type requirement"); - static_assert(not sqlpp::require_insert_t::value, "type requirement"); - static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); - static_assert(not sqlpp::must_not_update_t::value, "type requirement"); - static_assert(not sqlpp::is_boolean_t::value, "type requirement"); - static_assert(not sqlpp::is_text_t::value, "type requirement"); - static_assert(not sqlpp::is_alias_t::value, "type requirement"); - static_assert(not sqlpp::is_table_t::value, "type requirement"); - static_assert(sqlpp::is_regular::value, "type requirement"); - } - - // Test a an alias of a numeric table column - { - using T = decltype(t.alpha.as(alias::a)); - static_assert(sqlpp::is_numeric_t::value, "type requirement"); - static_assert(not sqlpp::is_expression_t::value, "type requirement"); - static_assert(sqlpp::is_named_expression_t::value, "type requirement"); - static_assert(not sqlpp::require_insert_t::value, "type requirement"); - static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); - static_assert(not sqlpp::must_not_update_t::value, "type requirement"); - static_assert(not sqlpp::is_boolean_t::value, "type requirement"); - static_assert(not sqlpp::is_text_t::value, "type requirement"); - static_assert(sqlpp::is_alias_t::value, "type requirement"); - static_assert(not sqlpp::is_table_t::value, "type requirement"); - static_assert(sqlpp::is_regular::value, "type requirement"); - } - - // Test a select of a single column without a from - { - using T = decltype(select(t.alpha)); // Hint: The current rule is pretty crude (a from is required), but certainly better than nothing - static_assert(not sqlpp::is_numeric_t::value, "type requirement"); - static_assert(not sqlpp::is_expression_t::value, "type requirement"); - static_assert(not sqlpp::is_named_expression_t::value, "type requirement"); - static_assert(not sqlpp::require_insert_t::value, "type requirement"); - static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); - static_assert(not sqlpp::must_not_update_t::value, "type requirement"); - static_assert(not sqlpp::is_boolean_t::value, "type requirement"); - static_assert(not sqlpp::is_text_t::value, "type requirement"); - static_assert(not sqlpp::is_alias_t::value, "type requirement"); - static_assert(not sqlpp::is_table_t::value, "type requirement"); - static_assert(sqlpp::is_regular::value, "type requirement"); - } - - // Test a select of a single numeric table column - { - using T = decltype(select(t.alpha).from(t)); - static_assert(sqlpp::is_select_column_list_t::value, "Must not be noop"); - static_assert(sqlpp::is_from_t::value, "Must not be noop"); - static_assert(sqlpp::is_numeric_t::value, "type requirement"); - static_assert(sqlpp::is_expression_t::value, "type requirement"); - static_assert(sqlpp::is_named_expression_t::value, "type requirement"); - static_assert(not sqlpp::require_insert_t::value, "type requirement"); - static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); - static_assert(not sqlpp::must_not_update_t::value, "type requirement"); - static_assert(not sqlpp::is_boolean_t::value, "type requirement"); - static_assert(not sqlpp::is_text_t::value, "type requirement"); - static_assert(not sqlpp::is_alias_t::value, "type requirement"); - static_assert(not sqlpp::is_table_t::value, "type requirement"); - static_assert(sqlpp::is_regular::value, "type requirement"); - } - - // Test a select of an alias of a single numeric table column - { - using T = decltype(select(t.alpha.as(alias::a)).from(t)); - static_assert(sqlpp::is_numeric_t::value, "type requirement"); - static_assert(sqlpp::is_expression_t::value, "type requirement"); - static_assert(sqlpp::is_named_expression_t::value, "type requirement"); - static_assert(not sqlpp::require_insert_t::value, "type requirement"); - static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); - static_assert(not sqlpp::must_not_update_t::value, "type requirement"); - static_assert(not sqlpp::is_boolean_t::value, "type requirement"); - static_assert(not sqlpp::is_text_t::value, "type requirement"); - static_assert(not sqlpp::is_alias_t::value, "type requirement"); - static_assert(not sqlpp::is_table_t::value, "type requirement"); - static_assert(sqlpp::is_regular::value, "type requirement"); - } - - // Test an alias of a select of a single numeric table column - { - using T = decltype(select(t.alpha).from(t).as(alias::b)); - static_assert(not sqlpp::is_numeric_t::value, "type requirement"); - static_assert(not sqlpp::is_expression_t::value, "type requirement"); - static_assert(not sqlpp::is_named_expression_t::value, "type requirement"); - static_assert(not sqlpp::require_insert_t::value, "type requirement"); - static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); - static_assert(not sqlpp::must_not_update_t::value, "type requirement"); - static_assert(not sqlpp::is_boolean_t::value, "red to not be boolean"); - static_assert(not sqlpp::is_text_t::value, "type requirement"); - static_assert(sqlpp::is_alias_t::value, "type requirement"); - static_assert(sqlpp::is_table_t::value, "type requirement"); - static_assert(sqlpp::is_regular::value, "type requirement"); - } - - // Test the column of an alias of a select of an alias of a single numeric table column - { - using T = decltype(select(t.alpha.as(alias::a)).from(t).as(alias::b)); - static_assert(not sqlpp::is_numeric_t::value, "type requirement"); - static_assert(not sqlpp::is_expression_t::value, "type requirement"); - static_assert(not sqlpp::is_named_expression_t::value, "type requirement"); - static_assert(not sqlpp::require_insert_t::value, "type requirement"); - static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); - static_assert(not sqlpp::must_not_update_t::value, "type requirement"); - static_assert(not sqlpp::is_boolean_t::value, "type requirement"); - static_assert(not sqlpp::is_text_t::value, "type requirement"); - static_assert(sqlpp::is_alias_t::value, "type requirement"); - static_assert(sqlpp::is_table_t::value, "type requirement"); - static_assert(sqlpp::is_regular::value, "type requirement"); - } - - // Test the column of an alias of a select of a single numeric table column - { - using T = decltype(select(t.alpha).from(t).as(alias::b).alpha); - static_assert(sqlpp::is_numeric_t::value, "type requirement"); - static_assert(sqlpp::is_expression_t::value, "type requirement"); - static_assert(sqlpp::is_named_expression_t::value, "type requirement"); - static_assert(not sqlpp::require_insert_t::value, "type requirement"); - static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); - static_assert(not sqlpp::must_not_update_t::value, "type requirement"); - static_assert(not sqlpp::is_boolean_t::value, "type requirement"); - static_assert(not sqlpp::is_text_t::value, "type requirement"); - static_assert(not sqlpp::is_alias_t::value, "type requirement"); - static_assert(not sqlpp::is_table_t::value, "type requirement"); - static_assert(sqlpp::is_regular::value, "type requirement"); - } - - // Test an alias of a select of an alias of a single numeric table column - { - using T = decltype(select(t.alpha.as(alias::a)).from(t).as(alias::b).a); - static_assert(sqlpp::is_numeric_t::value, "type requirement"); - static_assert(sqlpp::is_expression_t::value, "type requirement"); - static_assert(sqlpp::is_named_expression_t::value, "type requirement"); - static_assert(not sqlpp::require_insert_t::value, "type requirement"); - static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); - static_assert(not sqlpp::must_not_update_t::value, "type requirement"); - static_assert(not sqlpp::is_boolean_t::value, "type requirement"); - static_assert(not sqlpp::is_text_t::value, "type requirement"); - static_assert(not sqlpp::is_alias_t::value, "type requirement"); - static_assert(not sqlpp::is_table_t::value, "type requirement"); - static_assert(sqlpp::is_regular::value, "type requirement"); - } - - // Test that select(all_of(tab)) is expanded in select - { - auto a = select(all_of(t)); - auto b = select(t.alpha, t.beta, t.gamma, t.delta); - //auto c = select(t); - static_assert(std::is_same::value, "all_of(t) has to be expanded by select()"); - //static_assert(std::is_same::value, "t has to be expanded by select()"); - } - - // Test that select(all_of(tab)) is expanded in multi_column - { - auto a = multi_column(all_of(t)).as(alias::a); - auto b = multi_column(t.alpha, t.beta, t.gamma, t.delta).as(alias::a); - static_assert(std::is_same::value, "all_of(t) has to be expanded by multi_column"); - } - - // Test that a multicolumn is not a value - { - auto m = multi_column(t.alpha, t.beta).as(alias::a); - auto a = select(m).from(t).as(alias::b).a; - static_assert(not sqlpp::is_value_t::value, "a multi_column is not a value"); - } - // Test that result sets with identical name/value combinations have identical types - { - auto a = select(t.alpha); - auto b = select(f.epsilon.as(t.alpha)); - using A = typename decltype(a)::_result_row_t; - using B = typename decltype(b)::_result_row_t; - static_assert(std::is_same< - decltype(t.alpha)::_value_type::_base_value_type, - decltype(f.epsilon)::_value_type::_base_value_type>::value, "Two bigint columns must have identical base_value_type"); - static_assert(std::is_same::value, "select with identical columns(name/value_type) need to have identical result_types"); - } - for (const auto& row : db(select(all_of(t)).from(t).where(true))) { int64_t a = row.alpha; + const std::string b = row.beta; } + for (const auto& row : db(select(all_of(t).as(t)).from(t).where(true))) { - auto s = dynamic_select(db, all_of(t)).dynamic_from().dynamic_where().dynamic_limit().dynamic_offset(); - s.add_from(t); - s.add_where(t.alpha > 7 and t.alpha == any(select(t.alpha).from(t).where(t.alpha < 3))); - s.set_limit(30); - s.set_limit(3); - std::cerr << "------------------------\n"; - serialize(s, printer).str(); - std::cerr << "------------------------\n"; - using T = decltype(s); - static_assert(sqlpp::is_regular::value, "type requirement"); + int64_t a = row.tabBar.alpha; + const std::string b = row.tabBar.beta; } - // Test that select can be called with zero columns if it is used with dynamic columns. +#warning this should fail because f is not in from() + for (const auto& row : db(select(f.omega, all_of(t).as(t), t.gamma).from(t).where(true))) { - auto s = dynamic_select(db).dynamic_columns(); - s.add_column(t.alpha); - serialize(s, printer).str(); + int64_t a = row.tabBar.alpha; + const std::string b = row.tabBar.beta; + const bool g = row.gamma; + const float o = row.omega; } - // Test that verbatim_table compiles - { - auto s = select(t.alpha).from(sqlpp::verbatim_table("my_unknown_table")); - serialize(s, printer).str(); - } - - - static_assert(sqlpp::is_select_flag_t::value, "sqlpp::all has to be a select_flag"); - using T = sqlpp::vendor::wrap_operand::type; - static_assert(sqlpp::is_regular::value, "type requirement"); - static_assert(T::_is_expression, "T has to be an expression"); - static_assert(std::is_same::value, "T has to be a numeric"); - static_assert(sqlpp::is_numeric_t::value, "T has to be a numeric"); - static_assert(sqlpp::is_numeric_t::value, "TabBar.alpha has to be a numeric"); - ((t.alpha + 7) + 4).asc(); - static_assert(sqlpp::is_boolean_t::value, "Comparison expression have to be boolean"); - auto x = (t.gamma == true) and (t.alpha == 7); - auto y = t.gamma and true and t.gamma; - !t.gamma; - t.beta < "kaesekuchen"; - serialize(t.beta + "hallenhalma", printer).str(); - static_assert(sqlpp::must_not_insert_t::value, "alpha must not be inserted"); - serialize(t.alpha, printer).str(); - std::cerr << "\n" << sizeof(test::TabBar) << std::endl; - static_assert(std::is_same::value, "alpha should be a named expression"); - static_assert(sqlpp::is_named_expression_t::value, "alpha should be a named expression"); - static_assert(sqlpp::is_named_expression_t::value, "an alias of alpha should be a named expression"); - static_assert(sqlpp::is_alias_t::value, "an alias of alpha should be an alias"); - auto z = select(t.alpha).from(t) == 7; - auto l = t.as(alias::left); - auto r = select(t.gamma.as(alias::a)).from(t).where(t.gamma == true).as(alias::right); - static_assert(sqlpp::is_boolean_t::value, "select(bool) has to be a bool"); - serialize(sqlpp::select().flags(sqlpp::distinct, sqlpp::straight_join).columns(l.alpha, l.beta, select(r.a).from(r)) - .from(l, r) - .where(t.beta == "hello world" and select(t.gamma).from(t))// .as(alias::right)) - .group_by(l.gamma, r.a) - .having(r.a != true) - .order_by(l.beta.asc()) - .limit(17) - .offset(3) - .as(alias::a) - , printer).str(); - return 0; } diff --git a/tests/SelectTypeTest.cpp b/tests/SelectTypeTest.cpp new file mode 100644 index 00000000..fbe41a62 --- /dev/null +++ b/tests/SelectTypeTest.cpp @@ -0,0 +1,376 @@ +/* + * Copyright (c) 2013, 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 "is_regular.h" +#include +#include +#include +#include + + +MockDb db = {}; +MockDb::_serializer_context_t printer; + +namespace alias +{ + SQLPP_ALIAS_PROVIDER(a); + SQLPP_ALIAS_PROVIDER(b); + SQLPP_ALIAS_PROVIDER(left); + SQLPP_ALIAS_PROVIDER(right); +} + +int main() +{ + test::TabFoo f; + test::TabBar t; + + // Test a table + { + using T = decltype(t); + static_assert(not sqlpp::is_numeric_t::value, "type requirement"); + static_assert(not sqlpp::is_integral_t::value, "type requirement"); + static_assert(not sqlpp::is_floating_point_t::value, "type requirement"); + static_assert(not sqlpp::is_expression_t::value, "type requirement"); + static_assert(not sqlpp::is_named_expression_t::value, "type requirement"); + static_assert(not sqlpp::require_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_update_t::value, "type requirement"); + static_assert(not sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(not sqlpp::is_alias_t::value, "type requirement"); + static_assert(sqlpp::is_table_t::value, "type requirement"); + static_assert(sqlpp::is_regular::value, "type requirement"); + } + + // Test an alias of table + { + using T = decltype(t.as(alias::a)); + static_assert(not sqlpp::is_numeric_t::value, "type requirement"); + static_assert(not sqlpp::is_integral_t::value, "type requirement"); + static_assert(not sqlpp::is_floating_point_t::value, "type requirement"); + static_assert(not sqlpp::is_expression_t::value, "type requirement"); + static_assert(not sqlpp::is_named_expression_t::value, "type requirement"); + static_assert(not sqlpp::require_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_update_t::value, "type requirement"); + static_assert(not sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(sqlpp::is_alias_t::value, "type requirement"); + static_assert(sqlpp::is_table_t::value, "type requirement"); + static_assert(sqlpp::is_regular::value, "type requirement"); + } + + // Test an integral column of an alias of table + { + using T = decltype(t.as(alias::a).alpha); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(sqlpp::is_integral_t::value, "type requirement"); + static_assert(not sqlpp::is_floating_point_t::value, "type requirement"); + static_assert(sqlpp::is_expression_t::value, "type requirement"); + static_assert(sqlpp::is_named_expression_t::value, "type requirement"); + static_assert(not sqlpp::require_insert_t::value, "type requirement"); + static_assert(sqlpp::must_not_insert_t::value, "type requirement"); + static_assert(sqlpp::must_not_update_t::value, "type requirement"); + static_assert(not sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(not sqlpp::is_alias_t::value, "type requirement"); + static_assert(not sqlpp::is_table_t::value, "type requirement"); + static_assert(sqlpp::is_regular::value, "type requirement"); + } + + + // Test an integral table column + { + using T = decltype(t.alpha); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(sqlpp::is_integral_t::value, "type requirement"); + static_assert(not sqlpp::is_floating_point_t::value, "type requirement"); + static_assert(sqlpp::is_expression_t::value, "type requirement"); + static_assert(sqlpp::is_named_expression_t::value, "type requirement"); + static_assert(not sqlpp::require_insert_t::value, "type requirement"); + static_assert(sqlpp::must_not_insert_t::value, "type requirement"); + static_assert(sqlpp::must_not_update_t::value, "type requirement"); + static_assert(not sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(not sqlpp::is_alias_t::value, "type requirement"); + static_assert(not sqlpp::is_table_t::value, "type requirement"); + static_assert(sqlpp::is_regular::value, "type requirement"); + } + + // Test a floating point table column + { + using T = decltype(f.omega); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(not sqlpp::is_integral_t::value, "type requirement"); + static_assert(sqlpp::is_floating_point_t::value, "type requirement"); + static_assert(sqlpp::is_expression_t::value, "type requirement"); + static_assert(sqlpp::is_named_expression_t::value, "type requirement"); + static_assert(not sqlpp::require_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_update_t::value, "type requirement"); + static_assert(not sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(not sqlpp::is_alias_t::value, "type requirement"); + static_assert(not sqlpp::is_table_t::value, "type requirement"); + static_assert(sqlpp::is_regular::value, "type requirement"); + } + + // Test a an alias of a numeric table column + { + using T = decltype(t.alpha.as(alias::a)); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(not sqlpp::is_expression_t::value, "type requirement"); + static_assert(sqlpp::is_named_expression_t::value, "type requirement"); + static_assert(not sqlpp::require_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_update_t::value, "type requirement"); + static_assert(not sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(sqlpp::is_alias_t::value, "type requirement"); + static_assert(not sqlpp::is_table_t::value, "type requirement"); + static_assert(sqlpp::is_regular::value, "type requirement"); + } + + // Test a select of a single column without a from + { + using T = decltype(select(t.alpha)); // Hint: The current rule is pretty crude (a from is required), but certainly better than nothing + static_assert(not sqlpp::is_numeric_t::value, "type requirement"); + static_assert(not sqlpp::is_expression_t::value, "type requirement"); + static_assert(not sqlpp::is_named_expression_t::value, "type requirement"); + static_assert(not sqlpp::require_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_update_t::value, "type requirement"); + static_assert(not sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(not sqlpp::is_alias_t::value, "type requirement"); + static_assert(not sqlpp::is_table_t::value, "type requirement"); + static_assert(sqlpp::is_regular::value, "type requirement"); + } + + // Test a select of a single numeric table column + { + using T = decltype(select(t.alpha).from(t)); + static_assert(sqlpp::is_select_column_list_t::value, "Must not be noop"); + static_assert(sqlpp::is_from_t::value, "Must not be noop"); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(sqlpp::is_expression_t::value, "type requirement"); + static_assert(sqlpp::is_named_expression_t::value, "type requirement"); + static_assert(not sqlpp::require_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_update_t::value, "type requirement"); + static_assert(not sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(not sqlpp::is_alias_t::value, "type requirement"); + static_assert(not sqlpp::is_table_t::value, "type requirement"); + static_assert(sqlpp::is_regular::value, "type requirement"); + } + + // Test a select of an alias of a single numeric table column + { + using T = decltype(select(t.alpha.as(alias::a)).from(t)); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(sqlpp::is_expression_t::value, "type requirement"); + static_assert(sqlpp::is_named_expression_t::value, "type requirement"); + static_assert(not sqlpp::require_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_update_t::value, "type requirement"); + static_assert(not sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(not sqlpp::is_alias_t::value, "type requirement"); + static_assert(not sqlpp::is_table_t::value, "type requirement"); + static_assert(sqlpp::is_regular::value, "type requirement"); + } + + // Test an alias of a select of a single numeric table column + { + using T = decltype(select(t.alpha).from(t).as(alias::b)); + static_assert(not sqlpp::is_numeric_t::value, "type requirement"); + static_assert(not sqlpp::is_expression_t::value, "type requirement"); + static_assert(not sqlpp::is_named_expression_t::value, "type requirement"); + static_assert(not sqlpp::require_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_update_t::value, "type requirement"); + static_assert(not sqlpp::is_boolean_t::value, "red to not be boolean"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(sqlpp::is_alias_t::value, "type requirement"); + static_assert(sqlpp::is_table_t::value, "type requirement"); + static_assert(sqlpp::is_regular::value, "type requirement"); + } + + // Test the column of an alias of a select of an alias of a single numeric table column + { + using T = decltype(select(t.alpha.as(alias::a)).from(t).as(alias::b)); + static_assert(not sqlpp::is_numeric_t::value, "type requirement"); + static_assert(not sqlpp::is_expression_t::value, "type requirement"); + static_assert(not sqlpp::is_named_expression_t::value, "type requirement"); + static_assert(not sqlpp::require_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_update_t::value, "type requirement"); + static_assert(not sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(sqlpp::is_alias_t::value, "type requirement"); + static_assert(sqlpp::is_table_t::value, "type requirement"); + static_assert(sqlpp::is_regular::value, "type requirement"); + } + + // Test the column of an alias of a select of a single numeric table column + { + using T = decltype(select(t.alpha).from(t).as(alias::b).alpha); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(sqlpp::is_expression_t::value, "type requirement"); + static_assert(sqlpp::is_named_expression_t::value, "type requirement"); + static_assert(not sqlpp::require_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_update_t::value, "type requirement"); + static_assert(not sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(not sqlpp::is_alias_t::value, "type requirement"); + static_assert(not sqlpp::is_table_t::value, "type requirement"); + static_assert(sqlpp::is_regular::value, "type requirement"); + } + + // Test an alias of a select of an alias of a single numeric table column + { + using T = decltype(select(t.alpha.as(alias::a)).from(t).as(alias::b).a); + static_assert(sqlpp::is_numeric_t::value, "type requirement"); + static_assert(sqlpp::is_expression_t::value, "type requirement"); + static_assert(sqlpp::is_named_expression_t::value, "type requirement"); + static_assert(not sqlpp::require_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_insert_t::value, "type requirement"); + static_assert(not sqlpp::must_not_update_t::value, "type requirement"); + static_assert(not sqlpp::is_boolean_t::value, "type requirement"); + static_assert(not sqlpp::is_text_t::value, "type requirement"); + static_assert(not sqlpp::is_alias_t::value, "type requirement"); + static_assert(not sqlpp::is_table_t::value, "type requirement"); + static_assert(sqlpp::is_regular::value, "type requirement"); + } + + // Test that select(all_of(tab)) is expanded in select + { + auto a = select(all_of(t)); + auto b = select(t.alpha, t.beta, t.gamma, t.delta); + //auto c = select(t); + static_assert(std::is_same::value, "all_of(t) has to be expanded by select()"); + //static_assert(std::is_same::value, "t has to be expanded by select()"); + } + + // Test that select(all_of(tab)) is expanded in multi_column + { + auto a = multi_column(all_of(t)).as(alias::a); + auto b = multi_column(t.alpha, t.beta, t.gamma, t.delta).as(alias::a); + static_assert(std::is_same::value, "all_of(t) has to be expanded by multi_column"); + } + + // Test that a multicolumn is not a value + { + auto m = multi_column(t.alpha, t.beta).as(alias::a); + auto a = select(m).from(t).as(alias::b).a; + static_assert(not sqlpp::is_value_t::value, "a multi_column is not a value"); + } + // Test that result sets with identical name/value combinations have identical types + { + auto a = select(t.alpha); + auto b = select(f.epsilon.as(t.alpha)); + using A = typename decltype(a)::_result_row_t; + using B = typename decltype(b)::_result_row_t; + static_assert(std::is_same< + decltype(t.alpha)::_value_type::_base_value_type, + decltype(f.epsilon)::_value_type::_base_value_type>::value, "Two bigint columns must have identical base_value_type"); + static_assert(std::is_same::value, "select with identical columns(name/value_type) need to have identical result_types"); + } + + for (const auto& row : db(select(all_of(t)).from(t).where(true))) + { + int64_t a = row.alpha; + } + + { + auto s = dynamic_select(db, all_of(t)).dynamic_from().dynamic_where().dynamic_limit().dynamic_offset(); + s.add_from(t); + s.add_where(t.alpha > 7 and t.alpha == any(select(t.alpha).from(t).where(t.alpha < 3))); + s.set_limit(30); + s.set_limit(3); + std::cerr << "------------------------\n"; + serialize(s, printer).str(); + std::cerr << "------------------------\n"; + using T = decltype(s); + static_assert(sqlpp::is_regular::value, "type requirement"); + } + + // Test that select can be called with zero columns if it is used with dynamic columns. + { + auto s = dynamic_select(db).dynamic_columns(); + s.add_column(t.alpha); + serialize(s, printer).str(); + } + + // Test that verbatim_table compiles + { + auto s = select(t.alpha).from(sqlpp::verbatim_table("my_unknown_table")); + serialize(s, printer).str(); + } + + + static_assert(sqlpp::is_select_flag_t::value, "sqlpp::all has to be a select_flag"); + using T = sqlpp::vendor::wrap_operand::type; + static_assert(sqlpp::is_regular::value, "type requirement"); + static_assert(T::_is_expression, "T has to be an expression"); + static_assert(std::is_same::value, "T has to be a numeric"); + static_assert(sqlpp::is_numeric_t::value, "T has to be a numeric"); + static_assert(sqlpp::is_numeric_t::value, "TabBar.alpha has to be a numeric"); + ((t.alpha + 7) + 4).asc(); + static_assert(sqlpp::is_boolean_t::value, "Comparison expression have to be boolean"); + auto x = (t.gamma == true) and (t.alpha == 7); + auto y = t.gamma and true and t.gamma; + !t.gamma; + t.beta < "kaesekuchen"; + serialize(t.beta + "hallenhalma", printer).str(); + static_assert(sqlpp::must_not_insert_t::value, "alpha must not be inserted"); + serialize(t.alpha, printer).str(); + std::cerr << "\n" << sizeof(test::TabBar) << std::endl; + static_assert(std::is_same::value, "alpha should be a named expression"); + static_assert(sqlpp::is_named_expression_t::value, "alpha should be a named expression"); + static_assert(sqlpp::is_named_expression_t::value, "an alias of alpha should be a named expression"); + static_assert(sqlpp::is_alias_t::value, "an alias of alpha should be an alias"); + auto z = select(t.alpha).from(t) == 7; + auto l = t.as(alias::left); + auto r = select(t.gamma.as(alias::a)).from(t).where(t.gamma == true).as(alias::right); + static_assert(sqlpp::is_boolean_t::value, "select(bool) has to be a bool"); + serialize(sqlpp::select().flags(sqlpp::distinct, sqlpp::straight_join).columns(l.alpha, l.beta, select(r.a).from(r)) + .from(l, r) + .where(t.beta == "hello world" and select(t.gamma).from(t))// .as(alias::right)) + .group_by(l.gamma, r.a) + .having(r.a != true) + .order_by(l.beta.asc()) + .limit(17) + .offset(3) + .as(alias::a) + , printer).str(); + + return 0; +} diff --git a/tests/UpdateTest.cpp b/tests/UpdateTest.cpp index 0aedd8aa..113bc8c2 100644 --- a/tests/UpdateTest.cpp +++ b/tests/UpdateTest.cpp @@ -64,5 +64,7 @@ int main() u.add_set(t.gamma = false); serialize(u, printer).str(); + db(u); + return 0; }