mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-16 04:47:18 +08:00
More tests for provided_tables_of
This commit is contained in:
parent
c52a60cabd
commit
841ed273b9
@ -67,10 +67,8 @@ namespace sqlpp
|
||||
template <typename Lhs, typename JoinType, typename Rhs, typename Condition>
|
||||
struct provided_static_tables_of<join_t<Lhs, JoinType, Rhs, Condition>>
|
||||
{
|
||||
using type = typename std::conditional<
|
||||
is_dynamic<Rhs>::value,
|
||||
provided_static_tables_of_t<Lhs>,
|
||||
detail::type_vector_cat_t<provided_static_tables_of_t<Lhs>, provided_static_tables_of_t<Rhs>>>::type;
|
||||
using type =
|
||||
detail::type_vector_cat_t<provided_static_tables_of_t<Lhs>, provided_static_tables_of_t<Rhs>>;
|
||||
};
|
||||
|
||||
template <typename Lhs, typename JoinType, typename Rhs, typename Condition>
|
||||
@ -79,10 +77,10 @@ namespace sqlpp
|
||||
using type = detail::type_vector_cat_t<
|
||||
typename std::conditional<detail::type_vector<right_outer_join_t, full_outer_join_t>::contains<JoinType>::value,
|
||||
provided_tables_of_t<Lhs>,
|
||||
detail::type_vector<>>::type,
|
||||
provided_optional_tables_of_t<Lhs>>::type,
|
||||
typename std::conditional<detail::type_vector<left_outer_join_t, full_outer_join_t>::contains<JoinType>::value,
|
||||
provided_tables_of_t<Rhs>,
|
||||
detail::type_vector<>>::type>;
|
||||
provided_optional_tables_of_t<Rhs>>::type>;
|
||||
};
|
||||
|
||||
#warning: Need to make extra sure that ON does not require on extra tables.
|
||||
|
@ -41,7 +41,7 @@ namespace sqlpp
|
||||
return name_to_sql_string(context, t._name);
|
||||
}
|
||||
|
||||
auto schema(std::string name) -> schema_t
|
||||
inline auto schema(std::string name) -> schema_t
|
||||
{
|
||||
return schema_t{std::move(name)};
|
||||
};
|
||||
|
@ -64,11 +64,6 @@ namespace sqlpp
|
||||
using type = sqlpp::detail::type_vector<table_t<TableSpec>>;
|
||||
};
|
||||
|
||||
template <typename TableSpec>
|
||||
struct provided_static_tables_of<table_t<TableSpec>> : public provided_tables_of<table_t<TableSpec>>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Context, typename TableSpec>
|
||||
auto to_sql_string(Context& context, const table_t<TableSpec>& /*unused*/) -> std::string
|
||||
{
|
||||
|
@ -59,16 +59,6 @@ namespace sqlpp
|
||||
using type = sqlpp::detail::type_vector<table_as_t<TableSpec, NameTag>>;
|
||||
};
|
||||
|
||||
template <typename TableSpec, typename NameTag>
|
||||
struct provided_static_tables_of<table_as_t<TableSpec, NameTag>> : public provided_tables_of<table_as_t<TableSpec, NameTag>>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename TableSpec, typename NameTag>
|
||||
struct provided_optional_tables_of<table_as_t<TableSpec, NameTag>> : public provided_tables_of<table_as_t<TableSpec, NameTag>>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Context, typename TableSpec, typename NameTag>
|
||||
auto to_sql_string(Context& context, const table_as_t<TableSpec, NameTag>&) -> std::string
|
||||
{
|
||||
|
@ -289,11 +289,6 @@ namespace sqlpp
|
||||
using type = sqlpp::detail::type_vector<cte_ref_t<NameTagProvider>>;
|
||||
};
|
||||
|
||||
template <typename NameTagProvider, typename Statement, typename... ColumnSpecs>
|
||||
struct provided_static_tables_of<cte_t<NameTagProvider, Statement, ColumnSpecs...>> : public provided_tables_of<cte_t<NameTagProvider, Statement, ColumnSpecs...>>
|
||||
{
|
||||
};
|
||||
|
||||
#warning: Should enough if with_t provides ctes?
|
||||
template <typename NameTagProvider, typename Statement, typename... ColumnSpecs>
|
||||
struct provided_ctes_of<cte_t<NameTagProvider, Statement, ColumnSpecs...>>
|
||||
@ -301,11 +296,6 @@ namespace sqlpp
|
||||
using type = detail::type_vector<cte_ref_t<NameTagProvider>>;
|
||||
};
|
||||
|
||||
template <typename NameTagProvider, typename Statement, typename... ColumnSpecs>
|
||||
struct provided_static_ctes_of<cte_t<NameTagProvider, Statement, ColumnSpecs...>> : public provided_ctes_of<cte_t<NameTagProvider, Statement, ColumnSpecs...>>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Context, typename NameTagProvider, typename Statement, typename... ColumnSpecs>
|
||||
auto to_sql_string(Context& context, const cte_t<NameTagProvider, Statement, ColumnSpecs...>& t) -> std::string
|
||||
{
|
||||
@ -341,11 +331,6 @@ namespace sqlpp
|
||||
using type = sqlpp::detail::type_vector<cte_ref_t<NameTagProvider>>;
|
||||
};
|
||||
|
||||
template<typename NameTagProvider>
|
||||
struct provided_static_tables_of<cte_ref_t<NameTagProvider>> : public provided_tables_of<cte_ref_t<NameTagProvider>>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename NameTagProvider>
|
||||
struct required_ctes_of<cte_ref_t<NameTagProvider>>
|
||||
{
|
||||
|
@ -71,6 +71,16 @@ namespace sqlpp
|
||||
using type = detail::type_vector<Table>;
|
||||
};
|
||||
|
||||
template<typename Table>
|
||||
struct provided_tables_of<from_t<Table>> : public provided_tables_of<Table>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Table>
|
||||
struct provided_optional_tables_of<from_t<Table>> : public provided_optional_tables_of<Table>
|
||||
{
|
||||
};
|
||||
|
||||
SQLPP_PORTABLE_STATIC_ASSERT(
|
||||
assert_from_not_pre_join_t,
|
||||
"from() argument is a pre join, please use an explicit on() condition or unconditionally()");
|
||||
|
@ -77,6 +77,11 @@ namespace sqlpp
|
||||
using type = detail::type_vector<Table>;
|
||||
};
|
||||
|
||||
template<typename Table>
|
||||
struct provided_tables_of<into_t<Table>> : public provided_tables_of<Table>
|
||||
{
|
||||
};
|
||||
|
||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_into_t, "into() required");
|
||||
|
||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_into_arg_is_table, "argument for into() must be a table");
|
||||
|
@ -83,7 +83,7 @@ namespace sqlpp
|
||||
template <typename Select, typename NameTagProvider, typename... FieldSpecs>
|
||||
struct provided_tables_of<select_as_t<Select, NameTagProvider, FieldSpecs...>>
|
||||
: public std::conditional<Select::_can_be_used_as_table(),
|
||||
sqlpp::detail::type_vector<select_as_t<Select, NameTagProvider, FieldSpecs...>>,
|
||||
sqlpp::detail::type_vector<select_ref_t<NameTagProvider>>,
|
||||
sqlpp::detail::type_vector<>>
|
||||
{
|
||||
};
|
||||
@ -94,14 +94,9 @@ namespace sqlpp
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Select, typename NameTagProvider, typename... FieldSpecs>
|
||||
struct provided_optional_tables_of<select_as_t<Select, NameTagProvider, FieldSpecs...>>
|
||||
: public provided_tables_of<select_as_t<Select, NameTagProvider, FieldSpecs...>>
|
||||
{
|
||||
};
|
||||
|
||||
#warning: V1.0 has empty nodes. Is that correct? In either case document the decision here.
|
||||
#warning: Need to add required tables of
|
||||
#warning: Need to add nodes to allow for parameters to be used.
|
||||
|
||||
template <typename Context, typename Select, typename NameTagProvider, typename... FieldSpecs>
|
||||
auto to_sql_string(Context& context, const select_as_t<Select, NameTagProvider, FieldSpecs...>& t) -> std::string
|
||||
|
@ -80,6 +80,11 @@ namespace sqlpp
|
||||
using type = detail::type_vector<Table>;
|
||||
};
|
||||
|
||||
template<typename Table>
|
||||
struct provided_tables_of<single_table_t<Table>> : public provided_tables_of<Table>
|
||||
{
|
||||
};
|
||||
|
||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_update_table_arg_is_table_t, "argument for update() must be a table");
|
||||
template <typename Table>
|
||||
struct check_update_table
|
||||
|
@ -92,7 +92,7 @@ namespace sqlpp
|
||||
template <typename L, typename R>
|
||||
using check_arithmetic_args = ::sqlpp::enable_if_t<is_numeric<L>::value and is_numeric<R>::value>;
|
||||
|
||||
// L and R are expected to be numeric value types (boolen, integral, unsigned_integral, or floating_point).
|
||||
// L and R are expected to be numeric value types (boolean, integral, unsigned_integral, or floating_point).
|
||||
template <typename Operator, typename L, typename R>
|
||||
struct arithmetic_value_type
|
||||
{
|
||||
|
@ -26,6 +26,7 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sqlpp11/core/query/dynamic_fwd.h>
|
||||
#include <sqlpp11/core/type_traits.h>
|
||||
#include <sqlpp11/core/operator/assign_expression.h>
|
||||
#include <sqlpp11/core/operator/sort_order_expression.h>
|
||||
@ -58,7 +59,7 @@ namespace sqlpp
|
||||
template <typename Expr>
|
||||
struct nodes_of<dynamic_t<Expr>>
|
||||
{
|
||||
using type = Expr;
|
||||
using type = detail::type_vector<Expr>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
34
include/sqlpp11/core/query/dynamic_fwd.h
Normal file
34
include/sqlpp11/core/query/dynamic_fwd.h
Normal file
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* Copyright (c) 2024, 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.
|
||||
*/
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
template <typename Expr>
|
||||
struct dynamic_t;
|
||||
|
||||
} // namespace sqlpp
|
@ -28,13 +28,13 @@
|
||||
|
||||
#include <sqlpp11/core/type_traits/nodes_of.h>
|
||||
#include <sqlpp11/core/detail/type_vector.h>
|
||||
#include <sqlpp11/core/query/dynamic_fwd.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
// required_tables_of determines the type_vector of tables referenced by columns within within T.
|
||||
// required_tables_of recursively determines the type_vector of tables referenced by columns within within T.
|
||||
// column_t or other structs that might reference a table shall specialize this template to indicate their table
|
||||
// requirement.
|
||||
// Dynamic parts of a query shall wrap their required tables in dynamic_t.
|
||||
template<typename T>
|
||||
struct required_tables_of
|
||||
{
|
||||
@ -50,12 +50,23 @@ namespace sqlpp
|
||||
template<typename T>
|
||||
using required_tables_of_t = typename required_tables_of<T>::type;
|
||||
|
||||
// required_static_tables_of recursively determines the type_vector of tables statically referenced by columns within
|
||||
// within T. column_t or other structs that might reference a table shall specialize this template to indicate their
|
||||
// table requirement.
|
||||
//
|
||||
// Dynamic query parts are ignored.
|
||||
template<typename T>
|
||||
struct required_static_tables_of
|
||||
{
|
||||
using type = typename required_static_tables_of<nodes_of_t<T>>::type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct required_static_tables_of<dynamic_t<T>>
|
||||
{
|
||||
using type = detail::type_vector<>;
|
||||
};
|
||||
|
||||
template<typename... T>
|
||||
struct required_static_tables_of<detail::type_vector<T...>>
|
||||
{
|
||||
@ -66,57 +77,49 @@ namespace sqlpp
|
||||
using required_static_tables_of_t = typename required_static_tables_of<T>::type;
|
||||
|
||||
#warning: need type tests...
|
||||
//static_assert(required_tables_of_t<int>::size::value == 0, "");
|
||||
|
||||
// provided_tables_of determines the type_vector of tables provided by the query clause, e.g. by FROM.
|
||||
// Provided tables can be wrapped in dynamic_t if they are provided through a dynamic join.
|
||||
// provided_tables_of determines the type_vector of tables provided by a clause, e.g. by FROM.
|
||||
// table_t, cte_ref_t, or other structs that might provide a table in a query need to specialize this template.
|
||||
//
|
||||
// Note: In contrast to `required_tables_of` above, this is non-recursive. This is important for instance to prevent
|
||||
// `SELECT...AS` to leak from `select_column_list`.
|
||||
template <typename T>
|
||||
struct provided_tables_of
|
||||
{
|
||||
using type = typename provided_tables_of<nodes_of_t<T>>::type;
|
||||
using type = detail::type_vector<>;
|
||||
};
|
||||
|
||||
template <typename... T>
|
||||
struct provided_tables_of<detail::type_vector<T...>>
|
||||
template <typename T>
|
||||
struct provided_tables_of<dynamic_t<T>> : public provided_tables_of<T>
|
||||
{
|
||||
using type = detail::type_vector_cat_t<typename provided_tables_of<T>::type...>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using provided_tables_of_t = typename provided_tables_of<T>::type;
|
||||
|
||||
// provided_tables_of determines the type_vector of non-dynamic tables provided by a clause, e.g. by FROM.
|
||||
template <typename T>
|
||||
struct provided_static_tables_of
|
||||
struct provided_static_tables_of : public provided_tables_of<T>
|
||||
{
|
||||
using type = typename provided_static_tables_of<nodes_of_t<T>>::type;
|
||||
};
|
||||
|
||||
template <typename... T>
|
||||
struct provided_static_tables_of<detail::type_vector<T...>>
|
||||
template <typename T>
|
||||
struct provided_static_tables_of<dynamic_t<T>>
|
||||
{
|
||||
using type = detail::type_vector_cat_t<typename provided_static_tables_of<T>::type...>;
|
||||
using type = detail::type_vector<>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using provided_static_tables_of_t = typename provided_static_tables_of<T>::type;
|
||||
|
||||
// provided_tables_of determines the type_vector of outer join tables provided by a clause, e.g. by FROM.
|
||||
template <typename T>
|
||||
struct provided_optional_tables_of
|
||||
{
|
||||
using type = typename provided_optional_tables_of<nodes_of_t<T>>::type;
|
||||
};
|
||||
|
||||
template <typename... T>
|
||||
struct provided_optional_tables_of<detail::type_vector<T...>>
|
||||
{
|
||||
using type = detail::type_vector_cat_t<typename provided_optional_tables_of<T>::type...>;
|
||||
using type = detail::type_vector<>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using provided_optional_tables_of_t = typename provided_optional_tables_of<T>::type;
|
||||
|
||||
static_assert(provided_tables_of_t<int>::empty(), "");
|
||||
|
||||
} // namespace sqlpp
|
||||
|
||||
|
@ -24,7 +24,6 @@
|
||||
*/
|
||||
|
||||
#include "Sample.h"
|
||||
#include "../compare.h"
|
||||
#include <sqlpp11/sqlpp11.h>
|
||||
|
||||
int main(int, char* [])
|
||||
|
@ -40,7 +40,7 @@ void test_table()
|
||||
static_assert(std::is_same<sqlpp::name_tag_of_t<FooBar>, test::TabBar_::_sqlpp_name_tag>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_tables_of_t<FooBar>, sqlpp::detail::type_vector<FooBar>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_static_tables_of_t<FooBar>, sqlpp::provided_tables_of_t<FooBar>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_optional_tables_of_t<FooBar>, sqlpp::provided_tables_of_t<FooBar>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_optional_tables_of_t<FooBar>, sqlpp::detail::type_vector<>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::required_tables_of_t<FooBar>, sqlpp::detail::type_vector<>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::required_static_tables_of_t<FooBar>, sqlpp::required_tables_of_t<FooBar>>::value, "");
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
#include "Sample.h"
|
||||
#include <sqlpp11/sqlpp11.h>
|
||||
#include "../../../include/test_helpers.h"
|
||||
|
||||
void test_from()
|
||||
{
|
||||
@ -36,10 +37,11 @@ void test_from()
|
||||
// FROM CTE
|
||||
{
|
||||
auto x = cte(sqlpp::alias::x).as(select(foo.id).from(foo).unconditionally());
|
||||
auto f = from(x);
|
||||
auto statement = from(x);
|
||||
|
||||
using R = decltype(make_table_ref(x));
|
||||
using F = decltype(f);
|
||||
using S = decltype(statement);
|
||||
using F = extract_clause_t<S>;
|
||||
|
||||
static_assert(std::is_same<sqlpp::provided_tables_of_t<F>, sqlpp::detail::type_vector<R>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::required_ctes_of_t<F>, sqlpp::detail::type_vector<R>>::value, "");
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
#include "Sample.h"
|
||||
#include <sqlpp11/sqlpp11.h>
|
||||
#include "../../../include/test_helpers.h"
|
||||
|
||||
SQLPP_CREATE_NAME_TAG(cheese);
|
||||
|
||||
@ -45,7 +46,8 @@ void test_into()
|
||||
|
||||
// Valid into clause
|
||||
{
|
||||
using I = decltype(sqlpp::into(foo));
|
||||
using S = decltype(sqlpp::into(foo));
|
||||
using I = extract_clause_t<S>;
|
||||
static_assert(std::is_same<sqlpp::provided_tables_of_t<I>, sqlpp::detail::type_vector<Foo>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_static_tables_of_t<I>, sqlpp::provided_tables_of_t<I>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_optional_tables_of_t<I>, sqlpp::detail::type_vector<>>::value, "");
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
#include "Sample.h"
|
||||
#include <sqlpp11/sqlpp11.h>
|
||||
#include "../../../include/test_helpers.h"
|
||||
|
||||
SQLPP_CREATE_NAME_TAG(cheese);
|
||||
|
||||
@ -45,7 +46,8 @@ void test_single_table()
|
||||
|
||||
// Valid single table clause
|
||||
{
|
||||
using S = decltype(sqlpp::single_table(foo));
|
||||
using Statement = decltype(sqlpp::single_table(foo));
|
||||
using S = extract_clause_t<Statement>;
|
||||
static_assert(std::is_same<sqlpp::provided_tables_of_t<S>, sqlpp::detail::type_vector<Foo>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_static_tables_of_t<S>, sqlpp::provided_tables_of_t<S>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_optional_tables_of_t<S>, sqlpp::detail::type_vector<>>::value, "");
|
||||
|
@ -29,4 +29,5 @@ function(test_compile name)
|
||||
endfunction()
|
||||
|
||||
test_compile(aggregates)
|
||||
test_compile(tables_of)
|
||||
|
||||
|
192
tests/core/types/type_traits/tables_of.cpp
Normal file
192
tests/core/types/type_traits/tables_of.cpp
Normal file
@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright (c) 2024, 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 "Sample.h"
|
||||
#include <sqlpp11/sqlpp11.h>
|
||||
|
||||
SQLPP_CREATE_NAME_TAG(cheese);
|
||||
|
||||
void test_required_tables_of()
|
||||
{
|
||||
// Columns require tables.
|
||||
{
|
||||
using T = decltype(test::TabFoo{}.id);
|
||||
static_assert(std::is_same<sqlpp::required_tables_of_t<T>, sqlpp::detail::type_vector<test::TabFoo>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::required_static_tables_of_t<T>, sqlpp::detail::type_vector<test::TabFoo>>::value,
|
||||
"");
|
||||
}
|
||||
|
||||
// Tables do not require tables.
|
||||
{
|
||||
using T = decltype(test::TabFoo{});
|
||||
static_assert(sqlpp::required_tables_of_t<T>::empty(), "");
|
||||
static_assert(sqlpp::required_static_tables_of_t<T>::empty(), "");
|
||||
}
|
||||
|
||||
// Static expressions require collective tables.
|
||||
{
|
||||
using TF = test::TabFoo;
|
||||
using TB = test::TabBar;
|
||||
using TC = decltype(test::TabFoo{}.as(cheese));
|
||||
using T = decltype(TF{}.id + TB{}.id + TC{}.id);
|
||||
static_assert(std::is_same<sqlpp::required_tables_of_t<T>, sqlpp::detail::type_vector<TF, TB, TC>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::required_static_tables_of_t<T>, sqlpp::detail::type_vector<TF, TB, TC>>::value, "");
|
||||
}
|
||||
|
||||
// Dynamic expressions require all tables, but on the the static parts contribute to the statically required tables.
|
||||
{
|
||||
using TF = test::TabFoo;
|
||||
using TB = test::TabBar;
|
||||
using TC = decltype(test::TabFoo{}.as(cheese));
|
||||
using T = decltype(TF{}.id < 17 and dynamic(true, TB{}.id < 17) and TC{}.id < 17);
|
||||
static_assert(std::is_same<sqlpp::required_tables_of_t<T>, sqlpp::detail::type_vector<TF, TB, TC>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::required_static_tables_of_t<T>, sqlpp::detail::type_vector<TF, TC>>::value, "");
|
||||
}
|
||||
}
|
||||
|
||||
void test_provided_tables_of()
|
||||
{
|
||||
// Columns do not provide tables.
|
||||
{
|
||||
using T = decltype(test::TabFoo{}.id);
|
||||
static_assert(sqlpp::provided_tables_of_t<T>::empty(), "");
|
||||
static_assert(sqlpp::provided_static_tables_of_t<T>::empty(),
|
||||
"");
|
||||
static_assert(sqlpp::provided_optional_tables_of_t<T>::empty(),
|
||||
"");
|
||||
}
|
||||
|
||||
// Tables provide tables.
|
||||
{
|
||||
using T = test::TabFoo;
|
||||
static_assert(std::is_same<sqlpp::provided_tables_of_t<T>, sqlpp::detail::type_vector<T>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_static_tables_of_t<T>, sqlpp::detail::type_vector<T>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_optional_tables_of_t<T>, sqlpp::detail::type_vector<>>::value, "");
|
||||
}
|
||||
|
||||
// Schema-qualified tables provide tables.
|
||||
{
|
||||
using T = decltype(schema_qualified_table({"meme"}, test::TabFoo{}).as(cheese));
|
||||
static_assert(std::is_same<sqlpp::provided_tables_of_t<T>, sqlpp::detail::type_vector<T>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_static_tables_of_t<T>, sqlpp::detail::type_vector<T>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_optional_tables_of_t<T>, sqlpp::detail::type_vector<>>::value, "");
|
||||
}
|
||||
|
||||
// Tables AS provide tables.
|
||||
{
|
||||
using T = decltype(test::TabFoo{}.as(cheese));
|
||||
static_assert(std::is_same<sqlpp::provided_tables_of_t<T>, sqlpp::detail::type_vector<T>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_static_tables_of_t<T>, sqlpp::detail::type_vector<T>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_optional_tables_of_t<T>, sqlpp::detail::type_vector<>>::value, "");
|
||||
}
|
||||
|
||||
// SELECT AS provides tables.
|
||||
{
|
||||
using T = decltype(select(test::TabFoo{}.id).from(test::TabFoo{}).unconditionally().as(cheese));
|
||||
using Ref = sqlpp::select_ref_t<cheese_t>;
|
||||
static_assert(std::is_same<sqlpp::provided_tables_of_t<T>, sqlpp::detail::type_vector<Ref>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_static_tables_of_t<T>, sqlpp::detail::type_vector<Ref>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_optional_tables_of_t<T>, sqlpp::detail::type_vector<>>::value, "");
|
||||
}
|
||||
|
||||
// JOIN provides tables.
|
||||
{
|
||||
using F = test::TabFoo;
|
||||
using B = test::TabBar;
|
||||
using T = decltype(F{}.cross_join(B{}));
|
||||
static_assert(std::is_same<sqlpp::provided_tables_of_t<T>, sqlpp::detail::type_vector<F,B>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_static_tables_of_t<T>, sqlpp::detail::type_vector<F,B>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_optional_tables_of_t<T>, sqlpp::detail::type_vector<>>::value, "");
|
||||
}
|
||||
|
||||
// Dynamic JOIN provides non-static tables.
|
||||
{
|
||||
using F = test::TabFoo;
|
||||
using B = test::TabBar;
|
||||
using T = decltype(F{}.cross_join(dynamic(true, B{})));
|
||||
static_assert(std::is_same<sqlpp::provided_tables_of_t<T>, sqlpp::detail::type_vector<F,B>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_static_tables_of_t<T>, sqlpp::detail::type_vector<F>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_optional_tables_of_t<T>, sqlpp::detail::type_vector<>>::value, "");
|
||||
}
|
||||
|
||||
// Left outer join makes right-hand-side table "optional", i.e. columns can by NULL.
|
||||
{
|
||||
using F = test::TabFoo;
|
||||
using B = test::TabBar;
|
||||
using T = decltype(F{}.left_outer_join(dynamic(true, B{})).on(F{}.id == B{}.id));
|
||||
static_assert(std::is_same<sqlpp::provided_tables_of_t<T>, sqlpp::detail::type_vector<F,B>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_static_tables_of_t<T>, sqlpp::detail::type_vector<F>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_optional_tables_of_t<T>, sqlpp::detail::type_vector<B>>::value, "");
|
||||
}
|
||||
|
||||
// Right outer join makes left-hand-side table "optional", i.e. columns can by NULL.
|
||||
{
|
||||
using F = test::TabFoo;
|
||||
using B = test::TabBar;
|
||||
using T = decltype(F{}.right_outer_join(dynamic(true, B{})).on(F{}.id == B{}.id));
|
||||
static_assert(std::is_same<sqlpp::provided_tables_of_t<T>, sqlpp::detail::type_vector<F,B>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_static_tables_of_t<T>, sqlpp::detail::type_vector<F>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_optional_tables_of_t<T>, sqlpp::detail::type_vector<F>>::value, "");
|
||||
}
|
||||
|
||||
// Full outer join makes left-hand-side table "optional", i.e. columns can by NULL.
|
||||
{
|
||||
using F = test::TabFoo;
|
||||
using B = test::TabBar;
|
||||
using T = decltype(F{}.full_outer_join(dynamic(true, B{})).on(F{}.id == B{}.id));
|
||||
static_assert(std::is_same<sqlpp::provided_tables_of_t<T>, sqlpp::detail::type_vector<F,B>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_static_tables_of_t<T>, sqlpp::detail::type_vector<F>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_optional_tables_of_t<T>, sqlpp::detail::type_vector<F, B>>::value, "");
|
||||
}
|
||||
|
||||
// Nested joins propagate their provided tables.
|
||||
{
|
||||
using F = test::TabFoo;
|
||||
using B = test::TabBar;
|
||||
using C = decltype(test::TabFoo{}.as(cheese));
|
||||
using T = decltype(C{}.cross_join(F{}.full_outer_join(dynamic(true, B{})).on(F{}.id == B{}.id)));
|
||||
static_assert(std::is_same<sqlpp::provided_tables_of_t<T>, sqlpp::detail::type_vector<C,F,B>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_static_tables_of_t<T>, sqlpp::detail::type_vector<C,F>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_optional_tables_of_t<T>, sqlpp::detail::type_vector<F, B>>::value, "");
|
||||
}
|
||||
|
||||
// Nested joins propagate their provided tables.
|
||||
{
|
||||
using F = test::TabFoo;
|
||||
using B = test::TabBar;
|
||||
using C = decltype(test::TabFoo{}.as(cheese));
|
||||
using T = decltype(F{}.full_outer_join(dynamic(true, B{})).on(F{}.id == B{}.id).cross_join(C{}));
|
||||
static_assert(std::is_same<sqlpp::provided_tables_of_t<T>, sqlpp::detail::type_vector<F,B,C>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_static_tables_of_t<T>, sqlpp::detail::type_vector<F,C>>::value, "");
|
||||
static_assert(std::is_same<sqlpp::provided_optional_tables_of_t<T>, sqlpp::detail::type_vector<F, B>>::value, "");
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
void test_required_tables_of();
|
||||
void test_provided_tables_of();
|
||||
}
|
||||
|
@ -102,3 +102,18 @@ struct is_optional : public std::false_type{};
|
||||
template <typename T>
|
||||
struct is_optional<::sqlpp::optional<T>> : public std::true_type{};
|
||||
|
||||
// functions like `from(tab)` yield a statement with a single clause. This extracts the type of that clause.
|
||||
template <typename Statement>
|
||||
struct extract_clause;
|
||||
|
||||
template <typename Clause>
|
||||
struct extract_clause<sqlpp::statement_t<Clause>>
|
||||
{
|
||||
using type = Clause;
|
||||
};
|
||||
|
||||
template <typename Statement>
|
||||
using extract_clause_t = typename extract_clause<Statement>::type;
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user