mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-16 12:51:13 +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>
|
template <typename Lhs, typename JoinType, typename Rhs, typename Condition>
|
||||||
struct provided_static_tables_of<join_t<Lhs, JoinType, Rhs, Condition>>
|
struct provided_static_tables_of<join_t<Lhs, JoinType, Rhs, Condition>>
|
||||||
{
|
{
|
||||||
using type = typename std::conditional<
|
using type =
|
||||||
is_dynamic<Rhs>::value,
|
detail::type_vector_cat_t<provided_static_tables_of_t<Lhs>, provided_static_tables_of_t<Rhs>>;
|
||||||
provided_static_tables_of_t<Lhs>,
|
|
||||||
detail::type_vector_cat_t<provided_static_tables_of_t<Lhs>, provided_static_tables_of_t<Rhs>>>::type;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Lhs, typename JoinType, typename Rhs, typename Condition>
|
template <typename Lhs, typename JoinType, typename Rhs, typename Condition>
|
||||||
@ -79,10 +77,10 @@ namespace sqlpp
|
|||||||
using type = detail::type_vector_cat_t<
|
using type = detail::type_vector_cat_t<
|
||||||
typename std::conditional<detail::type_vector<right_outer_join_t, full_outer_join_t>::contains<JoinType>::value,
|
typename std::conditional<detail::type_vector<right_outer_join_t, full_outer_join_t>::contains<JoinType>::value,
|
||||||
provided_tables_of_t<Lhs>,
|
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,
|
typename std::conditional<detail::type_vector<left_outer_join_t, full_outer_join_t>::contains<JoinType>::value,
|
||||||
provided_tables_of_t<Rhs>,
|
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.
|
#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);
|
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)};
|
return schema_t{std::move(name)};
|
||||||
};
|
};
|
||||||
|
@ -64,11 +64,6 @@ namespace sqlpp
|
|||||||
using type = sqlpp::detail::type_vector<table_t<TableSpec>>;
|
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>
|
template <typename Context, typename TableSpec>
|
||||||
auto to_sql_string(Context& context, const table_t<TableSpec>& /*unused*/) -> std::string
|
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>>;
|
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>
|
template <typename Context, typename TableSpec, typename NameTag>
|
||||||
auto to_sql_string(Context& context, const table_as_t<TableSpec, NameTag>&) -> std::string
|
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>>;
|
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?
|
#warning: Should enough if with_t provides ctes?
|
||||||
template <typename NameTagProvider, typename Statement, typename... ColumnSpecs>
|
template <typename NameTagProvider, typename Statement, typename... ColumnSpecs>
|
||||||
struct provided_ctes_of<cte_t<NameTagProvider, Statement, 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>>;
|
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>
|
template <typename Context, typename NameTagProvider, typename Statement, typename... ColumnSpecs>
|
||||||
auto to_sql_string(Context& context, const cte_t<NameTagProvider, Statement, ColumnSpecs...>& t) -> std::string
|
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>>;
|
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>
|
template<typename NameTagProvider>
|
||||||
struct required_ctes_of<cte_ref_t<NameTagProvider>>
|
struct required_ctes_of<cte_ref_t<NameTagProvider>>
|
||||||
{
|
{
|
||||||
|
@ -71,6 +71,16 @@ namespace sqlpp
|
|||||||
using type = detail::type_vector<Table>;
|
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(
|
SQLPP_PORTABLE_STATIC_ASSERT(
|
||||||
assert_from_not_pre_join_t,
|
assert_from_not_pre_join_t,
|
||||||
"from() argument is a pre join, please use an explicit on() condition or unconditionally()");
|
"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>;
|
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_t, "into() required");
|
||||||
|
|
||||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_into_arg_is_table, "argument for into() must be a table");
|
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>
|
template <typename Select, typename NameTagProvider, typename... FieldSpecs>
|
||||||
struct provided_tables_of<select_as_t<Select, NameTagProvider, FieldSpecs...>>
|
struct provided_tables_of<select_as_t<Select, NameTagProvider, FieldSpecs...>>
|
||||||
: public std::conditional<Select::_can_be_used_as_table(),
|
: 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<>>
|
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: 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 required tables of
|
||||||
|
#warning: Need to add nodes to allow for parameters to be used.
|
||||||
|
|
||||||
template <typename Context, typename Select, typename NameTagProvider, typename... FieldSpecs>
|
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
|
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>;
|
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");
|
SQLPP_PORTABLE_STATIC_ASSERT(assert_update_table_arg_is_table_t, "argument for update() must be a table");
|
||||||
template <typename Table>
|
template <typename Table>
|
||||||
struct check_update_table
|
struct check_update_table
|
||||||
|
@ -92,7 +92,7 @@ namespace sqlpp
|
|||||||
template <typename L, typename R>
|
template <typename L, typename R>
|
||||||
using check_arithmetic_args = ::sqlpp::enable_if_t<is_numeric<L>::value and is_numeric<R>::value>;
|
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>
|
template <typename Operator, typename L, typename R>
|
||||||
struct arithmetic_value_type
|
struct arithmetic_value_type
|
||||||
{
|
{
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* 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/type_traits.h>
|
||||||
#include <sqlpp11/core/operator/assign_expression.h>
|
#include <sqlpp11/core/operator/assign_expression.h>
|
||||||
#include <sqlpp11/core/operator/sort_order_expression.h>
|
#include <sqlpp11/core/operator/sort_order_expression.h>
|
||||||
@ -58,7 +59,7 @@ namespace sqlpp
|
|||||||
template <typename Expr>
|
template <typename Expr>
|
||||||
struct nodes_of<dynamic_t<Expr>>
|
struct nodes_of<dynamic_t<Expr>>
|
||||||
{
|
{
|
||||||
using type = Expr;
|
using type = detail::type_vector<Expr>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
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/type_traits/nodes_of.h>
|
||||||
#include <sqlpp11/core/detail/type_vector.h>
|
#include <sqlpp11/core/detail/type_vector.h>
|
||||||
|
#include <sqlpp11/core/query/dynamic_fwd.h>
|
||||||
|
|
||||||
namespace sqlpp
|
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
|
// column_t or other structs that might reference a table shall specialize this template to indicate their table
|
||||||
// requirement.
|
// requirement.
|
||||||
// Dynamic parts of a query shall wrap their required tables in dynamic_t.
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct required_tables_of
|
struct required_tables_of
|
||||||
{
|
{
|
||||||
@ -50,12 +50,23 @@ namespace sqlpp
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
using required_tables_of_t = typename required_tables_of<T>::type;
|
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>
|
template<typename T>
|
||||||
struct required_static_tables_of
|
struct required_static_tables_of
|
||||||
{
|
{
|
||||||
using type = typename required_static_tables_of<nodes_of_t<T>>::type;
|
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>
|
template<typename... T>
|
||||||
struct required_static_tables_of<detail::type_vector<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;
|
using required_static_tables_of_t = typename required_static_tables_of<T>::type;
|
||||||
|
|
||||||
#warning: need type tests...
|
#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 a clause, e.g. by FROM.
|
||||||
|
|
||||||
// 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.
|
|
||||||
// table_t, cte_ref_t, or other structs that might provide a table in a query need to specialize this template.
|
// 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>
|
template <typename T>
|
||||||
struct provided_tables_of
|
struct provided_tables_of
|
||||||
{
|
{
|
||||||
using type = typename provided_tables_of<nodes_of_t<T>>::type;
|
using type = detail::type_vector<>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename... T>
|
template <typename T>
|
||||||
struct provided_tables_of<detail::type_vector<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>
|
template <typename T>
|
||||||
using provided_tables_of_t = typename provided_tables_of<T>::type;
|
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>
|
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>
|
template <typename T>
|
||||||
struct provided_static_tables_of<detail::type_vector<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>
|
template <typename T>
|
||||||
using provided_static_tables_of_t = typename provided_static_tables_of<T>::type;
|
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>
|
template <typename T>
|
||||||
struct provided_optional_tables_of
|
struct provided_optional_tables_of
|
||||||
{
|
{
|
||||||
using type = typename provided_optional_tables_of<nodes_of_t<T>>::type;
|
using type = detail::type_vector<>;
|
||||||
};
|
|
||||||
|
|
||||||
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...>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using provided_optional_tables_of_t = typename provided_optional_tables_of<T>::type;
|
using provided_optional_tables_of_t = typename provided_optional_tables_of<T>::type;
|
||||||
|
|
||||||
static_assert(provided_tables_of_t<int>::empty(), "");
|
|
||||||
|
|
||||||
} // namespace sqlpp
|
} // namespace sqlpp
|
||||||
|
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Sample.h"
|
#include "Sample.h"
|
||||||
#include "../compare.h"
|
|
||||||
#include <sqlpp11/sqlpp11.h>
|
#include <sqlpp11/sqlpp11.h>
|
||||||
|
|
||||||
int main(int, char* [])
|
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::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_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_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_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, "");
|
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 "Sample.h"
|
||||||
#include <sqlpp11/sqlpp11.h>
|
#include <sqlpp11/sqlpp11.h>
|
||||||
|
#include "../../../include/test_helpers.h"
|
||||||
|
|
||||||
void test_from()
|
void test_from()
|
||||||
{
|
{
|
||||||
@ -36,10 +37,11 @@ void test_from()
|
|||||||
// FROM CTE
|
// FROM CTE
|
||||||
{
|
{
|
||||||
auto x = cte(sqlpp::alias::x).as(select(foo.id).from(foo).unconditionally());
|
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 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::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, "");
|
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 "Sample.h"
|
||||||
#include <sqlpp11/sqlpp11.h>
|
#include <sqlpp11/sqlpp11.h>
|
||||||
|
#include "../../../include/test_helpers.h"
|
||||||
|
|
||||||
SQLPP_CREATE_NAME_TAG(cheese);
|
SQLPP_CREATE_NAME_TAG(cheese);
|
||||||
|
|
||||||
@ -45,7 +46,8 @@ void test_into()
|
|||||||
|
|
||||||
// Valid into clause
|
// 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_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_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, "");
|
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 "Sample.h"
|
||||||
#include <sqlpp11/sqlpp11.h>
|
#include <sqlpp11/sqlpp11.h>
|
||||||
|
#include "../../../include/test_helpers.h"
|
||||||
|
|
||||||
SQLPP_CREATE_NAME_TAG(cheese);
|
SQLPP_CREATE_NAME_TAG(cheese);
|
||||||
|
|
||||||
@ -45,7 +46,8 @@ void test_single_table()
|
|||||||
|
|
||||||
// Valid single table clause
|
// 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_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_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, "");
|
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()
|
endfunction()
|
||||||
|
|
||||||
test_compile(aggregates)
|
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>
|
template <typename T>
|
||||||
struct is_optional<::sqlpp::optional<T>> : public std::true_type{};
|
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