All statements back to composite design

The point is that even though the CRTP code looked nice, it was too hard
to comprehend.
This commit is contained in:
rbock
2014-02-09 23:30:30 +01:00
parent cc76820870
commit 22c43358f2
17 changed files with 543 additions and 417 deletions

View File

@@ -130,7 +130,7 @@ namespace sqlpp
void add_values(Args... args)
{
static_assert(is_column_list_t<InsertValueList>::value, "cannot call add_set() before columns()");
return _insert_value_list.add_columns(args...);
return _insert_value_list.add_values(args...);
}
// run and prepare

View File

@@ -107,6 +107,7 @@ namespace sqlpp
auto using_(Args... args)
-> _policies_update_t<vendor::no_using_t, vendor::using_t<void, Args...>>
{
static_assert(is_noop_t<Using>::value, "cannot call using_()/dynamic_using() twice");
return { *this, vendor::using_t<void, Args...>(args...) };
}
@@ -114,6 +115,7 @@ namespace sqlpp
auto dynamic_using(Args... args)
-> _policies_update_t<vendor::no_using_t, vendor::using_t<_database_t, Args...>>
{
static_assert(is_noop_t<Using>::value, "cannot call using_()/dynamic_using() twice");
static_assert(not std::is_same<_database_t, void>::value, "dynamic_using must not be called in a static statement");
return { *this, vendor::using_t<_database_t, Args...>(args...) };
}
@@ -122,6 +124,7 @@ namespace sqlpp
auto where(Args... args)
-> _policies_update_t<vendor::no_where_t, vendor::where_t<void, Args...>>
{
static_assert(is_noop_t<Where>::value, "cannot call where()/dynamic_where() twice");
return { *this, vendor::where_t<void, Args...>(args...) };
}
@@ -129,6 +132,7 @@ namespace sqlpp
auto dynamic_where(Args... args)
-> _policies_update_t<vendor::no_where_t, vendor::where_t<_database_t, Args...>>
{
static_assert(is_noop_t<Where>::value, "cannot call where()/dynamic_where() twice");
static_assert(not std::is_same<_database_t, void>::value, "dynamic_where must not be called in a static statement");
return { *this, vendor::where_t<_database_t, Args...>(args...) };
}

View File

@@ -55,74 +55,179 @@ namespace sqlpp
namespace detail
{
template<
typename FlagList,
typename ColumnList,
typename From,
typename Where,
typename GroupBy,
typename Having,
typename OrderBy,
typename Limit,
typename Offset
typename From
>
struct select_helper_t
{
using _column_list_t = ColumnList;
using _from_t = ColumnList;
static_assert(is_noop_t<ColumnList>::value or sqlpp::is_select_column_list_t<ColumnList>::value, "Yikes");
static_assert(is_noop_t<From>::value or sqlpp::is_from_t<From>::value, "Yikes");
using _value_type = typename std::conditional<
sqlpp::is_from_t<From>::value,
typename ColumnList::_value_type,
no_value_t // If there is no from, the select is not complete (this logic is a bit simple, but better than nothing)
>::type;
template<typename Database>
struct can_run_t
{
//static_assert(is_where_t<Where>::value, "cannot select remove without having a where condition, use .where(true) to remove all rows");
//static_assert(not vendor::is_noop<ColumnList>::value, "cannot run select without having selected anything");
//static_assert(is_from_t<From>::value, "cannot run select without a from()");
//static_assert(is_where_t<Where>::value, "cannot run select without having a where condition, use .where(true) to select all rows");
// FIXME: Check for missing aliases (if references are used)
// FIXME: Check for missing tables, well, actually, check for missing tables at the where(), order_by(), etc.
static constexpr bool value = true;
};
};
}
// SELECT
template<typename Database, typename... Policies>
struct select_t: public vendor::policy_t<Policies>..., public vendor::crtp_wrapper_t<select_t<Database, Policies...>, Policies>...,
public detail::select_helper_t<Policies...>::_value_type::template operators<select_t<Database, Policies...>>
template<typename Database = void,
typename FlagList = vendor::no_select_flag_list_t,
typename ColumnList = vendor::no_select_column_list_t,
typename From = vendor::no_from_t,
typename Where = vendor::no_where_t,
typename GroupBy = vendor::no_group_by_t,
typename Having = vendor::no_having_t,
typename OrderBy = vendor::no_order_by_t,
typename Limit = vendor::no_limit_t,
typename Offset = vendor::no_offset_t
>
struct select_t: public detail::select_helper_t<ColumnList, From>::_value_type::template operators<select_t<Database, FlagList, ColumnList, From, Where, GroupBy, Having, OrderBy, Limit, Offset>>
{
template<typename Needle, typename Replacement>
using _policy_update_t = select_t<Database, vendor::policy_update_t<Policies, Needle, Replacement>...>;
using _database_t = Database;
using _parameter_tuple_t = std::tuple<Policies...>;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
template<typename Needle, typename Replacement, typename... Policies>
struct _policies_update_impl
{
using type = select_t<Database, vendor::policy_update_t<Policies, Needle, Replacement>...>;
};
template<typename Needle, typename Replacement>
using _policies_update_t = typename _policies_update_impl<Needle, Replacement, FlagList, ColumnList, From, Where, GroupBy, Having, OrderBy, Limit, Offset>::type;
using _parameter_tuple_t = std::tuple<FlagList, ColumnList, From, Where, GroupBy, Having, OrderBy, Limit, Offset>;
using _parameter_list_t = typename make_parameter_list_t<select_t>::type;
using _column_list_t = typename detail::select_helper_t<Policies...>::_column_list_t;
using _column_list_t = ColumnList;
using _result_row_t = typename _column_list_t::_result_row_t;
using _dynamic_names_t = typename _column_list_t::_dynamic_names_t;
using _is_select = std::true_type;
using _requires_braces = std::true_type;
using _value_type = typename detail::select_helper_t<Policies...>::_value_type;
using _value_type = typename detail::select_helper_t<ColumnList, From>::_value_type;
using _name_t = typename _column_list_t::_name_t;
// Constructors
select_t()
{}
template<typename Whatever>
select_t(select_t r, Whatever whatever):
vendor::policy_t<Policies>(r, whatever)...
template<typename X>
select_t(X x, FlagList flag_list):
_flag_list(flag_list),
_column_list(x._column_list),
_from(x._from),
_where(x._where),
_group_by(x._group_by),
_having(x._having),
_order_by(x._order_by),
_limit(x._limit),
_offset(x._offset)
{}
template<typename Remove, typename Whatever>
select_t(Remove r, Whatever whatever):
vendor::policy_t<Policies>(r, whatever)...
template<typename X>
select_t(X x, ColumnList column_list):
_flag_list(x._flag_list),
_column_list(column_list),
_from(x._from),
_where(x._where),
_group_by(x._group_by),
_having(x._having),
_order_by(x._order_by),
_limit(x._limit),
_offset(x._offset)
{}
template<typename X>
select_t(X x, From from):
_flag_list(x._flag_list),
_column_list(x._column_list),
_from(from),
_where(x._where),
_group_by(x._group_by),
_having(x._having),
_order_by(x._order_by),
_limit(x._limit),
_offset(x._offset)
{}
template<typename X>
select_t(X x, Where where):
_flag_list(x._flag_list),
_column_list(x._column_list),
_from(x._from),
_where(where),
_group_by(x._group_by),
_having(x._having),
_order_by(x._order_by),
_limit(x._limit),
_offset(x._offset)
{}
template<typename X>
select_t(X x, GroupBy group_by):
_flag_list(x._flag_list),
_column_list(x._column_list),
_from(x._from),
_where(x._where),
_group_by(group_by),
_having(x._having),
_order_by(x._order_by),
_limit(x._limit),
_offset(x._offset)
{}
template<typename X>
select_t(X x, Having having):
_flag_list(x._flag_list),
_column_list(x._column_list),
_from(x._from),
_where(x._where),
_group_by(x._group_by),
_having(having),
_order_by(x._order_by),
_limit(x._limit),
_offset(x._offset)
{}
template<typename X>
select_t(X x, OrderBy order_by):
_flag_list(x._flag_list),
_column_list(x._column_list),
_from(x._from),
_where(x._where),
_group_by(x._group_by),
_having(x._having),
_order_by(order_by),
_limit(x._limit),
_offset(x._offset)
{}
template<typename X>
select_t(X x, Limit limit):
_flag_list(x._flag_list),
_column_list(x._column_list),
_from(x._from),
_where(x._where),
_group_by(x._group_by),
_having(x._having),
_order_by(x._order_by),
_limit(limit),
_offset(x._offset)
{}
template<typename X>
select_t(X x, Offset offset):
_flag_list(x._flag_list),
_column_list(x._column_list),
_from(x._from),
_where(x._where),
_group_by(x._group_by),
_having(x._having),
_order_by(x._order_by),
_limit(x._limit),
_offset(offset)
{}
select_t(const select_t& r) = default;
@@ -131,7 +236,230 @@ namespace sqlpp
select_t& operator=(select_t&& r) = default;
~select_t() = default;
// Indicators
// type update functions
template<typename... Args>
auto flags(Args... args)
-> _policies_update_t<vendor::no_select_flag_list_t, vendor::select_flag_list_t<void, Args...>>
{
static_assert(is_noop_t<FlagList>::value, "flags()/dynamic_flags() must not be called twice");
return { *this, vendor::select_flag_list_t<void, Args...>(args...) };
}
template<typename... Args>
auto dynamic_flags(Args... args)
-> _policies_update_t<vendor::no_select_flag_list_t, vendor::select_flag_list_t<_database_t, Args...>>
{
static_assert(is_noop_t<FlagList>::value, "flags()/dynamic_flags() must not be called twice");
static_assert(_is_dynamic::value, "dynamic_flags must not be called in a static statement");
return { *this, vendor::select_flag_list_t<_database_t, Args...>(args...) };
}
template<typename... Args>
auto columns(Args... args)
-> _policies_update_t<vendor::no_select_column_list_t, vendor::select_column_list_t<void, Args...>>
{
static_assert(is_noop_t<ColumnList>::value, "columns()/dynamic_columns() must not be called twice");
return { *this, vendor::select_column_list_t<void, Args...>(args...) };
}
template<typename... Args>
auto dynamic_columns(Args... args)
-> _policies_update_t<vendor::no_select_column_list_t, vendor::select_column_list_t<_database_t, Args...>>
{
static_assert(is_noop_t<ColumnList>::value, "columns()/dynamic_columns() must not be called twice");
static_assert(_is_dynamic::value, "dynamic_columns must not be called in a static statement");
return { *this, vendor::select_column_list_t<_database_t, Args...>(args...) };
}
template<typename... Args>
auto from(Args... args)
-> _policies_update_t<vendor::no_from_t, vendor::from_t<void, Args...>>
{
return { *this, vendor::from_t<void, Args...>(args...) };
}
template<typename... Args>
auto dynamic_from(Args... args)
-> _policies_update_t<vendor::no_from_t, vendor::from_t<_database_t, Args...>>
{
static_assert(not std::is_same<_database_t, void>::value, "dynamic_from must not be called in a static statement");
return { *this, vendor::from_t<_database_t, Args...>(args...) };
}
template<typename... Args>
auto where(Args... args)
-> _policies_update_t<vendor::no_where_t, vendor::where_t<void, Args...>>
{
static_assert(is_noop_t<Where>::value, "cannot call where()/dynamic_where() twice");
return { *this, vendor::where_t<void, Args...>(args...) };
}
template<typename... Args>
auto dynamic_where(Args... args)
-> _policies_update_t<vendor::no_where_t, vendor::where_t<_database_t, Args...>>
{
static_assert(is_noop_t<Where>::value, "cannot call where()/dynamic_where() twice");
static_assert(not std::is_same<_database_t, void>::value, "dynamic_where must not be called in a static statement");
return { *this, vendor::where_t<_database_t, Args...>(args...) };
}
template<typename... Args>
auto group_by(Args... args)
-> _policies_update_t<vendor::no_group_by_t, vendor::group_by_t<void, Args...>>
{
static_assert(is_noop_t<GroupBy>::value, "cannot call group_by()/dynamic_group_by() twice");
return { *this, vendor::group_by_t<void, Args...>(args...) };
}
template<typename... Args>
auto dynamic_group_by(Args... args)
-> _policies_update_t<vendor::no_group_by_t, vendor::group_by_t<_database_t, Args...>>
{
static_assert(is_noop_t<GroupBy>::value, "cannot call group_by()/dynamic_group_by() twice");
static_assert(not std::is_same<_database_t, void>::value, "dynamic_group_by must not be called in a static statement");
return { *this, vendor::group_by_t<_database_t, Args...>(args...) };
}
template<typename... Args>
auto having(Args... args)
-> _policies_update_t<vendor::no_having_t, vendor::having_t<void, Args...>>
{
static_assert(is_noop_t<Having>::value, "cannot call having()/dynamic_having() twice");
return { *this, vendor::having_t<void, Args...>(args...) };
}
template<typename... Args>
auto dynamic_having(Args... args)
-> _policies_update_t<vendor::no_having_t, vendor::having_t<_database_t, Args...>>
{
static_assert(is_noop_t<Having>::value, "cannot call having()/dynamic_having() twice");
static_assert(not std::is_same<_database_t, void>::value, "dynamic_having must not be called in a static statement");
return { *this, vendor::having_t<_database_t, Args...>(args...) };
}
template<typename... Args>
auto order_by(Args... args)
-> _policies_update_t<vendor::no_order_by_t, vendor::order_by_t<void, Args...>>
{
static_assert(is_noop_t<OrderBy>::value, "cannot call order_by()/dynamic_order_by() twice");
return { *this, vendor::order_by_t<void, Args...>(args...) };
}
template<typename... Args>
auto dynamic_order_by(Args... args)
-> _policies_update_t<vendor::no_order_by_t, vendor::order_by_t<_database_t, Args...>>
{
static_assert(is_noop_t<OrderBy>::value, "cannot call order_by()/dynamic_order_by() twice");
static_assert(not std::is_same<_database_t, void>::value, "dynamic_order_by must not be called in a static statement");
return { *this, vendor::order_by_t<_database_t, Args...>(args...) };
}
template<typename Arg>
auto limit(Arg arg)
-> _policies_update_t<vendor::no_limit_t, vendor::limit_t<typename vendor::wrap_operand<Arg>::type>>
{
static_assert(is_noop_t<Limit>::value, "cannot call limit()/dynamic_limit() twice");
return { *this, vendor::limit_t<typename vendor::wrap_operand<Arg>::type>({arg}) };
}
auto dynamic_limit()
-> _policies_update_t<vendor::no_limit_t, vendor::dynamic_limit_t<_database_t>>
{
static_assert(is_noop_t<Limit>::value, "cannot call limit()/dynamic_limit() twice");
static_assert(not std::is_same<_database_t, void>::value, "dynamic_limit must not be called in a static statement");
return { *this, vendor::dynamic_limit_t<_database_t>() };
}
template<typename Arg>
auto offset(Arg arg)
-> _policies_update_t<vendor::no_offset_t, vendor::offset_t<typename vendor::wrap_operand<Arg>::type>>
{
static_assert(is_noop_t<Offset>::value, "cannot call offset()/dynamic_offset() twice");
return { *this, vendor::offset_t<typename vendor::wrap_operand<Arg>::type>({arg}) };
}
auto dynamic_offset()
-> _policies_update_t<vendor::no_offset_t, vendor::dynamic_offset_t<_database_t>>
{
static_assert(is_noop_t<Offset>::value, "cannot call offset()/dynamic_offset() twice");
static_assert(not std::is_same<_database_t, void>::value, "dynamic_offset must not be called in a static statement");
return { *this, vendor::dynamic_offset_t<_database_t>() };
}
// value adding methods
template<typename... Args>
void add_flag(Args... args)
{
static_assert(is_select_flag_list_t<FlagList>::value, "cannot call add_flag() before dynamic_flags()");
static_assert(is_dynamic_t<FlagList>::value, "cannot call add_flag() before dynamic_flags()");
return _flag_list.add_flag(*this, args...);
}
template<typename... Args>
void add_column(Args... args)
{
static_assert(is_select_column_list_t<ColumnList>::value, "cannot call add_column() before dynamic_columns()");
static_assert(is_dynamic_t<ColumnList>::value, "cannot call add_column() before dynamic_columns()");
return _column_list.add_column(*this, args...);
}
template<typename... Args>
void add_from(Args... args)
{
static_assert(is_from_t<From>::value, "cannot call add_from() before dynamic_from()");
static_assert(is_dynamic_t<From>::value, "cannot call add_using() before dynamic_from()");
return _from.add_from(*this, args...);
}
template<typename... Args>
void add_where(Args... args)
{
static_assert(is_where_t<Where>::value, "cannot call add_where() before dynamic_where()");
static_assert(is_dynamic_t<Where>::value, "cannot call add_where() before dynamic_where()");
return _where.add_where(*this, args...);
}
template<typename... Args>
void add_group_by(Args... args)
{
static_assert(is_group_by_t<GroupBy>::value, "cannot call add_group_by() before dynamic_group_by()");
static_assert(is_dynamic_t<GroupBy>::value, "cannot call add_group_by() before dynamic_group_by()");
return _group_by.add_group_by(*this, args...);
}
template<typename... Args>
void add_having(Args... args)
{
static_assert(is_having_t<Having>::value, "cannot call add_having() before dynamic_having()");
static_assert(is_dynamic_t<Having>::value, "cannot call add_having() before dynamic_having()");
return _having.add_having(*this, args...);
}
template<typename... Args>
void add_order_by(Args... args)
{
static_assert(is_order_by_t<OrderBy>::value, "cannot call add_order_by() before dynamic_order_by()");
static_assert(is_dynamic_t<OrderBy>::value, "cannot call add_order_by() before dynamic_order_by()");
return _order_by.add_order_by(*this, args...);
}
template<typename Arg>
void set_limit(Arg arg)
{
static_assert(is_limit_t<Limit>::value, "cannot call add_limit() before dynamic_limit()");
static_assert(is_dynamic_t<Limit>::value, "cannot call add_limit() before dynamic_limit()");
return _limit.set_limit(arg);
}
template<typename Arg>
void set_offset(Arg arg)
{
static_assert(is_offset_t<Offset>::value, "cannot call add_offset() before dynamic_offset()");
static_assert(is_dynamic_t<Offset>::value, "cannot call add_offset() before dynamic_offset()");
return _offset.set_offset(arg);
}
// PseudoTable
template<typename AliasProvider>
struct _pseudo_table_t
{
@@ -166,12 +494,25 @@ namespace sqlpp
return _result_row_t::static_size() + get_dynamic_names().size();
}
template<typename Db>
struct can_run_t
{
//static_assert(is_where_t<Where>::value, "cannot select remove without having a where condition, use .where(true) to remove all rows");
//static_assert(not vendor::is_noop<ColumnList>::value, "cannot run select without having selected anything");
//static_assert(is_from_t<From>::value, "cannot run select without a from()");
//static_assert(is_where_t<Where>::value, "cannot run select without having a where condition, use .where(true) to select all rows");
// FIXME: Check for missing aliases (if references are used)
// FIXME: Check for missing tables, well, actually, check for missing tables at the where(), order_by(), etc.
static constexpr bool value = true;
};
// Execute
template<typename Db>
auto _run(Db& db) const
-> result_t<decltype(db.select(*this)), _result_row_t>
{
static_assert(detail::select_helper_t<Policies...>::template can_run_t<Db>::value, "Cannot execute select statement");
static_assert(can_run_t<Db>::value, "Cannot execute select statement");
static_assert(_get_static_no_of_parameters() == 0, "cannot run select directly with parameters, use prepare instead");
return {db.select(*this), get_dynamic_names()};
}
@@ -181,10 +522,20 @@ namespace sqlpp
auto _prepare(Db& db) const
-> prepared_select_t<Db, select_t>
{
static_assert(detail::select_helper_t<Policies...>::template can_run_t<Db>::value, "Cannot prepare select statement");
static_assert(can_run_t<Db>::value, "Cannot prepare select statement");
return {{}, get_dynamic_names(), db.prepare_select(*this)};
}
FlagList _flag_list;
ColumnList _column_list;
From _from;
Where _where;
GroupBy _group_by;
Having _having;
OrderBy _order_by;
Limit _limit;
Offset _offset;
};
namespace vendor
@@ -198,15 +549,15 @@ namespace sqlpp
{
context << "SELECT ";
interpret(t._flag_list(), context);
interpret(t._column_list(), context);
interpret(t._from(), context);
interpret(t._where(), context);
interpret(t._group_by(), context);
interpret(t._having(), context);
interpret(t._order_by(), context);
interpret(t._limit(), context);
interpret(t._offset(), context);
interpret(t._flag_list, context);
interpret(t._column_list, context);
interpret(t._from, context);
interpret(t._where, context);
interpret(t._group_by, context);
interpret(t._having, context);
interpret(t._order_by, context);
interpret(t._limit, context);
interpret(t._offset, context);
return context;
}
@@ -233,32 +584,29 @@ namespace sqlpp
decltype(std::tuple_cat(as_tuple<Columns>::_(std::declval<Columns>())...))>;
}
blank_select_t<void> select() // FIXME: These should be constexpr
select_t<void> select() // FIXME: These should be constexpr
{
return { blank_select_t<void>() };
return { select_t<void>() };
}
template<typename... Columns>
auto select(Columns... columns)
-> vendor::update_policies_t<blank_select_t<void>,
vendor::no_select_column_list_t,
detail::make_select_column_list_t<void, Columns...>>
-> select_t<void, vendor::no_select_flag_list_t, detail::make_select_column_list_t<void, Columns...>>
{
return { blank_select_t<void>(), detail::make_select_column_list_t<void, Columns...>(std::tuple_cat(detail::as_tuple<Columns>::_(columns)...)) };
return { select_t<void>(), detail::make_select_column_list_t<void, Columns...>(std::tuple_cat(detail::as_tuple<Columns>::_(columns)...)) };
}
template<typename Database>
blank_select_t<Database> dynamic_select(const Database&)
select_t<Database> dynamic_select(const Database&)
{
return { blank_select_t<Database>() };
return { select_t<Database>() };
}
template<typename Database, typename... Columns>
auto dynamic_select(const Database&, Columns... columns)
-> vendor::update_policies_t<blank_select_t<Database>, vendor::no_select_column_list_t, detail::make_select_column_list_t<void, Columns...>>
-> select_t<Database, vendor::no_select_flag_list_t, detail::make_select_column_list_t<void, Columns...>>
{
return { blank_select_t<Database>(), detail::make_select_column_list_t<void, Columns...>(std::tuple_cat(detail::as_tuple<Columns>::_(columns)...)) };
return { select_t<Database>(), detail::make_select_column_list_t<void, Columns...>(std::tuple_cat(detail::as_tuple<Columns>::_(columns)...)) };
}
}

View File

@@ -27,7 +27,6 @@
#ifndef SQLPP_SELECT_FLAGS_H
#define SQLPP_SELECT_FLAGS_H
#include <sqlpp11/select_fwd.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/type_set.h>
#include <sqlpp11/vendor/interpret_tuple.h>

View File

@@ -1,37 +0,0 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_SELECT_FWD_H
#define SQLPP_SELECT_FWD_H
#include <type_traits>
namespace sqlpp
{
template<typename Database, typename... Policies>
struct select_t;
}
#endif

View File

@@ -44,7 +44,7 @@ namespace sqlpp
{
template<
typename Table,
typename Assignments,
typename UpdateList,
typename Where
>
struct check_update_t
@@ -53,27 +53,50 @@ namespace sqlpp
};
}
template<typename Database, typename... Policies>
struct update_t: public vendor::policy_t<Policies>..., public vendor::crtp_wrapper_t<update_t<Database, Policies...>, Policies>...
template<typename Database = void,
typename Table = vendor::no_single_table_t,
typename UpdateList = vendor::no_update_list_t,
typename Where = vendor::no_where_t>
struct update_t
{
template<typename Needle, typename Replacement>
using _policy_update_t = update_t<Database, vendor::policy_update_t<Policies, Needle, Replacement>...>;
using _database_t = Database;
using _parameter_tuple_t = std::tuple<Policies...>;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
template<typename Needle, typename Replacement, typename... Policies>
struct _policies_update_impl
{
using type = update_t<Database, vendor::policy_update_t<Policies, Needle, Replacement>...>;
};
template<typename Needle, typename Replacement>
using _policies_update_t = typename _policies_update_impl<Needle, Replacement, Table, UpdateList, Where>::type;
using _parameter_tuple_t = std::tuple<Table, UpdateList, Where>;
using _parameter_list_t = typename make_parameter_list_t<update_t>::type;
update_t()
{}
template<typename Whatever>
update_t(update_t r, Whatever whatever):
vendor::policy_t<Policies>(r, whatever)...
// Constructors
template<typename X>
update_t(X x, Table table):
_table(table),
_update_list(x._update_list),
_where(x._where)
{}
template<typename Remove, typename Whatever>
update_t(Remove r, Whatever whatever):
vendor::policy_t<Policies>(r, whatever)...
template<typename X>
update_t(X x, UpdateList update_list):
_table(x._table),
_update_list(update_list),
_where(x._where)
{}
template<typename X>
update_t(X x, Where where):
_table(x._table),
_update_list(x._update_list),
_where(where)
{}
update_t(const update_t&) = default;
@@ -82,6 +105,59 @@ namespace sqlpp
update_t& operator=(update_t&&) = default;
~update_t() = default;
// type update functions
template<typename... Args>
auto set(Args... args)
-> _policies_update_t<vendor::no_update_list_t, vendor::update_list_t<void, Args...>>
{
static_assert(is_noop_t<UpdateList>::value, "cannot call set()/dynamic_set() twice");
return { *this, vendor::update_list_t<void, Args...>(args...) };
}
template<typename... Args>
auto dynamic_set(Args... args)
-> _policies_update_t<vendor::no_update_list_t, vendor::update_list_t<_database_t, Args...>>
{
static_assert(is_noop_t<UpdateList>::value, "cannot call set()/dynamic_set() twice");
static_assert(_is_dynamic::value, "dynamic_set must not be called in a static statement");
return { *this, vendor::update_list_t<_database_t, Args...>(args...) };
}
template<typename... Args>
auto where(Args... args)
-> _policies_update_t<vendor::no_where_t, vendor::where_t<void, Args...>>
{
static_assert(is_noop_t<Where>::value, "cannot call where()/dynamic_where() twice");
return { *this, vendor::where_t<void, Args...>(args...) };
}
template<typename... Args>
auto dynamic_where(Args... args)
-> _policies_update_t<vendor::no_where_t, vendor::where_t<_database_t, Args...>>
{
static_assert(is_noop_t<Where>::value, "cannot call where()/dynamic_where() twice");
static_assert(not std::is_same<_database_t, void>::value, "dynamic_where must not be called in a static statement");
return { *this, vendor::where_t<_database_t, Args...>(args...) };
}
// value adding methods
template<typename... Args>
void add_set(Args... args)
{
static_assert(is_update_list_t<UpdateList>::value, "cannot call add_set() before dynamic_set()");
static_assert(is_dynamic_t<UpdateList>::value, "cannot call add_set() before dynamic_set()");
return _update_list.add_set(*this, args...);
}
template<typename... Args>
void add_where(Args... args)
{
static_assert(is_where_t<Where>::value, "cannot call add_where() before dynamic_where()");
static_assert(is_dynamic_t<Where>::value, "cannot call add_where() before dynamic_where()");
return _where.add_where(*this, args...);
}
// run and prepare
static constexpr size_t _get_static_no_of_parameters()
{
return _parameter_list_t::size::value;
@@ -96,7 +172,6 @@ namespace sqlpp
std::size_t _run(Db& db) const
{
static_assert(_get_static_no_of_parameters() == 0, "cannot run update directly with parameters, use prepare instead");
static_assert(detail::check_update_t<Policies...>::value, "Cannot run this update expression");
return db.update(*this);
}
@@ -104,9 +179,12 @@ namespace sqlpp
auto _prepare(Db& db) const
-> prepared_update_t<Database, update_t>
{
static_assert(detail::check_update_t<Policies...>::value, "Cannot run this update expression");
return {{}, db.prepare_update(*this)};
}
Table _table;
UpdateList _update_list;
Where _where;
};
namespace vendor
@@ -119,29 +197,26 @@ namespace sqlpp
static Context& _(const T& t, Context& context)
{
context << "UPDATE ";
interpret(t._single_table(), context);
interpret(t._update_list(), context);
interpret(t._where(), context);
interpret(t._table, context);
interpret(t._update_list, context);
interpret(t._where, context);
return context;
}
};
}
template<typename Database>
using blank_update_t = update_t<Database, vendor::no_single_table_t, vendor::no_update_list_t, vendor::no_where_t>;
template<typename Table>
constexpr auto update(Table table)
-> update_t<void, vendor::single_table_t<void, Table>, vendor::no_update_list_t, vendor::no_where_t>
-> update_t<void, vendor::single_table_t<void, Table>>
{
return { blank_update_t<void>(), vendor::single_table_t<void, Table>{table} };
return { update_t<void>(), vendor::single_table_t<void, Table>{table} };
}
template<typename Database, typename Table>
constexpr auto dynamic_update(const Database&, Table table)
-> update_t<Database, vendor::single_table_t<void, Table>, vendor::no_update_list_t, vendor::no_where_t>
-> update_t<Database, vendor::single_table_t<void, Table>>
{
return { blank_update_t<Database>(), vendor::single_table_t<void, Table>{table} };
return { update_t<Database>(), vendor::single_table_t<void, Table>{table} };
}
}

View File

@@ -27,7 +27,6 @@
#ifndef SQLPP_FROM_H
#define SQLPP_FROM_H
#include <sqlpp11/select_fwd.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/interpretable_list.h>
#include <sqlpp11/vendor/interpret_tuple.h>
@@ -66,22 +65,21 @@ namespace sqlpp
from_t& operator=(from_t&&) = default;
~from_t() = default;
template<typename Table>
void add_from(Table table)
template<typename Select, typename Table>
void add_from(const Select&, Table table)
{
static_assert(_is_dynamic::value, "add_from can only be called for dynamic_from");
static_assert(is_table_t<Table>::value, "from arguments require to be tables or joins");
_dynamic_tables.emplace_back(table);
}
const from_t& _from() const { return *this; }
std::tuple<Tables...> _tables;
vendor::interpretable_list_t<Database> _dynamic_tables;
};
struct no_from_t
{
const no_from_t& _from() const { return *this; }
using _is_noop = std::true_type;
};
// CRTP Wrappers
@@ -90,25 +88,6 @@ namespace sqlpp
{
};
template<typename Derived>
struct crtp_wrapper_t<Derived, no_from_t>
{
template<typename... Args>
auto from(Args... args)
-> vendor::update_policies_t<Derived, no_from_t, from_t<void, Args...>>
{
return { static_cast<Derived&>(*this), from_t<void, Args...>(args...) };
}
template<typename... Args>
auto dynamic_from(Args... args)
-> vendor::update_policies_t<Derived, no_from_t, from_t<get_database_t<Derived>, Args...>>
{
static_assert(not std::is_same<get_database_t<Derived>, void>::value, "dynamic_from must not be called in a static statement");
return { static_cast<Derived&>(*this), from_t<get_database_t<Derived>, Args...>(args...) };
}
};
// Interpreters
template<typename Context, typename Database, typename... Tables>
struct interpreter_t<Context, from_t<Database, Tables...>>

View File

@@ -64,8 +64,8 @@ namespace sqlpp
group_by_t& operator=(group_by_t&&) = default;
~group_by_t() = default;
template<typename Expression>
void add_group_by(Expression expression)
template<typename Statement, typename Expression>
void add_group_by(const Statement&, Expression expression)
{
static_assert(is_table_t<Expression>::value, "from arguments require to be tables or joins");
_dynamic_expressions.emplace_back(expression);
@@ -78,35 +78,9 @@ namespace sqlpp
struct no_group_by_t
{
using _is_group_by = std::true_type;
const no_group_by_t& _group_by() const { return *this; }
using _is_noop = std::true_type;
};
// CRTP Wrappers
template<typename Derived, typename Database, typename... Args>
struct crtp_wrapper_t<Derived, group_by_t<Database, Args...>>
{
};
template<typename Derived>
struct crtp_wrapper_t<Derived, no_group_by_t>
{
template<typename... Args>
auto group_by(Args... args)
-> vendor::update_policies_t<Derived, no_group_by_t, group_by_t<void, Args...>>
{
return { static_cast<Derived&>(*this), group_by_t<void, Args...>(args...) };
}
template<typename... Args>
auto dynamic_group_by(Args... args)
-> vendor::update_policies_t<Derived, no_group_by_t, group_by_t<get_database_t<Derived>, Args...>>
{
static_assert(not std::is_same<get_database_t<Derived>, void>::value, "dynamic_group_by must not be called in a static statement");
return { static_cast<Derived&>(*this), group_by_t<get_database_t<Derived>, Args...>(args...) };
}
};
// Interpreters
template<typename Context, typename Database, typename... Expressions>
struct interpreter_t<Context, group_by_t<Database, Expressions...>>

View File

@@ -69,42 +69,15 @@ namespace sqlpp
_dynamic_expressions.emplace_back(expr);
}
const having_t& _having() const { return *this; }
_parameter_tuple_t _expressions;
vendor::interpretable_list_t<Database> _dynamic_expressions;
};
struct no_having_t
{
using _is_having = std::true_type;
const no_having_t& _having() const { return *this; }
using _is_noop = std::true_type;
};
// CRTP Wrappers
template<typename Derived, typename Database, typename... Args>
struct crtp_wrapper_t<Derived, having_t<Database, Args...>>
{
};
template<typename Derived>
struct crtp_wrapper_t<Derived, no_having_t>
{
template<typename... Args>
auto having(Args... args)
-> vendor::update_policies_t<Derived, no_having_t, having_t<void, Args...>>
{
return { static_cast<Derived&>(*this), having_t<void, Args...>(args...) };
}
template<typename... Args>
auto dynamic_having(Args... args)
-> vendor::update_policies_t<Derived, no_having_t, having_t<get_database_t<Derived>, Args...>>
{
static_assert(not std::is_same<get_database_t<Derived>, void>::value, "dynamic_having must not be called in a static statement");
return { static_cast<Derived&>(*this), having_t<get_database_t<Derived>, Args...>(args...) };
}
};
// Interpreters
template<typename Context, typename Database, typename... Expressions>
struct interpreter_t<Context, having_t<Database, Expressions...>>

View File

@@ -52,7 +52,6 @@ namespace sqlpp
limit_t& operator=(limit_t&&) = default;
~limit_t() = default;
const limit_t& _limit() const { return *this; }
Limit _value;
};
@@ -88,56 +87,15 @@ namespace sqlpp
_initialized = true;
}
const dynamic_limit_t& _limit() const { return *this; }
bool _initialized = false;
interpretable_t<Database> _value;
};
struct no_limit_t
{
using _is_limit = std::true_type;
const no_limit_t& _limit() const { return *this; }
using _is_noop = std::true_type;
};
// CRTP Wrappers
template<typename Derived, typename Limit>
struct crtp_wrapper_t<Derived, limit_t<Limit>>
{
};
template<typename Derived, typename Database>
struct crtp_wrapper_t<Derived, dynamic_limit_t<Database>>
{
};
template<typename Derived>
struct crtp_wrapper_t<Derived, no_limit_t>
{
template<typename... Args>
struct delayed_get_database_t
{
using type = get_database_t<Derived>;
};
template<typename Arg>
auto limit(Arg arg)
-> vendor::update_policies_t<Derived, no_limit_t, limit_t<typename wrap_operand<Arg>::type>>
{
typename wrap_operand<Arg>::type value = {arg};
return { static_cast<Derived&>(*this), limit_t<typename wrap_operand<Arg>::type>(value) };
}
template<typename... Args>
auto dynamic_limit(Args... args)
-> vendor::update_policies_t<Derived, no_limit_t, dynamic_limit_t<typename delayed_get_database_t<Args...>::type>>
{
static_assert(sizeof...(Args) < 2, "dynamic_limit must be called with zero or one arguments");
static_assert(not std::is_same<get_database_t<Derived>, void>::value, "dynamic_limit must not be called in a static statement");
return { static_cast<Derived&>(*this), dynamic_limit_t<typename delayed_get_database_t<Args...>::type>(args...) };
}
};
// Interpreters
template<typename Context, typename Database>
struct interpreter_t<Context, dynamic_limit_t<Database>>

View File

@@ -52,8 +52,6 @@ namespace sqlpp
offset_t& operator=(offset_t&&) = default;
~offset_t() = default;
const offset_t& _offset() const { return *this; }
Offset _value;
};
@@ -89,55 +87,15 @@ namespace sqlpp
_initialized = true;
}
const dynamic_offset_t& _offset() const { return *this; }
bool _initialized = false;
interpretable_t<Database> _value;
};
struct no_offset_t
{
using _is_offset = std::true_type;
const no_offset_t& _offset() const { return *this; }
using _is_noop = std::true_type;
};
// CRTP Wrappers
template<typename Derived, typename Offset>
struct crtp_wrapper_t<Derived, offset_t<Offset>>
{
};
template<typename Derived, typename Database>
struct crtp_wrapper_t<Derived, dynamic_offset_t<Database>>
{
};
template<typename Derived>
struct crtp_wrapper_t<Derived, no_offset_t>
{
template<typename... Args>
struct delayed_get_database_t
{
using type = get_database_t<Derived>;
};
template<typename Arg>
auto offset(Arg arg)
-> vendor::update_policies_t<Derived, no_offset_t, offset_t<typename wrap_operand<Arg>::type>>
{
typename wrap_operand<Arg>::type value = {arg};
return { static_cast<Derived&>(*this), offset_t<typename wrap_operand<Arg>::type>(value) };
}
template<typename... Args>
auto dynamic_offset(Args... args)
-> vendor::update_policies_t<Derived, no_offset_t, dynamic_offset_t<typename delayed_get_database_t<Args...>::type>>
{
static_assert(sizeof...(Args) < 2, "dynamic_offset must be called with zero or one arguments");
static_assert(not std::is_same<get_database_t<Derived>, void>::value, "dynamic_offset must not be called in a static statement");
return { static_cast<Derived&>(*this), dynamic_offset_t<typename delayed_get_database_t<Args...>::type>(args...) };
}
};
// Interpreters
template<typename Context, typename Offset>
struct interpreter_t<Context, offset_t<Offset>>

View File

@@ -28,7 +28,6 @@
#define SQLPP_ORDER_BY_H
#include <tuple>
#include <sqlpp11/select_fwd.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/vendor/interpretable.h>
@@ -63,49 +62,22 @@ namespace sqlpp
order_by_t& operator=(order_by_t&&) = default;
~order_by_t() = default;
template<typename Expression>
void add_order_by(Expression expressions)
template<typename Statement, typename Expression>
void add_order_by(const Statement&, Expression expressions)
{
static_assert(is_sort_order_t<Expression>::value, "order_by arguments require to be sort-order expressions");
_dynamic_expressions.push_back(expressions);
}
const order_by_t& _order_by() const { return *this; }
_parameter_tuple_t _expressions;
vendor::interpretable_list_t<Database> _dynamic_expressions;
};
struct no_order_by_t
{
using _is_order_by = std::true_type;
const no_order_by_t& _order_by() const { return *this; }
using _is_noop = std::true_type;
};
// CRTP Wrappers
template<typename Derived, typename Database, typename... Args>
struct crtp_wrapper_t<Derived, order_by_t<Database, Args...>>
{
};
template<typename Derived>
struct crtp_wrapper_t<Derived, no_order_by_t>
{
template<typename... Args>
auto order_by(Args... args)
-> vendor::update_policies_t<Derived, no_order_by_t, order_by_t<void, Args...>>
{
return { static_cast<Derived&>(*this), order_by_t<void, Args...>(args...) };
}
template<typename... Args>
auto dynamic_order_by(Args... args)
-> vendor::update_policies_t<Derived, no_order_by_t, order_by_t<get_database_t<Derived>, Args...>>
{
static_assert(not std::is_same<get_database_t<Derived>, void>::value, "dynamic_order_by must not be called in a static statement");
return { static_cast<Derived&>(*this), order_by_t<get_database_t<Derived>, Args...>(args...) };
}
};
// Interpreters
template<typename Context, typename Database, typename... Expressions>
struct interpreter_t<Context, order_by_t<Database, Expressions...>>

View File

@@ -29,7 +29,6 @@
#include <tuple>
#include <sqlpp11/result_row.h>
#include <sqlpp11/select_fwd.h>
#include <sqlpp11/table.h>
#include <sqlpp11/no_value.h>
#include <sqlpp11/vendor/field.h>
@@ -184,8 +183,8 @@ namespace sqlpp
select_column_list_t& operator=(select_column_list_t&&) = default;
~select_column_list_t() = default;
template<typename Expr>
void add_column(Expr namedExpr)
template<typename Select, typename Expr>
void add_column(const Select&, Expr namedExpr)
{
static_assert(is_named_expression_t<Expr>::value, "select() arguments require to be named expressions");
static_assert(_is_dynamic::value, "cannot add columns to a non-dynamic column list");
@@ -199,7 +198,7 @@ namespace sqlpp
struct no_select_column_list_t
{
using _is_select_column_list = std::true_type;
using _is_noop = std::true_type;
using _result_row_t = ::sqlpp::result_row_t<>;
using _dynamic_names_t = typename dynamic_select_column_list<void>::_names_t;
using _value_type = no_value_t;
@@ -210,35 +209,8 @@ namespace sqlpp
{
static_assert(wrong_t<T>::value, "Cannot use a select as a table when no columns have been selected yet");
};
const no_select_column_list_t& _column_list() const { return *this; }
};
// CRTP Wrappers
template<typename Derived, typename Database, typename... Args>
struct crtp_wrapper_t<Derived, select_column_list_t<Database, Args...>>
{
};
template<typename Derived>
struct crtp_wrapper_t<Derived, no_select_column_list_t>
{
template<typename... Args>
auto columns(Args... args)
-> vendor::update_policies_t<Derived, no_select_column_list_t, select_column_list_t<void, Args...>>
{
return { static_cast<Derived&>(*this), select_column_list_t<void, Args...>(args...) };
}
template<typename... Args>
auto dynamic_columns(Args... args)
-> vendor::update_policies_t<Derived, no_select_column_list_t, select_column_list_t<get_database_t<Derived>, Args...>>
{
static_assert(not std::is_same<get_database_t<Derived>, void>::value, "dynamic_columns must not be called in a static statement");
return { static_cast<Derived&>(*this), select_column_list_t<get_database_t<Derived>, Args...>(args...) };
}
};
// Interpreters
template<typename Context, typename Database, typename... Columns>
struct interpreter_t<Context, select_column_list_t<Database, Columns...>>

View File

@@ -28,7 +28,6 @@
#define SQLPP_VENDOR_SELECT_FLAG_LIST_H
#include <tuple>
#include <sqlpp11/select_fwd.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/select_flags.h>
#include <sqlpp11/detail/type_set.h>
@@ -63,8 +62,8 @@ namespace sqlpp
select_flag_list_t& operator=(select_flag_list_t&&) = default;
~select_flag_list_t() = default;
template<typename Flag>
void add_flag(Flag flag)
template<typename Select, typename Flag>
void add_flag(const Select&, Flag flag)
{
static_assert(is_select_flag_t<Flag>::value, "flag arguments require to be select flags");
_dynamic_flags.emplace_back(flag);
@@ -77,34 +76,9 @@ namespace sqlpp
struct no_select_flag_list_t
{
using _is_select_flag_list = std::true_type;
const no_select_flag_list_t& _flag_list() const { return *this; }
using _is_noop = std::true_type;
};
// CRTP Wrappers
template<typename Derived, typename Database, typename... Args>
struct crtp_wrapper_t<Derived, select_flag_list_t<Database, Args...>>
{
};
template<typename Derived>
struct crtp_wrapper_t<Derived, no_select_flag_list_t>
{
template<typename... Args>
auto flags(Args... args)
-> vendor::update_policies_t<Derived, no_select_flag_list_t, select_flag_list_t<void, Args...>>
{
return { static_cast<Derived&>(*this), select_flag_list_t<void, Args...>(args...) };
}
template<typename... Args>
auto dynamic_flags(Args... args)
-> vendor::update_policies_t<Derived, no_select_flag_list_t, select_flag_list_t<get_database_t<Derived>, Args...>>
{
static_assert(not std::is_same<get_database_t<Derived>, void>::value, "dynamic_flags must not be called in a static statement");
return { static_cast<Derived&>(*this), select_flag_list_t<get_database_t<Derived>, Args...>(args...) };
}
};
// Interpreters
template<typename Context, typename Database, typename... Flags>

View File

@@ -62,8 +62,8 @@ namespace sqlpp
update_list_t& operator=(update_list_t&&) = default;
~update_list_t() = default;
template<typename Assignment>
void add_set(Assignment assignment)
template<typename Update, typename Assignment>
void add_set(const Update&, Assignment assignment)
{
static_assert(is_assignment_t<Assignment>::value, "set() arguments require to be assigments");
static_assert(not must_not_update_t<typename Assignment::_column_t>::value, "set() argument must not be updated");
@@ -77,35 +77,10 @@ namespace sqlpp
struct no_update_list_t
{
using _is_update_list = std::true_type;
using _is_noop = std::true_type;
const no_update_list_t& _update_list() const { return *this; }
};
// CRTP Wrappers
template<typename Derived, typename Database, typename... Args>
struct crtp_wrapper_t<Derived, update_list_t<Database, Args...>>
{
};
template<typename Derived>
struct crtp_wrapper_t<Derived, no_update_list_t>
{
template<typename... Args>
auto set(Args... args)
-> vendor::update_policies_t<Derived, no_update_list_t, update_list_t<void, Args...>>
{
return { static_cast<Derived&>(*this), update_list_t<void, Args...>(args...) };
}
template<typename... Args>
auto dynamic_set(Args... args)
-> vendor::update_policies_t<Derived, no_update_list_t, update_list_t<get_database_t<Derived>, Args...>>
{
static_assert(not std::is_same<get_database_t<Derived>, void>::value, "dynamic_update_list must not be called in a static statement");
return { static_cast<Derived&>(*this), update_list_t<get_database_t<Derived>, Args...>(args...) };
}
};
// Interpreters
template<typename Context, typename Database, typename... Assignments>
struct interpreter_t<Context, update_list_t<Database, Assignments...>>

View File

@@ -6,13 +6,13 @@ macro (build_and_run arg)
add_test(${arg} ${arg})
endmacro ()
#build_and_run(InterpretTest)
build_and_run(InterpretTest)
build_and_run(InsertTest)
build_and_run(RemoveTest)
#build_and_run(UpdateTest)
#build_and_run(SelectTest)
#build_and_run(FunctionTest)
#build_and_run(PreparedTest)
build_and_run(UpdateTest)
build_and_run(SelectTest)
build_and_run(FunctionTest)
build_and_run(PreparedTest)
find_package(PythonInterp REQUIRED)

View File

@@ -23,6 +23,7 @@
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include "Sample.h"
#include "MockDb.h"
#include "is_regular.h"
@@ -31,7 +32,6 @@
#include <sqlpp11/functions.h>
#include <sqlpp11/connection.h>
#include <iostream>
DbMock db = {};
DbMock::_context_t printer(std::cerr);
@@ -175,6 +175,8 @@ int main()
// Test a select of a single numeric table column
{
using T = decltype(select(t.alpha).from(t));
static_assert(sqlpp::is_select_column_list_t<decltype(T::_column_list)>::value, "Must not be noop");
static_assert(sqlpp::is_from_t<decltype(T::_from)>::value, "Must not be noop");
static_assert(sqlpp::is_numeric_t<T>::value, "type requirement");
static_assert(sqlpp::is_expression_t<T>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<T>::value, "type requirement");