mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-16 12:51:13 +08:00
Rewrite select_as and add type tests
This commit is contained in:
parent
4630bf7f0c
commit
5578cce232
@ -67,7 +67,8 @@ namespace sqlpp
|
|||||||
template <typename T = _table>
|
template <typename T = _table>
|
||||||
auto table() const -> _table
|
auto table() const -> _table
|
||||||
{
|
{
|
||||||
static_assert(is_table_t<T>::value, "cannot call get_table for columns of a sub-selects or cte");
|
#warning: subselects use pseudo-columns, cte should do the same, I guess?
|
||||||
|
static_assert(is_table<T>::value, "cannot call get_table for columns of a sub-select or cte");
|
||||||
return _table{};
|
return _table{};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ namespace sqlpp
|
|||||||
template <typename AliasProvider, typename Statement, typename... FieldSpecs>
|
template <typename AliasProvider, typename Statement, typename... FieldSpecs>
|
||||||
struct cte_t : public cte_base<AliasProvider, FieldSpecs>::type...
|
struct cte_t : public cte_base<AliasProvider, FieldSpecs>::type...
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_cte, tag::is_table>; // FIXME: is table? really?
|
using _traits = make_traits<no_value_t, tag::is_cte>;
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
using _provided_tables = detail::type_set<cte_t>;
|
using _provided_tables = detail::type_set<cte_t>;
|
||||||
using _required_ctes = detail::make_joined_set_t<required_ctes_of<Statement>, detail::type_set<AliasProvider>>;
|
using _required_ctes = detail::make_joined_set_t<required_ctes_of<Statement>, detail::type_set<AliasProvider>>;
|
||||||
@ -216,8 +216,16 @@ namespace sqlpp
|
|||||||
Statement _statement;
|
Statement _statement;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename AliasProvider, typename Statement, typename... ColumnSpecs>
|
#warning: is table? really?
|
||||||
struct name_tag_of<cte_t<AliasProvider, Statement, ColumnSpecs...>> : public name_tag_of<AliasProvider>{};
|
template <typename AliasProvider, typename Statement, typename... ColumnSpecs>
|
||||||
|
struct is_table<cte_t<AliasProvider, Statement, ColumnSpecs...>> : public std::true_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename AliasProvider, typename Statement, typename... ColumnSpecs>
|
||||||
|
struct name_tag_of<cte_t<AliasProvider, Statement, ColumnSpecs...>> : public name_tag_of<AliasProvider>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
template <typename Context, typename AliasProvider, typename Statement, typename... ColumnSpecs>
|
template <typename Context, typename AliasProvider, typename Statement, typename... ColumnSpecs>
|
||||||
Context& serialize(Context& context, const cte_t<AliasProvider, Statement, ColumnSpecs...>& t)
|
Context& serialize(Context& context, const cte_t<AliasProvider, Statement, ColumnSpecs...>& t)
|
||||||
@ -235,7 +243,7 @@ namespace sqlpp
|
|||||||
template <typename AliasProvider>
|
template <typename AliasProvider>
|
||||||
struct cte_ref_t
|
struct cte_ref_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_alias, tag::is_cte, tag::is_table>; // FIXME: is table? really?
|
using _traits = make_traits<no_value_t, tag::is_alias, tag::is_cte>;
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
using _required_ctes = detail::make_type_set_t<AliasProvider>;
|
using _required_ctes = detail::make_type_set_t<AliasProvider>;
|
||||||
using _provided_tables = detail::type_set<AliasProvider>;
|
using _provided_tables = detail::type_set<AliasProvider>;
|
||||||
@ -253,7 +261,11 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename AliasProvider>
|
#warning: is table? really?
|
||||||
|
template<typename AliasProvider>
|
||||||
|
struct is_table<cte_ref_t<AliasProvider>> : public std::true_type{};
|
||||||
|
|
||||||
|
template<typename AliasProvider>
|
||||||
struct name_tag_of<cte_ref_t<AliasProvider>> : public name_tag_of<AliasProvider>{};
|
struct name_tag_of<cte_ref_t<AliasProvider>> : public name_tag_of<AliasProvider>{};
|
||||||
|
|
||||||
template <typename Context, typename AliasProvider>
|
template <typename Context, typename AliasProvider>
|
||||||
|
@ -98,9 +98,8 @@ namespace sqlpp
|
|||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
auto for_update() -> decltype(statement_t<no_for_update_t>().for_update())
|
||||||
auto for_update(T&& t) -> decltype(statement_t<no_for_update_t>().for_update(std::forward<T>(t)))
|
|
||||||
{
|
{
|
||||||
return statement_t<no_for_update_t>().for_update(std::forward<T>(t));
|
return statement_t<no_for_update_t>().for_update();
|
||||||
}
|
}
|
||||||
} // namespace sqlpp
|
} // namespace sqlpp
|
||||||
|
@ -78,7 +78,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
using type = static_combined_check_t<
|
using type = static_combined_check_t<
|
||||||
static_check_t<not is_pre_join_t<Table>::value, assert_from_not_pre_join_t>,
|
static_check_t<not is_pre_join_t<Table>::value, assert_from_not_pre_join_t>,
|
||||||
static_check_t<is_table_t<Table>::value, assert_from_table_t>,
|
static_check_t<is_table<Table>::value, assert_from_table_t>,
|
||||||
static_check_t<required_tables_of_t<Table>::size::value == 0, assert_from_dependency_free_t>,
|
static_check_t<required_tables_of_t<Table>::size::value == 0, assert_from_dependency_free_t>,
|
||||||
static_check_t<provided_tables_of<Table>::size::value ==
|
static_check_t<provided_tables_of<Table>::size::value ==
|
||||||
detail::make_name_of_set_t<provided_tables_of<Table>>::size::value,
|
detail::make_name_of_set_t<provided_tables_of<Table>>::size::value,
|
||||||
|
@ -35,7 +35,7 @@ namespace sqlpp
|
|||||||
template <typename PreJoin, typename On>
|
template <typename PreJoin, typename On>
|
||||||
struct join_t
|
struct join_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_table, tag::is_join>;
|
using _traits = make_traits<no_value_t, tag::is_join>;
|
||||||
using _nodes = detail::type_vector<PreJoin, On>;
|
using _nodes = detail::type_vector<PreJoin, On>;
|
||||||
using _can_be_null = std::false_type;
|
using _can_be_null = std::false_type;
|
||||||
using _provided_tables = provided_tables_of<PreJoin>;
|
using _provided_tables = provided_tables_of<PreJoin>;
|
||||||
@ -81,6 +81,9 @@ namespace sqlpp
|
|||||||
On _on;
|
On _on;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename PreJoin, typename On>
|
||||||
|
struct is_table<join_t<PreJoin, On>> : public std::true_type{};
|
||||||
|
|
||||||
template <typename Context, typename PreJoin, typename On>
|
template <typename Context, typename PreJoin, typename On>
|
||||||
Context& serialize(Context& context, const join_t<PreJoin, On>& t)
|
Context& serialize(Context& context, const join_t<PreJoin, On>& t)
|
||||||
{
|
{
|
||||||
|
@ -56,6 +56,15 @@ namespace sqlpp
|
|||||||
std::string _verbatim_lhs, _verbatim_rhs;
|
std::string _verbatim_lhs, _verbatim_rhs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename ValueType, typename Expr>
|
||||||
|
struct value_type_of<parameterized_verbatim_t<ValueType, Expr>>
|
||||||
|
{
|
||||||
|
using type = ValueType;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename ValueType, typename Expr>
|
||||||
|
struct nodes_of<parameterized_verbatim_t<ValueType, Expr>> : public nodes_of<Expr>{};
|
||||||
|
|
||||||
template <typename Context, typename ValueType, typename Expr>
|
template <typename Context, typename ValueType, typename Expr>
|
||||||
Context& serialize(Context& context, const parameterized_verbatim_t<ValueType, Expr>& t)
|
Context& serialize(Context& context, const parameterized_verbatim_t<ValueType, Expr>& t)
|
||||||
{
|
{
|
||||||
|
@ -42,8 +42,8 @@ namespace sqlpp
|
|||||||
struct check_pre_join
|
struct check_pre_join
|
||||||
{
|
{
|
||||||
using type = static_combined_check_t<
|
using type = static_combined_check_t<
|
||||||
static_check_t<is_table_t<Lhs>::value, assert_pre_join_lhs_table_t>,
|
static_check_t<is_table<Lhs>::value, assert_pre_join_lhs_table_t>,
|
||||||
static_check_t<is_table_t<Rhs>::value, assert_pre_join_rhs_table_t>,
|
static_check_t<is_table<Rhs>::value, assert_pre_join_rhs_table_t>,
|
||||||
static_check_t<not is_join_t<Rhs>::value, assert_pre_join_rhs_no_join_t>,
|
static_check_t<not is_join_t<Rhs>::value, assert_pre_join_rhs_no_join_t>,
|
||||||
static_check_t<detail::is_disjunct_from<detail::make_name_of_set_t<provided_tables_of<Lhs>>,
|
static_check_t<detail::is_disjunct_from<detail::make_name_of_set_t<provided_tables_of<Lhs>>,
|
||||||
detail::make_name_of_set_t<provided_tables_of<Rhs>>>::value,
|
detail::make_name_of_set_t<provided_tables_of<Rhs>>>::value,
|
||||||
@ -93,8 +93,8 @@ namespace sqlpp
|
|||||||
using _can_be_null = std::false_type;
|
using _can_be_null = std::false_type;
|
||||||
using _provided_outer_tables = typename JoinType::template _provided_outer_tables<Lhs, Rhs>;
|
using _provided_outer_tables = typename JoinType::template _provided_outer_tables<Lhs, Rhs>;
|
||||||
|
|
||||||
static_assert(is_table_t<Lhs>::value, "lhs argument for join() has to be a table or join");
|
static_assert(is_table<Lhs>::value, "lhs argument for join() has to be a table or join");
|
||||||
static_assert(is_table_t<Rhs>::value, "rhs argument for join() has to be a table");
|
static_assert(is_table<Rhs>::value, "rhs argument for join() has to be a table");
|
||||||
static_assert(not is_join_t<Rhs>::value, "rhs argument for join must not be a join");
|
static_assert(not is_join_t<Rhs>::value, "rhs argument for join must not be a join");
|
||||||
|
|
||||||
static_assert(detail::is_disjunct_from<provided_tables_of<Lhs>, provided_tables_of<Rhs>>::value,
|
static_assert(detail::is_disjunct_from<provided_tables_of<Lhs>, provided_tables_of<Rhs>>::value,
|
||||||
|
@ -40,7 +40,7 @@ namespace sqlpp
|
|||||||
template <typename Table>
|
template <typename Table>
|
||||||
struct schema_qualified_table_t
|
struct schema_qualified_table_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<value_type_of_t<Table>, tag::is_table>;
|
using _traits = make_traits<value_type_of_t<Table>>;
|
||||||
|
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
using _required_ctes = detail::type_set<>;
|
using _required_ctes = detail::type_set<>;
|
||||||
@ -61,6 +61,9 @@ namespace sqlpp
|
|||||||
Table _table;
|
Table _table;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename Table>
|
||||||
|
struct is_table<schema_qualified_table_t<Table>> : public std::true_type {};
|
||||||
|
|
||||||
template <typename Context, typename Table>
|
template <typename Context, typename Table>
|
||||||
Context& serialize(Context& context, const schema_qualified_table_t<Table>& t)
|
Context& serialize(Context& context, const schema_qualified_table_t<Table>& t)
|
||||||
{
|
{
|
||||||
|
92
include/sqlpp11/select_as.h
Normal file
92
include/sqlpp11/select_as.h
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2016, 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 <sqlpp11/type_traits.h>
|
||||||
|
#include <sqlpp11/enable_as.h>
|
||||||
|
|
||||||
|
namespace sqlpp
|
||||||
|
{
|
||||||
|
// pseudo_column_t is the column of a sub-select used as a table, for instance.
|
||||||
|
#warning: Maybe use this for CTE as well
|
||||||
|
#warning: Should be in its own header
|
||||||
|
template <typename TableAliasProvider, typename ColumnSpec>
|
||||||
|
struct pseudo_column_t : public enable_as<pseudo_column_t<TableAliasProvider, ColumnSpec>>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
template <typename TableAliasProvider, typename ColumnSpec>
|
||||||
|
struct name_tag_of<pseudo_column_t<TableAliasProvider, ColumnSpec>> : public name_tag_of<ColumnSpec>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename TableAliasProvider, typename ColumnSpec>
|
||||||
|
struct value_type_of<pseudo_column_t<TableAliasProvider, ColumnSpec>> : public value_type_of<ColumnSpec>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Select, typename AliasProvider, typename... ColumnSpecs>
|
||||||
|
struct select_as_t
|
||||||
|
: public ColumnSpecs::_alias_t::template _member_t<pseudo_column_t<AliasProvider, ColumnSpecs>>...
|
||||||
|
{
|
||||||
|
select_as_t(Select select) : _select(select)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
select_as_t(const select_as_t& rhs) = default;
|
||||||
|
select_as_t(select_as_t&& rhs) = default;
|
||||||
|
select_as_t& operator=(const select_as_t& rhs) = default;
|
||||||
|
select_as_t& operator=(select_as_t&& rhs) = default;
|
||||||
|
~select_as_t() = default;
|
||||||
|
|
||||||
|
Select _select;
|
||||||
|
};
|
||||||
|
|
||||||
|
// The Select expression has a value in case it has just one column selected.
|
||||||
|
template<typename Select, typename AliasProvider, typename ColumnSpec>
|
||||||
|
struct value_type_of<select_as_t<Select, AliasProvider, ColumnSpec>> : value_type_of<Select> {};
|
||||||
|
|
||||||
|
template<typename Select, typename AliasProvider, typename... ColumnSpecs>
|
||||||
|
struct name_tag_of<select_as_t<Select, AliasProvider, ColumnSpecs...>> : name_tag_of<AliasProvider> {};
|
||||||
|
|
||||||
|
#warning: Is this (_can_be_used_as_table) required for use as a named value, too?
|
||||||
|
template <typename Select, typename AliasProvider, typename... ColumnSpecs>
|
||||||
|
struct is_table<select_as_t<Select, AliasProvider, ColumnSpecs...>>
|
||||||
|
: std::integral_constant<bool, Select::_can_be_used_as_table()>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
#warning: V1.0 has empty nodes. Is that correct? In either case document the decision here.
|
||||||
|
|
||||||
|
|
||||||
|
template <typename Context, typename Select, typename AliasProvider, typename... ColumnSpecs>
|
||||||
|
Context& serialize(Context& context, const select_as_t<Select, AliasProvider, ColumnSpecs...>& t)
|
||||||
|
{
|
||||||
|
#warning: add AS Alias
|
||||||
|
serialize(context, t._select);
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
} // namespace sqlpp
|
@ -32,7 +32,7 @@
|
|||||||
#include <sqlpp11/interpret_tuple.h>
|
#include <sqlpp11/interpret_tuple.h>
|
||||||
#include <sqlpp11/policy_update.h>
|
#include <sqlpp11/policy_update.h>
|
||||||
#include <sqlpp11/result_row.h>
|
#include <sqlpp11/result_row.h>
|
||||||
#include <sqlpp11/select_pseudo_table.h>
|
#include <sqlpp11/select_as.h>
|
||||||
#include <sqlpp11/table.h>
|
#include <sqlpp11/table.h>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
@ -78,6 +78,22 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
|
// FIXME: We might use field specs here (same as with cte)
|
||||||
|
//
|
||||||
|
// provide type information for sub-selects that are used as named expressions or tables
|
||||||
|
template <typename Select, typename Column>
|
||||||
|
struct select_column_spec_t: public name_tag_base
|
||||||
|
{
|
||||||
|
using _alias_t = name_tag_of_t<Column>;
|
||||||
|
|
||||||
|
#warning: Need to test this!
|
||||||
|
static constexpr bool _depends_on_outer_table =
|
||||||
|
detail::make_intersect_set_t<required_tables_of_t<Column>, typename Select::_used_outer_tables>::size::value >
|
||||||
|
0;
|
||||||
|
};
|
||||||
|
template <typename Select, typename Column>
|
||||||
|
struct value_type_of<select_column_spec_t<Select, Column>> : public value_type_of<Column> {};
|
||||||
|
|
||||||
SQLPP_PORTABLE_STATIC_ASSERT(
|
SQLPP_PORTABLE_STATIC_ASSERT(
|
||||||
assert_no_unknown_tables_in_selected_columns_t,
|
assert_no_unknown_tables_in_selected_columns_t,
|
||||||
"at least one selected column requires a table which is otherwise not known in the statement");
|
"at least one selected column requires a table which is otherwise not known in the statement");
|
||||||
@ -158,25 +174,12 @@ namespace sqlpp
|
|||||||
using _result_row_t = result_row_t<Db, _field_t<Db, Columns>...>;
|
using _result_row_t = result_row_t<Db, _field_t<Db, Columns>...>;
|
||||||
|
|
||||||
template <typename AliasProvider>
|
template <typename AliasProvider>
|
||||||
struct _deferred_table_t
|
auto as(const AliasProvider& aliasProvider) const
|
||||||
{
|
-> select_as_t<_statement_t, AliasProvider, select_column_spec_t<_statement_t, Columns>...>
|
||||||
using table = select_pseudo_table_t<_statement_t, Columns...>;
|
|
||||||
using alias = typename table::template _alias_t<AliasProvider>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename AliasProvider>
|
|
||||||
using _table_t = typename _deferred_table_t<AliasProvider>::table;
|
|
||||||
|
|
||||||
template <typename AliasProvider>
|
|
||||||
using _alias_t = typename _deferred_table_t<AliasProvider>::alias;
|
|
||||||
|
|
||||||
template <typename AliasProvider>
|
|
||||||
_alias_t<AliasProvider> as(const AliasProvider& aliasProvider) const
|
|
||||||
{
|
{
|
||||||
consistency_check_t<_statement_t>::verify();
|
consistency_check_t<_statement_t>::verify();
|
||||||
static_assert(_statement_t::_can_be_used_as_table(),
|
using table = select_as_t<_statement_t, AliasProvider, select_column_spec_t<_statement_t, Columns>...>;
|
||||||
"statement cannot be used as table, e.g. due to missing tables");
|
return table(_get_statement());
|
||||||
return _table_t<AliasProvider>(_get_statement()).as(aliasProvider);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t get_no_of_result_columns() const
|
size_t get_no_of_result_columns() const
|
||||||
|
@ -1,100 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2013-2016, 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 <sqlpp11/type_traits.h>
|
|
||||||
#include <sqlpp11/table.h>
|
|
||||||
|
|
||||||
namespace sqlpp
|
|
||||||
{
|
|
||||||
// FIXME: We might use field specs here (same as with cte)
|
|
||||||
//
|
|
||||||
// provide type information for sub-selects that are used as named expressions or tables
|
|
||||||
template <typename Select, typename NamedExpr>
|
|
||||||
struct select_column_spec_t: public name_tag_base
|
|
||||||
{
|
|
||||||
using _alias_t = name_tag_of_t<NamedExpr>;
|
|
||||||
using has_default = std::false_type;
|
|
||||||
|
|
||||||
static constexpr bool _depends_on_outer_table =
|
|
||||||
detail::make_intersect_set_t<required_tables_of_t<NamedExpr>, typename Select::_used_outer_tables>::size::value >
|
|
||||||
0;
|
|
||||||
|
|
||||||
#warning: somehow prevent insert...
|
|
||||||
#warning: may need to make value type optional for outer tables
|
|
||||||
using _traits = make_traits<value_type_of_t<NamedExpr>/*,
|
|
||||||
tag_if<tag::can_be_null, _depends_on_outer_table>*/>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename... NamedExpr>
|
|
||||||
struct select_expression_type {
|
|
||||||
using value_t = no_value_t;
|
|
||||||
static constexpr bool _is_expression = false;
|
|
||||||
static constexpr bool _can_be_null = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename NamedExpr>
|
|
||||||
struct select_expression_type<NamedExpr> {
|
|
||||||
using value_t = value_type_of_t<NamedExpr>;
|
|
||||||
static constexpr bool _is_expression = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Select, typename... NamedExpr>
|
|
||||||
struct select_pseudo_table_t
|
|
||||||
: public table_t<select_pseudo_table_t<Select, NamedExpr...>, select_column_spec_t<Select, NamedExpr>...>
|
|
||||||
{
|
|
||||||
using _expr_t = select_expression_type<NamedExpr...>;
|
|
||||||
using _traits = make_traits<
|
|
||||||
// Usage as named expression
|
|
||||||
typename _expr_t::value_t,
|
|
||||||
tag_if<tag::is_expression, _expr_t::_is_expression>,
|
|
||||||
// Usage as table
|
|
||||||
tag::is_table,
|
|
||||||
tag::is_pseudo_table,
|
|
||||||
tag_if<tag::requires_parens, requires_parens_t<Select>::value>>;
|
|
||||||
using _nodes = detail::type_vector<>;
|
|
||||||
|
|
||||||
select_pseudo_table_t(Select select) : _select(select)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
select_pseudo_table_t(const select_pseudo_table_t& rhs) = default;
|
|
||||||
select_pseudo_table_t(select_pseudo_table_t&& rhs) = default;
|
|
||||||
select_pseudo_table_t& operator=(const select_pseudo_table_t& rhs) = default;
|
|
||||||
select_pseudo_table_t& operator=(select_pseudo_table_t&& rhs) = default;
|
|
||||||
~select_pseudo_table_t() = default;
|
|
||||||
|
|
||||||
Select _select;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Context, typename Select, typename... NamedExpr>
|
|
||||||
Context& serialize(Context& context, const select_pseudo_table_t<Select, NamedExpr...>& t)
|
|
||||||
{
|
|
||||||
serialize(context, t._select);
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
} // namespace sqlpp
|
|
@ -57,7 +57,8 @@ namespace sqlpp
|
|||||||
using _traits = make_traits<no_value_t, tag::is_single_table>;
|
using _traits = make_traits<no_value_t, tag::is_single_table>;
|
||||||
using _nodes = detail::type_vector<Table>;
|
using _nodes = detail::type_vector<Table>;
|
||||||
|
|
||||||
static_assert(is_table_t<Table>::value, "argument has to be a table");
|
#warning: can't we do this with a table_t<> specialization
|
||||||
|
static_assert(is_table<Table>::value, "argument has to be a table");
|
||||||
static_assert(required_tables_of_t<Table>::size::value == 0, "table depends on another table");
|
static_assert(required_tables_of_t<Table>::size::value == 0, "table depends on another table");
|
||||||
|
|
||||||
using _data_t = single_table_data_t<Table>;
|
using _data_t = single_table_data_t<Table>;
|
||||||
@ -84,7 +85,7 @@ namespace sqlpp
|
|||||||
template <typename Table>
|
template <typename Table>
|
||||||
struct check_update_table
|
struct check_update_table
|
||||||
{
|
{
|
||||||
using type = static_combined_check_t<static_check_t<is_table_t<Table>::value, assert_update_table_arg_is_table_t>>;
|
using type = static_combined_check_t<static_check_t<is_table<Table>::value, assert_update_table_arg_is_table_t>>;
|
||||||
};
|
};
|
||||||
template <typename Table>
|
template <typename Table>
|
||||||
using check_update_table_t = typename check_update_table<Table>::type;
|
using check_update_table_t = typename check_update_table<Table>::type;
|
||||||
|
@ -41,7 +41,7 @@ namespace sqlpp
|
|||||||
template <typename Table, typename... ColumnSpec>
|
template <typename Table, typename... ColumnSpec>
|
||||||
struct table_t : public ColumnSpec::_alias_t::template _member_t<column_t<Table, ColumnSpec>>...
|
struct table_t : public ColumnSpec::_alias_t::template _member_t<column_t<Table, ColumnSpec>>...
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_raw_table, tag::is_table>;
|
using _traits = make_traits<no_value_t, tag::is_raw_table>;
|
||||||
|
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
using _provided_tables = detail::type_set<Table>;
|
using _provided_tables = detail::type_set<Table>;
|
||||||
@ -102,6 +102,9 @@ namespace sqlpp
|
|||||||
template <typename Table, typename... ColumnSpec>
|
template <typename Table, typename... ColumnSpec>
|
||||||
struct name_tag_of<table_t<Table, ColumnSpec...>>: public name_tag_of<Table> {};
|
struct name_tag_of<table_t<Table, ColumnSpec...>>: public name_tag_of<Table> {};
|
||||||
|
|
||||||
|
template <typename Table, typename... ColumnSpec>
|
||||||
|
struct is_table<table_t<Table, ColumnSpec...>>: public std::true_type {};
|
||||||
|
|
||||||
template <typename Context, typename Table, typename... ColumnSpec>
|
template <typename Context, typename Table, typename... ColumnSpec>
|
||||||
Context& serialize(Context& context, const table_t<Table, ColumnSpec...>& /*unused*/)
|
Context& serialize(Context& context, const table_t<Table, ColumnSpec...>& /*unused*/)
|
||||||
{
|
{
|
||||||
|
@ -42,7 +42,6 @@ namespace sqlpp
|
|||||||
struct table_alias_t : public ColumnSpec::_alias_t::template _member_t<column_t<AliasProvider, ColumnSpec>>...
|
struct table_alias_t : public ColumnSpec::_alias_t::template _member_t<column_t<AliasProvider, ColumnSpec>>...
|
||||||
{
|
{
|
||||||
using _traits = make_traits<value_type_of_t<Table>,
|
using _traits = make_traits<value_type_of_t<Table>,
|
||||||
tag::is_table,
|
|
||||||
tag::is_alias,
|
tag::is_alias,
|
||||||
tag_if<tag::is_selectable, is_expression_t<Table>::value>>;
|
tag_if<tag::is_selectable, is_expression_t<Table>::value>>;
|
||||||
|
|
||||||
@ -97,6 +96,9 @@ namespace sqlpp
|
|||||||
Table _table;
|
Table _table;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename AliasProvider, typename Table, typename... ColumnSpec>
|
||||||
|
struct is_table<table_alias_t<AliasProvider, Table, ColumnSpec...>> : public std::true_type{};
|
||||||
|
|
||||||
template<typename AliasProvider, typename Table, typename... ColumnSpec>
|
template<typename AliasProvider, typename Table, typename... ColumnSpec>
|
||||||
struct name_tag_of<table_alias_t<AliasProvider, Table, ColumnSpec...>> : public name_tag_of<AliasProvider>{};
|
struct name_tag_of<table_alias_t<AliasProvider, Table, ColumnSpec...>> : public name_tag_of<AliasProvider>{};
|
||||||
|
|
||||||
|
@ -462,7 +462,6 @@ namespace sqlpp
|
|||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_noop)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_noop)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_missing)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_missing)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_return_value)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_return_value)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_table)
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_raw_table)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_raw_table)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_pre_join)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_pre_join)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_join)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_join)
|
||||||
@ -736,6 +735,9 @@ namespace sqlpp
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
struct has_name : public std::integral_constant<bool, not std::is_same<name_tag_of_t<T>, no_name_t>::value> {};
|
struct has_name : public std::integral_constant<bool, not std::is_same<name_tag_of_t<T>, no_name_t>::value> {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_table : public std::false_type{};
|
||||||
|
|
||||||
template <typename ValueType, typename... Tags>
|
template <typename ValueType, typename... Tags>
|
||||||
struct make_traits
|
struct make_traits
|
||||||
{
|
{
|
||||||
|
@ -79,7 +79,7 @@ namespace sqlpp
|
|||||||
struct check_using
|
struct check_using
|
||||||
{
|
{
|
||||||
using type = static_combined_check_t<
|
using type = static_combined_check_t<
|
||||||
static_check_t<logic::all_t<is_table_t<Tables>::value...>::value, assert_using_args_are_tables_t>>;
|
static_check_t<logic::all_t<is_table<Tables>::value...>::value, assert_using_args_are_tables_t>>;
|
||||||
};
|
};
|
||||||
template <typename... Tables>
|
template <typename... Tables>
|
||||||
using check_using_t = typename check_using<Tables...>::type;
|
using check_using_t = typename check_using<Tables...>::type;
|
||||||
|
@ -31,6 +31,9 @@ int ForUpdate(int, char* [])
|
|||||||
{
|
{
|
||||||
const auto foo = test::TabFoo{};
|
const auto foo = test::TabFoo{};
|
||||||
|
|
||||||
|
compare(__LINE__, sqlpp::for_update(),
|
||||||
|
" FOR UPDATE ");
|
||||||
|
|
||||||
compare(__LINE__, select(foo.doubleN).from(foo).unconditionally().for_update(),
|
compare(__LINE__, select(foo.doubleN).from(foo).unconditionally().for_update(),
|
||||||
"SELECT tab_foo.double_n FROM tab_foo FOR UPDATE ");
|
"SELECT tab_foo.double_n FROM tab_foo FOR UPDATE ");
|
||||||
|
|
||||||
|
@ -32,12 +32,25 @@
|
|||||||
SQLPP_ALIAS_PROVIDER(id_count)
|
SQLPP_ALIAS_PROVIDER(id_count)
|
||||||
SQLPP_ALIAS_PROVIDER(cheese)
|
SQLPP_ALIAS_PROVIDER(cheese)
|
||||||
|
|
||||||
|
using namespace sqlpp;
|
||||||
|
|
||||||
int SelectAs(int, char*[])
|
int SelectAs(int, char*[])
|
||||||
{
|
{
|
||||||
const auto foo = test::TabFoo{};
|
const auto foo = test::TabFoo{};
|
||||||
const auto bar = test::TabBar{};
|
const auto bar = test::TabBar{};
|
||||||
|
|
||||||
// SELECT...AS as selectable column
|
// SELECT...AS as selectable column
|
||||||
|
//using S = table_alias_t<cheese_t, select_pseudo_table_t<statement_t<no_with_t, select_t, no_select_flag_list_t, select_column_list_t<as_expression<count_t<noop, column_t<test::TabBar, test::TabBar_::Id> >, id_count_t> >, from_t<test::TabBar>, where_t<unconditional_t>, no_group_by_t, no_having_t, no_order_by_t, no_limit_t, no_offset_t, no_union_t, no_for_update_t>, as_expression<count_t<noop, column_t<test::TabBar, test::TabBar_::Id> >, id_count_t> >, select_column_spec_t<statement_t<no_with_t, select_t, no_select_flag_list_t, select_column_list_t<as_expression<count_t<noop, column_t<test::TabBar, test::TabBar_::Id> >, id_count_t> >, from_t<test::TabBar>, where_t<unconditional_t>, no_group_by_t, no_having_t, no_order_by_t, no_limit_t, no_offset_t, no_union_t, no_for_update_t>, as_expression<count_t<noop, column_t<test::TabBar, test::TabBar_::Id> >, id_count_t> > >;
|
||||||
|
using S = select_pseudo_table_t<statement_t<no_with_t, select_t, no_select_flag_list_t, select_column_list_t<as_expression<count_t<noop, column_t<test::TabBar, test::TabBar_::Id> >, id_count_t> >, from_t<test::TabBar>, where_t<unconditional_t>, no_group_by_t, no_having_t, no_order_by_t, no_limit_t, no_offset_t, no_union_t, no_for_update_t>> ;
|
||||||
|
static_assert(sqlpp::has_value_type<S>::value, "");
|
||||||
|
/*
|
||||||
|
sqlpp::name_tag_of_t<decltype(select(count(bar.id).as(id_count)).from(bar).unconditionally())::_result_type_provider>::hansi;
|
||||||
|
sqlpp::value_type_of_t<decltype(select(count(bar.id).as(id_count)).from(bar).unconditionally())::_result_type_provider>::hansi;
|
||||||
|
static_assert(sqlpp::has_value_type<decltype(select(count(bar.id).as(id_count)).from(bar).unconditionally())>::value, "");
|
||||||
|
static_assert(sqlpp::has_name<decltype(select(count(bar.id).as(id_count)).from(bar).unconditionally())>::value, "");
|
||||||
|
*/
|
||||||
|
#error: The select itself should not offer an "as" that yields a value.
|
||||||
|
#error: The id_count should offer the alias that offers the value.
|
||||||
compare(__LINE__, select(foo.doubleN, select(count(bar.id).as(id_count)).from(bar).unconditionally().as(cheese)),
|
compare(__LINE__, select(foo.doubleN, select(count(bar.id).as(id_count)).from(bar).unconditionally().as(cheese)),
|
||||||
"SELECT tab_foo.double_n,(SELECT COUNT(tab_bar.id) AS id_count FROM tab_bar) AS cheese");
|
"SELECT tab_foo.double_n,(SELECT COUNT(tab_bar.id) AS id_count FROM tab_bar) AS cheese");
|
||||||
|
|
||||||
|
@ -42,5 +42,6 @@ test_compile(dynamic)
|
|||||||
test_compile(in_expression)
|
test_compile(in_expression)
|
||||||
test_compile(logical_expression)
|
test_compile(logical_expression)
|
||||||
test_compile(result_row)
|
test_compile(result_row)
|
||||||
|
test_compile(select_as)
|
||||||
test_compile(value)
|
test_compile(value)
|
||||||
|
|
||||||
|
157
tests/core/types/select_as.cpp
Normal file
157
tests/core/types/select_as.cpp
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
/*
|
||||||
|
* 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 "MockDb.h"
|
||||||
|
#include "Sample.h"
|
||||||
|
#include <sqlpp11/sqlpp11.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
auto db = MockDb{};
|
||||||
|
|
||||||
|
template <typename T, typename V>
|
||||||
|
using is_same_type = std::is_same<sqlpp::value_type_of_t<T>, V>;
|
||||||
|
}
|
||||||
|
|
||||||
|
SQLPP_ALIAS_PROVIDER(always);
|
||||||
|
SQLPP_ALIAS_PROVIDER(sometimes);
|
||||||
|
SQLPP_ALIAS_PROVIDER(column)
|
||||||
|
SQLPP_ALIAS_PROVIDER(table)
|
||||||
|
SQLPP_ALIAS_PROVIDER(foo)
|
||||||
|
|
||||||
|
template <typename Value>
|
||||||
|
void test_select_as(Value v)
|
||||||
|
{
|
||||||
|
auto v_not_null = sqlpp::value(v).as(always);
|
||||||
|
auto v_maybe_null = sqlpp::value(sqlpp::compat::make_optional(v)).as(sometimes);
|
||||||
|
|
||||||
|
using ValueType = sqlpp::value_type_of_t<Value>;
|
||||||
|
using OptValueType = sqlpp::value_type_of_t<sqlpp::compat::optional<Value>>;
|
||||||
|
|
||||||
|
// SINGLE VALUE
|
||||||
|
|
||||||
|
// A select of a single value can be used as a value.
|
||||||
|
static_assert(is_same_type<decltype(select(v_not_null)), ValueType>(), "");
|
||||||
|
static_assert(is_same_type<decltype(select(v_maybe_null)), OptValueType>(), "");
|
||||||
|
|
||||||
|
// A select of a single value can be named and used as a named value.
|
||||||
|
static_assert(sqlpp::has_name<decltype(select(v_not_null).as(column))>::value, "");
|
||||||
|
static_assert(sqlpp::has_name<decltype(select(v_maybe_null).as(column))>::value, "");
|
||||||
|
|
||||||
|
static_assert(is_same_type<decltype(select(v_not_null).as(column)), ValueType>(), "");
|
||||||
|
static_assert(is_same_type<decltype(select(v_maybe_null).as(column)), OptValueType>(), "");
|
||||||
|
|
||||||
|
// A select of a single value can be named and used as a pseudo table
|
||||||
|
static_assert(sqlpp::is_table<decltype(select(v_not_null).as(column))>::value, "");
|
||||||
|
static_assert(sqlpp::is_table<decltype(select(v_maybe_null).as(column))>::value, "");
|
||||||
|
|
||||||
|
// The column of a single-value pseudo table can be used as named value
|
||||||
|
static_assert(sqlpp::has_name<decltype(select(v_not_null).as(column).always)>::value, "");
|
||||||
|
static_assert(sqlpp::has_name<decltype(select(v_maybe_null).as(column).sometimes)>::value, "");
|
||||||
|
|
||||||
|
static_assert(is_same_type<decltype(select(v_not_null).as(column).always), ValueType>(), "");
|
||||||
|
static_assert(is_same_type<decltype(select(v_maybe_null).as(column).sometimes), OptValueType>(), "");
|
||||||
|
|
||||||
|
// The column of a single-value pseudo table can be renamed and used as named value
|
||||||
|
static_assert(sqlpp::has_name<decltype(select(v_not_null).as(column).always.as(foo))>::value, "");
|
||||||
|
static_assert(sqlpp::has_name<decltype(select(v_maybe_null).as(column).sometimes.as(foo))>::value, "");
|
||||||
|
|
||||||
|
static_assert(is_same_type<decltype(select(v_not_null).as(column).always.as(foo)), ValueType>(), "");
|
||||||
|
static_assert(is_same_type<decltype(select(v_maybe_null).as(column).sometimes.as(foo)), OptValueType>(), "");
|
||||||
|
|
||||||
|
#warning: implement
|
||||||
|
|
||||||
|
// MULTIPLE VALUES
|
||||||
|
#warning: write
|
||||||
|
|
||||||
|
// A select of multiple values can not be used as a value.
|
||||||
|
static_assert(not sqlpp::has_value_type<decltype(select(v_not_null, v_maybe_null))>::value, "");
|
||||||
|
|
||||||
|
// A select of multiple values can be named and used as a named value.
|
||||||
|
static_assert(sqlpp::has_name<decltype(select(v_not_null, v_maybe_null).as(column))>::value, "");
|
||||||
|
static_assert(not sqlpp::has_value_type<decltype(select(v_not_null, v_maybe_null).as(column))>::value, "");
|
||||||
|
|
||||||
|
// A select of multiple values can be named and used as a pseudo table
|
||||||
|
static_assert(sqlpp::is_table<decltype(select(v_not_null, v_maybe_null).as(table))>::value, "");
|
||||||
|
|
||||||
|
// The column of a multi-value pseudo table can be used as named value
|
||||||
|
static_assert(sqlpp::has_name<decltype(select(v_not_null, v_maybe_null).as(table).always)>::value, "");
|
||||||
|
static_assert(sqlpp::has_name<decltype(select(v_not_null, v_maybe_null).as(table).sometimes)>::value, "");
|
||||||
|
|
||||||
|
static_assert(is_same_type<decltype(select(v_not_null, v_maybe_null).as(table).always), ValueType>(), "");
|
||||||
|
static_assert(is_same_type<decltype(select(v_not_null, v_maybe_null).as(table).sometimes), OptValueType>(), "");
|
||||||
|
|
||||||
|
// The column of a multi-value pseudo table can be renamed and used as named value
|
||||||
|
static_assert(sqlpp::has_name<decltype(select(v_not_null, v_maybe_null).as(table).always.as(foo))>::value, "");
|
||||||
|
static_assert(sqlpp::has_name<decltype(select(v_not_null, v_maybe_null).as(table).sometimes.as(foo))>::value, "");
|
||||||
|
|
||||||
|
static_assert(is_same_type<decltype(select(v_not_null, v_maybe_null).as(table).always.as(foo)), ValueType>(), "");
|
||||||
|
static_assert(is_same_type<decltype(select(v_not_null, v_maybe_null).as(table).sometimes.as(foo)), OptValueType>(), "");
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// boolean
|
||||||
|
test_select_as(bool{true});
|
||||||
|
|
||||||
|
// integral
|
||||||
|
test_select_as(int8_t{7});
|
||||||
|
test_select_as(int16_t{7});
|
||||||
|
test_select_as(int32_t{7});
|
||||||
|
test_select_as(int64_t{7});
|
||||||
|
|
||||||
|
// unsigned integral
|
||||||
|
test_select_as(uint8_t{7});
|
||||||
|
test_select_as(uint16_t{7});
|
||||||
|
test_select_as(uint32_t{7});
|
||||||
|
test_select_as(uint64_t{7});
|
||||||
|
|
||||||
|
// floating point
|
||||||
|
test_select_as(float{7.7});
|
||||||
|
test_select_as(double{7.7});
|
||||||
|
|
||||||
|
// text
|
||||||
|
test_select_as('7');
|
||||||
|
test_select_as("seven");
|
||||||
|
test_select_as(std::string("seven"));
|
||||||
|
test_select_as(sqlpp::compat::string_view("seven"));
|
||||||
|
|
||||||
|
// blob
|
||||||
|
test_select_as(std::vector<uint8_t>{});
|
||||||
|
|
||||||
|
// date
|
||||||
|
test_select_as(::sqlpp::chrono::day_point{});
|
||||||
|
|
||||||
|
// timestamp
|
||||||
|
test_select_as(::sqlpp::chrono::microsecond_point{});
|
||||||
|
using minute_point = std::chrono::time_point<std::chrono::system_clock, std::chrono::minutes>;
|
||||||
|
test_select_as(minute_point{});
|
||||||
|
|
||||||
|
// time_of_day
|
||||||
|
test_select_as(std::chrono::microseconds{});
|
||||||
|
}
|
||||||
|
|
@ -187,5 +187,12 @@ int Select(int, char*[])
|
|||||||
std::cout << row.doubleN << " " << row.cheese << std::endl;
|
std::cout << row.doubleN << " " << row.cheese << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checking #584
|
||||||
|
auto abs = db.prepare(select(t.alpha).from(t).where(sqlpp::parameterized_verbatim<sqlpp::unsigned_integral>(
|
||||||
|
"ABS(field1 -", sqlpp::parameter(t.alpha), ")") <=
|
||||||
|
sqlpp::parameter(sqlpp::unsigned_integral(), param2)));
|
||||||
|
abs.params.alpha = 7;
|
||||||
|
abs.params.param2 = 7;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user