0
0
mirror of https://github.com/rbock/sqlpp11.git synced 2024-11-15 20:31:16 +08:00

Merge branch 'feature/trivial-value-is-null' into develop

This commit is contained in:
rbock 2014-03-20 10:51:36 +01:00
commit 4a25f5bcb9
46 changed files with 970 additions and 633 deletions

View File

@ -28,6 +28,7 @@
#define SQLPP_BOOLEAN_H
#include <cstdlib>
#include <cassert>
#include <ostream>
#include <sqlpp11/basic_operators.h>
#include <sqlpp11/type_traits.h>
@ -98,6 +99,7 @@ namespace sqlpp
bool _is_null;
};
template<typename Db, bool NullIsTrivial = false>
struct _result_entry_t
{
_result_entry_t():
@ -133,15 +135,28 @@ namespace sqlpp
bool is_null() const
{
if (not _is_valid)
if (connector_assert_result_validity_t<Db>::value)
assert(_is_valid);
else if (not _is_valid)
throw exception("accessing is_null in non-existing row");
return _is_null;
}
_cpp_value_type value() const
{
if (not _is_valid)
throw exception("accessing value in non-existing row");
const bool null_value = _is_null and not NullIsTrivial and not connector_null_result_is_trivial_value_t<Db>::value;
if (connector_assert_result_validity_t<Db>::value)
{
assert(_is_valid);
assert(not null_value);
}
else
{
if (not _is_valid)
throw exception("accessing value in non-existing row");
if (null_value)
throw exception("accessing value of NULL field");
}
return _value;
}
@ -189,7 +204,8 @@ namespace sqlpp
};
};
inline std::ostream& operator<<(std::ostream& os, const boolean::_result_entry_t& e)
template<typename Db, bool TrivialIsNull>
inline std::ostream& operator<<(std::ostream& os, const boolean::_result_entry_t<Db, TrivialIsNull>& e)
{
return os << e.value();
}

View File

@ -34,52 +34,52 @@ namespace sqlpp
namespace detail
{
template<bool... b>
struct and_impl;
struct all_impl;
template<>
struct and_impl<>
struct all_impl<>
{
static constexpr bool value = true;
};
template<bool... Rest>
struct and_impl<true, Rest...>
struct all_impl<true, Rest...>
{
static constexpr bool value = and_impl<Rest...>::value;
static constexpr bool value = all_impl<Rest...>::value;
};
template<bool... Rest>
struct and_impl<false, Rest...>
struct all_impl<false, Rest...>
{
static constexpr bool value = false;
};
template<template<typename> class Predicate, typename... T>
using and_t = and_impl<Predicate<T>::value...>;
using all_t = all_impl<Predicate<T>::value...>;
template<bool... b>
struct or_impl;
struct any_impl;
template<>
struct or_impl<>
struct any_impl<>
{
static constexpr bool value = false;
};
template<bool... Rest>
struct or_impl<false, Rest...>
struct any_impl<false, Rest...>
{
static constexpr bool value = or_impl<Rest...>::value;
static constexpr bool value = any_impl<Rest...>::value;
};
template<bool... Rest>
struct or_impl<true, Rest...>
struct any_impl<true, Rest...>
{
static constexpr bool value = true;
};
template<template<typename> class Predicate, typename... T>
using or_t = or_impl<Predicate<T>::value...>;
using any_t = any_impl<Predicate<T>::value...>;
}
}

View File

@ -38,7 +38,10 @@ namespace sqlpp
{
// some forward declarations and helpers
template<typename... T>
struct make_set;
struct make_type_set;
template<typename E, typename SET>
struct is_element_of;
// A type set
template<typename... Elements>
@ -47,118 +50,126 @@ namespace sqlpp
using size = std::integral_constant<size_t, sizeof...(Elements)>;
using _is_type_set = std::true_type;
static_assert(std::is_same<type_set, typename make_set<Elements...>::type>::value, "use make_set to construct a set");
template<typename T>
struct count
{
template<typename E>
using same = std::is_same<T, E>;
static constexpr bool value = or_t<same, Elements...>::value;
};
template<typename T>
struct is_superset_of
{
static_assert(::sqlpp::vendor::wrong_t<T>::value, "invalid argument for is_superset_of");
};
template<typename... T>
struct is_superset_of<type_set<T...>>
{
static constexpr bool value = and_t<count, T...>::value;
};
template<typename T>
struct join
{
static_assert(::sqlpp::vendor::wrong_t<T>::value, "invalid argument for type_set::join");
};
template<typename... T>
struct join<type_set<T...>>
{
using type = typename make_set<Elements..., T...>::type;
};
template<typename T>
struct is_subset_of
{
static_assert(::sqlpp::vendor::wrong_t<T>::value, "invalid argument for is_subset_of");
};
template<typename... T>
struct is_subset_of<type_set<T...>>
{
static constexpr bool value = type_set<T...>::template is_superset_of<type_set>::value;
};
template<typename T>
struct is_disjunct_from
{
static_assert(::sqlpp::vendor::wrong_t<T>::value, "invalid argument for is_disjunct_from");
};
template<typename... T>
struct is_disjunct_from<type_set<T...>>
{
static constexpr bool value = not(or_t<type_set::count, T...>::value or or_t<type_set<T...>::template count, Elements...>::value);
};
static_assert(std::is_same<type_set, typename make_type_set<Elements...>::type>::value, "use make_type_set to construct a set");
template<typename T>
struct insert
{
using type = typename std::conditional<count<T>::value,
type_set,
type_set<T, Elements...>>::type;
using type = typename std::conditional<not is_element_of<T, type_set>::value,
type_set<T, Elements...>,
type_set>::type;
};
template<template<typename A> class Predicate, typename T>
struct insert_if
{
using type = typename std::conditional<Predicate<T>::value,
using type = typename std::conditional<Predicate<T>::value and not is_element_of<T, type_set>::value,
type_set<Elements..., T>,
type_set>::type;
};
};
template<typename E, typename SET>
struct is_element_of
{
static_assert(::sqlpp::vendor::wrong_t<E, SET>::value, "SET has to be a type set");
};
template<typename E, typename... Elements>
struct is_element_of<E, type_set<Elements...>>
{
template<typename X>
using matchE = std::is_same<E, X>;
static constexpr bool value = any_t<matchE, Elements...>::value;
};
template<typename L, typename R>
struct is_superset_of
{
static_assert(::sqlpp::vendor::wrong_t<L, R>::value, "L and R have to be type sets");
};
template<typename... LElements, typename... RElements>
struct is_superset_of<type_set<LElements...>, type_set<RElements...>>
{
template<typename X>
using is_element_of_L = is_element_of<X, type_set<LElements...>>;
static constexpr bool value = all_t<is_element_of_L, RElements...>::value;
};
template<typename L, typename R>
struct is_subset_of
{
static constexpr bool value = is_superset_of<R, L>::value;
};
template<typename L, typename R>
struct joined_set
{
static_assert(::sqlpp::vendor::wrong_t<L, R>::value, "L and R have to be type sets");
};
template<typename... LElements, typename... RElements>
struct joined_set<type_set<LElements...>, type_set<RElements...>>
{
using type = typename make_type_set<LElements..., RElements...>::type;
};
template<typename L, typename R>
struct is_disjunct_from
{
static_assert(::sqlpp::vendor::wrong_t<L, R>::value, "invalid argument for is_disjunct_from");
};
template<typename... LElements, typename... RElements>
struct is_disjunct_from<type_set<LElements...>, type_set<RElements...>>
{
template<typename X>
using is_element_of_L = is_element_of<X, type_set<LElements...>>;
template<typename X>
using is_element_of_R = is_element_of<X, type_set<RElements...>>;
static constexpr bool value =
not(any_t<is_element_of_L, RElements...>::value or any_t<is_element_of_R, LElements...>::value);
};
template<>
struct make_set<>
struct make_type_set<>
{
using type = type_set<>;
};
template<typename T, typename... Rest>
struct make_set<T, Rest...>
struct make_type_set<T, Rest...>
{
using type = typename make_set<Rest...>::type::template insert<T>::type;
using type = typename make_type_set<Rest...>::type::template insert<T>::type;
};
template<template<typename> class Predicate, typename... T>
struct make_set_if;
struct make_type_set_if;
template<template<typename> class Predicate>
struct make_set_if<Predicate>
struct make_type_set_if<Predicate>
{
using type = type_set<>;
};
template<template<typename> class Predicate, typename T, typename... Rest>
struct make_set_if<Predicate, T, Rest...>
struct make_type_set_if<Predicate, T, Rest...>
{
using type = typename make_set_if<Predicate, Rest...>::type::template insert_if<Predicate, T>::type;
using type = typename make_type_set_if<Predicate, Rest...>::type::template insert_if<Predicate, T>::type;
};
template<template<typename> class Predicate, typename... T>
struct make_set_if_not
struct make_type_set_if_not
{
template<typename X>
using InversePredicate = std::integral_constant<bool, not Predicate<X>::value>;
using type = typename make_set_if<InversePredicate, T...>::type;
using type = typename make_type_set_if<InversePredicate, T...>::type;
};
template<typename... T>
using has_duplicates = std::integral_constant<bool, make_set<T...>::type::size::value != sizeof...(T)>;
using has_duplicates = std::integral_constant<bool, make_type_set<T...>::type::size::value != sizeof...(T)>;
template<typename... T>
struct make_joined_set
@ -172,20 +183,12 @@ namespace sqlpp
using type = type_set<>;
};
/*
template<typename... E>
struct make_joined_set<type_set<E...>>
{
using type = type_set<E...>;
};
*/
template<typename... E, typename... T>
struct make_joined_set<type_set<E...>, T...>
{
using _rest = typename make_joined_set<T...>::type;
using type = typename type_set<E...>::template join<_rest>::type;
using type = typename joined_set<type_set<E...>, _rest>::type;
};
}

View File

@ -28,6 +28,7 @@
#define SQLPP_FLOATING_POINT_H
#include <cstdlib>
#include <cassert>
#include <sqlpp11/basic_operators.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/exception.h>
@ -98,6 +99,7 @@ namespace sqlpp
bool _is_null;
};
template<typename Db, bool NullIsTrivial = false>
struct _result_entry_t
{
using _value_type = integral;
@ -135,15 +137,28 @@ namespace sqlpp
bool is_null() const
{
if (not _is_valid)
if (connector_assert_result_validity_t<Db>::value)
assert(_is_valid);
else if (not _is_valid)
throw exception("accessing is_null in non-existing row");
return _is_null;
}
_cpp_value_type value() const
{
if (not _is_valid)
throw exception("accessing value in non-existing row");
const bool null_value = _is_null and not NullIsTrivial and not connector_null_result_is_trivial_value_t<Db>::value;
if (connector_assert_result_validity_t<Db>::value)
{
assert(_is_valid);
assert(not null_value);
}
else
{
if (not _is_valid)
throw exception("accessing value in non-existing row");
if (null_value)
throw exception("accessing value of NULL field");
}
return _value;
}
@ -237,7 +252,8 @@ namespace sqlpp
};
};
inline std::ostream& operator<<(std::ostream& os, const floating_point::_result_entry_t& e)
template<typename Db, bool TrivialIsNull>
inline std::ostream& operator<<(std::ostream& os, const floating_point::_result_entry_t<Db, TrivialIsNull>& e)
{
return os << e.value();
}

View File

@ -45,7 +45,7 @@ namespace sqlpp
>
struct insert_t
{
static_assert(Table::_table_set::template is_superset_of<typename InsertValueList::_table_set>::value, "columns do not match the table they are to be inserted into");
static_assert(::sqlpp::detail::is_superset_of<typename Table::_table_set, typename InsertValueList::_table_set>::value, "columns do not match the table they are to be inserted into");
using _database_t = Database;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;

View File

@ -28,6 +28,7 @@
#define SQLPP_INTEGRAL_H
#include <cstdlib>
#include <cassert>
#include <sqlpp11/basic_operators.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/exception.h>
@ -98,6 +99,7 @@ namespace sqlpp
bool _is_null;
};
template<typename Db, bool NullIsTrivial = false>
struct _result_entry_t
{
using _value_type = integral;
@ -135,15 +137,28 @@ namespace sqlpp
bool is_null() const
{
if (not _is_valid)
if (connector_assert_result_validity_t<Db>::value)
assert(_is_valid);
else if (not _is_valid)
throw exception("accessing is_null in non-existing row");
return _is_null;
}
_cpp_value_type value() const
{
if (not _is_valid)
throw exception("accessing value in non-existing row");
const bool null_value = _is_null and not NullIsTrivial and not connector_null_result_is_trivial_value_t<Db>::value;
if (connector_assert_result_validity_t<Db>::value)
{
assert(_is_valid);
assert(not null_value);
}
else
{
if (not _is_valid)
throw exception("accessing value in non-existing row");
if (null_value)
throw exception("accessing value of NULL field");
}
return _value;
}
@ -244,7 +259,8 @@ namespace sqlpp
};
};
inline std::ostream& operator<<(std::ostream& os, const integral::_result_entry_t& e)
template<typename Db, bool NullIsTrivial>
inline std::ostream& operator<<(std::ostream& os, const integral::_result_entry_t<Db, NullIsTrivial>& e)
{
return os << e.value();
}

View File

@ -82,11 +82,11 @@ namespace sqlpp
static_assert(not is_join_t<Rhs>::value, "rhs argument for join must not be a join");
static_assert(vendor::is_noop<On>::value or is_on_t<On>::value, "invalid on expression in join().on()");
static_assert(Lhs::_table_set::template is_disjunct_from<typename Rhs::_table_set>::value, "joined tables must not be identical");
static_assert(::sqlpp::detail::is_disjunct_from<typename Lhs::_table_set, typename Rhs::_table_set>::value, "joined tables must not be identical");
using _is_table = std::true_type;
using _is_join = std::true_type;
using _table_set = typename Lhs::_table_set::template join<typename Rhs::_table_set>::type;
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Lhs::_table_set, typename Rhs::_table_set>::type;
template<typename OnT>
using set_on_t = join_t<JoinType, Lhs, Rhs, OnT>;

View File

@ -40,7 +40,7 @@ namespace sqlpp
template<typename Unused, typename... Columns>
struct multi_column_t
{
static_assert(detail::and_t<is_named_expression_t, Columns...>::value, "multi_column parameters need to be named expressions");
static_assert(detail::all_t<is_named_expression_t, Columns...>::value, "multi_column parameters need to be named expressions");
multi_column_t(std::tuple<Columns...> columns):
_columns(columns)
@ -72,7 +72,7 @@ namespace sqlpp
template<typename AliasProvider, typename... Columns>
struct multi_column_alias_t
{
static_assert(detail::and_t<is_named_expression_t, Columns...>::value, "multi_column parameters need to be named expressions");
static_assert(detail::all_t<is_named_expression_t, Columns...>::value, "multi_column parameters need to be named expressions");
using _name_t = typename AliasProvider::_name_t;

View File

@ -36,8 +36,6 @@ namespace sqlpp
static constexpr bool _is_expression = true;
using _value_type = no_value_t;
using _table_set = ::sqlpp::detail::type_set<>;
static constexpr bool _is_trivial() { return false; }
};
namespace vendor

View File

@ -41,7 +41,7 @@ namespace sqlpp
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
static_assert(_is_dynamic::value or sizeof...(Expr), "at least one expression argument required in on()");
static_assert(detail::and_t<is_expression_t, Expr...>::value, "at least one argument is not an expression in on()");
static_assert(detail::all_t<is_expression_t, Expr...>::value, "at least one argument is not an expression in on()");
template<typename E>
void add(E expr)

View File

@ -32,15 +32,15 @@
namespace sqlpp
{
template<typename Db, typename Select>
template<typename Database, typename Select>
struct prepared_select_t
{
using _result_row_t = typename Select::_result_row_t;
using _result_row_t = typename Select::template _result_row_t<Database>;
using _parameter_list_t = typename Select::_parameter_list_t;
using _dynamic_names_t = typename Select::_dynamic_names_t;
using _prepared_statement_t = typename Db::_prepared_statement_t;
using _prepared_statement_t = typename Database::_prepared_statement_t;
auto _run(Db& db) const
auto _run(Database& db) const
-> result_t<decltype(db.run_prepared_select(*this)), _result_row_t>
{
return {db.run_prepared_select(*this), _dynamic_names};

View File

@ -41,13 +41,13 @@ namespace sqlpp
template<size_t level, size_t index, typename... NamedExpr>
struct result_row_impl;
template<size_t level, size_t index, typename NamedExpr, typename... Rest>
struct result_row_impl<level, index, NamedExpr, Rest...>:
public NamedExpr::_name_t::template _member_t<typename NamedExpr::_value_type::_result_entry_t>,
public result_row_impl<level, index + 1, Rest...>
template<size_t level, size_t index, typename Db, typename NamedExpr, typename... Rest>
struct result_row_impl<level, index, Db, NamedExpr, Rest...>:
public NamedExpr::_name_t::template _member_t<typename NamedExpr::_value_type::template _result_entry_t<Db, NamedExpr::_trivial_value_is_null>>,
public result_row_impl<level, index + 1, Db, Rest...>
{
using _field = typename NamedExpr::_name_t::template _member_t<typename NamedExpr::_value_type::_result_entry_t>;
using _rest = result_row_impl<level, index + 1, Rest...>;
using _field = typename NamedExpr::_name_t::template _member_t<typename NamedExpr::_value_type::template _result_entry_t<Db, NamedExpr::_trivial_value_is_null>>;
using _rest = result_row_impl<level, index + 1, Db, Rest...>;
static constexpr size_t _last_index = _rest::_last_index;
result_row_impl() = default;
@ -84,13 +84,13 @@ namespace sqlpp
}
};
template<size_t level, size_t index, typename AliasProvider, typename... Col, typename... Rest>
struct result_row_impl<level, index, vendor::multi_field_t<AliasProvider, std::tuple<Col...>>, Rest...>:
public AliasProvider::_name_t::template _member_t<result_row_impl<level, index, Col...>>, // level prevents identical closures to be present twice in the inheritance tree
public result_row_impl<level, index + sizeof...(Col), Rest...>
template<size_t level, size_t index, typename AliasProvider, typename Db, typename... Col, typename... Rest>
struct result_row_impl<level, index, Db, vendor::multi_field_t<AliasProvider, std::tuple<Col...>>, Rest...>:
public AliasProvider::_name_t::template _member_t<result_row_impl<level, index, Db, Col...>>, // level prevents identical closures to be present twice in the inheritance tree
public result_row_impl<level, index + sizeof...(Col), Db, Rest...>
{
using _multi_field = typename AliasProvider::_name_t::template _member_t<result_row_impl<level, index, Col...>>;
using _rest = result_row_impl<level, index + sizeof...(Col), Rest...>;
using _multi_field = typename AliasProvider::_name_t::template _member_t<result_row_impl<level, index, Db, Col...>>;
using _rest = result_row_impl<level, index + sizeof...(Col), Db, Rest...>;
static constexpr size_t _last_index = _rest::_last_index;
result_row_impl() = default;
@ -126,8 +126,8 @@ namespace sqlpp
}
};
template<size_t level, size_t index>
struct result_row_impl<level, index>
template<size_t level, size_t index, typename Db>
struct result_row_impl<level, index, Db>
{
static constexpr size_t _last_index = index;
result_row_impl() = default;
@ -155,10 +155,10 @@ namespace sqlpp
};
}
template<typename... NamedExpr>
struct result_row_t: public detail::result_row_impl<0, 0, NamedExpr...>
template<typename Db, typename... NamedExpr>
struct result_row_t: public detail::result_row_impl<0, 0, Db, NamedExpr...>
{
using _impl = detail::result_row_impl<0, 0, NamedExpr...>;
using _impl = detail::result_row_impl<0, 0, Db, NamedExpr...>;
bool _is_valid;
static constexpr size_t _last_static_index = _impl::_last_index;
@ -221,11 +221,11 @@ namespace sqlpp
}
};
template<typename... NamedExpr>
struct dynamic_result_row_t: public detail::result_row_impl<0, 0, NamedExpr...>
template<typename Db, typename... NamedExpr>
struct dynamic_result_row_t: public detail::result_row_impl<0, 0, Db, NamedExpr...>
{
using _impl = detail::result_row_impl<0, 0, NamedExpr...>;
using _field_type = detail::text::_result_entry_t;
using _impl = detail::result_row_impl<0, 0, Db, NamedExpr...>;
using _field_type = detail::text::_result_entry_t<Db, false>;
static constexpr size_t _last_static_index = _impl::_last_index;
bool _is_valid;

View File

@ -58,8 +58,8 @@ namespace sqlpp
>
struct select_helper_t
{
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");
static_assert(is_noop_t<ColumnList>::value or sqlpp::is_select_column_list_t<ColumnList>::value, "column list of select is neither naught nor a valid column list");
static_assert(is_noop_t<From>::value or sqlpp::is_from_t<From>::value, "from() part of select is neither naught nor a valid from()");
using _value_type = typename std::conditional<
sqlpp::is_from_t<From>::value,
typename ColumnList::_value_type,
@ -99,7 +99,8 @@ namespace sqlpp
using _table_set = ::sqlpp::detail::type_set<>;
using _column_list_t = ColumnList;
using _result_row_t = typename _column_list_t::_result_row_t;
template<typename Db>
using _result_row_t = typename _column_list_t::template _result_row_t<Db>;
using _dynamic_names_t = typename _column_list_t::_dynamic_names_t;
using _is_select = std::true_type;
@ -490,13 +491,19 @@ namespace sqlpp
size_t get_no_of_result_columns() const
{
return _result_row_t::static_size() + get_dynamic_names().size();
return _column_list_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(column_list::_table_set::template is_subset_t<_from_t::_table_set>::value
static_assert(detail::is_subset_of<column_list::_table_set, _from_t::_table_set>::value
subset_of_t sollte ein eigenes template sein, das macht so etwas wie obiges sicher einfacher lesbar
also: use any and all instead of and_t and or_t
*/
//static_assert(is_where_t<Where>::value, "cannot select select 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");
@ -509,7 +516,7 @@ namespace sqlpp
// Execute
template<typename Db>
auto _run(Db& db) const
-> result_t<decltype(db.select(*this)), _result_row_t>
-> result_t<decltype(db.select(*this)), _result_row_t<Db>>
{
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");

View File

@ -38,6 +38,18 @@ namespace sqlpp
return vendor::serializer_t<Context, T>::_(t, context);
}
/*
namespace vendor // Required if you want to call serialize(sqlpp::value(7), printer), for instance
{
template<typename T, typename Context>
auto serialize(const T& t, Context& context)
-> decltype(vendor::serializer_t<Context, T>::_(t, context))
{
return vendor::serializer_t<Context, T>::_(t, context);
}
}
*/
}
#endif

View File

@ -42,15 +42,21 @@ namespace sqlpp
return _os << t;
}
void flush()
static std::string escape(std::string arg)
{
_os << std::endl;
}
std::string escape(std::string arg)
{
// FIXME: Need to do better escaping
return arg;
if (arg.find('\''))
{
std::string retVal;
for (const auto c : arg)
{
if (c == '\'')
retVal.push_back(c);
retVal.push_back(c);
}
return retVal;
}
else
return arg;
}
std::ostream& _os;

View File

@ -44,7 +44,7 @@ namespace sqlpp
{
using _table_set = detail::type_set<Table>; // Hint need a type_set here to be similar to a join (which always represents more than one table)
static_assert(sizeof...(ColumnSpec), "at least one column required per table");
using _required_insert_columns = typename detail::make_set_if<require_insert_t, column_t<Table, ColumnSpec>...>::type;
using _required_insert_columns = typename detail::make_type_set_if<require_insert_t, column_t<Table, ColumnSpec>...>::type;
using _column_tuple_t = std::tuple<column_t<Table, ColumnSpec>...>;
template<typename AliasProvider>
using _alias_t = table_alias_t<AliasProvider, Table, ColumnSpec...>;

View File

@ -27,6 +27,7 @@
#ifndef SQLPP_TEXT_H
#define SQLPP_TEXT_H
#include <cassert>
#include <sqlpp11/basic_operators.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/exception.h>
@ -97,6 +98,7 @@ namespace sqlpp
bool _is_null;
};
template<typename Db, bool NullIsTrivial = false>
struct _result_entry_t
{
_result_entry_t():
@ -135,16 +137,29 @@ namespace sqlpp
bool is_null() const
{
if (not _is_valid)
if (connector_assert_result_validity_t<Db>::value)
assert(_is_valid);
else if (not _is_valid)
throw exception("accessing is_null in non-existing row");
return _value_ptr == nullptr;
}
_cpp_value_type value() const
{
if (not _is_valid)
throw exception("accessing value in non-existing row");
if (_value_ptr)
const bool null_value = _value_ptr == nullptr and not NullIsTrivial and not connector_null_result_is_trivial_value_t<Db>::value;
if (connector_assert_result_validity_t<Db>::value)
{
assert(_is_valid);
assert(not null_value);
}
else
{
if (not _is_valid)
throw exception("accessing value in non-existing row");
if (null_value)
throw exception("accessing value of NULL field");
}
if (_value_ptr)
return std::string(_value_ptr, _value_ptr + _len);
else
return "";
@ -195,7 +210,8 @@ namespace sqlpp
};
};
inline std::ostream& operator<<(std::ostream& os, const text::_result_entry_t& e)
template<typename Db, bool TrivialIsNull>
inline std::ostream& operator<<(std::ostream& os, const text::_result_entry_t<Db, TrivialIsNull>& e)
{
return os << e.value();
}

View File

@ -74,7 +74,7 @@ namespace sqlpp
}
template<typename T>
struct tvin_wrap_t
struct maybe_tvin_t
{
using _table_set = typename T::_table_set;
static constexpr bool _is_trivial()
@ -82,20 +82,20 @@ namespace sqlpp
return false;
}
tvin_wrap_t(T t):
maybe_tvin_t(T t):
_value(t)
{}
tvin_wrap_t(const tvin_wrap_t&) = default;
tvin_wrap_t(tvin_wrap_t&&) = default;
tvin_wrap_t& operator=(const tvin_wrap_t&) = default;
tvin_wrap_t& operator=(tvin_wrap_t&&) = default;
~tvin_wrap_t() = default;
maybe_tvin_t(const maybe_tvin_t&) = default;
maybe_tvin_t(maybe_tvin_t&&) = default;
maybe_tvin_t& operator=(const maybe_tvin_t&) = default;
maybe_tvin_t& operator=(maybe_tvin_t&&) = default;
~maybe_tvin_t() = default;
T _value;
};
template<typename T>
struct tvin_wrap_t<tvin_t<T>>
struct maybe_tvin_t<tvin_t<T>>
{
using _table_set = typename T::_table_set;
bool _is_trivial() const
@ -103,14 +103,14 @@ namespace sqlpp
return _value._is_trivial();
};
tvin_wrap_t(tvin_t<T> t):
maybe_tvin_t(tvin_t<T> t):
_value(t._value)
{}
tvin_wrap_t(const tvin_wrap_t&) = default;
tvin_wrap_t(tvin_wrap_t&&) = default;
tvin_wrap_t& operator=(const tvin_wrap_t&) = default;
tvin_wrap_t& operator=(tvin_wrap_t&&) = default;
~tvin_wrap_t() = default;
maybe_tvin_t(const maybe_tvin_t&) = default;
maybe_tvin_t(maybe_tvin_t&&) = default;
maybe_tvin_t& operator=(const maybe_tvin_t&) = default;
maybe_tvin_t& operator=(maybe_tvin_t&&) = default;
~maybe_tvin_t() = default;
typename tvin_t<T>::_operand_t _value;
};
@ -118,9 +118,9 @@ namespace sqlpp
namespace vendor
{
template<typename Context, typename Operand>
struct serializer_t<Context, tvin_wrap_t<Operand>>
struct serializer_t<Context, maybe_tvin_t<Operand>>
{
using T = tvin_wrap_t<Operand>;
using T = maybe_tvin_t<Operand>;
static Context& _(const T& t, Context& context)
{

View File

@ -92,6 +92,7 @@ namespace sqlpp
SQLPP_IS_COLUMN_TRAIT_GENERATOR(must_not_update);
SQLPP_IS_COLUMN_TRAIT_GENERATOR(require_insert);
SQLPP_IS_COLUMN_TRAIT_GENERATOR(can_be_null);
SQLPP_IS_COLUMN_TRAIT_GENERATOR(trivial_value_is_null);
SQLPP_TYPE_TRAIT_GENERATOR(is_noop);
SQLPP_TYPE_TRAIT_GENERATOR(is_table);
@ -123,7 +124,8 @@ namespace sqlpp
SQLPP_TYPE_TRAIT_GENERATOR(requires_braces);
SQLPP_TYPE_TRAIT_GENERATOR(is_parameter);
SQLPP_CONNECTOR_TRAIT_GENERATOR(has_empty_list_insert);
SQLPP_CONNECTOR_TRAIT_GENERATOR(null_result_is_trivial_value);
SQLPP_CONNECTOR_TRAIT_GENERATOR(assert_result_validity);
template<typename T, template<typename> class IsTag>
using copy_type_trait = typename std::conditional<IsTag<T>::value, std::true_type, std::false_type>::type;

View File

@ -57,8 +57,8 @@ namespace sqlpp
typename Where = vendor::no_where_t>
struct update_t
{
static_assert(Table::_table_set::template is_superset_of<typename UpdateList::_table_set>::value, "updated columns do not match the table");
static_assert(Table::_table_set::template is_superset_of<typename Where::_table_set>::value, "where condition does not match updated table");
static_assert(::sqlpp::detail::is_superset_of<typename Table::_table_set, typename UpdateList::_table_set>::value, "updated columns do not match the table");
static_assert(::sqlpp::detail::is_superset_of<typename Table::_table_set, typename Where::_table_set>::value, "where condition does not match updated table");
using _database_t = Database;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;

View File

@ -38,6 +38,30 @@ namespace sqlpp
{
namespace vendor
{
template<typename T, typename Enable = void>
struct is_trivial_t
{
static constexpr bool _(const T&)
{
return false;
}
};
template<typename T>
struct is_trivial_t<T, typename std::enable_if<std::is_member_function_pointer<decltype(&T::_is_trivial)>::value, void>::type>
{
static bool _(const T& t)
{
return t._is_trivial();
}
};
template<typename T>
bool is_trivial(const T& t)
{
return is_trivial_t<typename T::value_type>::_(t);
}
template<typename Lhs, typename Rhs>
struct assignment_t
{
@ -45,9 +69,9 @@ namespace sqlpp
using _column_t = Lhs;
using value_type = Rhs;
using _parameter_tuple_t = std::tuple<_column_t, Rhs>;
using _table_set = typename Lhs::_table_set::template join<typename Rhs::_table_set>::type;
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Lhs::_table_set, typename Rhs::_table_set>::type;
static_assert(not std::is_same<Rhs, null_t>::value or can_be_null_t<_column_t>::value, "column cannot be null");
static_assert(can_be_null_t<_column_t>::value ? true : not std::is_same<Rhs, null_t>::value, "column must not be null");
assignment_t(_column_t lhs, value_type rhs):
_lhs(lhs),
@ -71,9 +95,19 @@ namespace sqlpp
static Context& _(const T& t, Context& context)
{
serialize(simple_column(t._lhs), context);
context << "=";
serialize(t._rhs, context);
if ((trivial_value_is_null_t<typename T::_column_t>::value
and is_trivial_t<typename T::value_type>::_(t._rhs))
or (std::is_same<Rhs, null_t>::value))
{
serialize(simple_column(t._lhs), context);
context << "=NULL";
}
else
{
serialize(simple_column(t._lhs), context);
context << "=";
serialize(t._rhs, context);
}
return context;
}
};
@ -85,6 +119,7 @@ namespace sqlpp
using _column_t = Lhs;
using value_type = tvin_t<Rhs>;
using _parameter_tuple_t = std::tuple<_column_t, Rhs>;
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Lhs::_table_set, typename Rhs::_table_set>::type;
static_assert(can_be_null_t<_column_t>::value, "column cannot be null");

View File

@ -39,7 +39,7 @@ namespace sqlpp
struct concat_t: public First::_value_type::template operators<concat_t<First, Args...>>
{
static_assert(sizeof...(Args) > 0, "concat requires two arguments at least");
static_assert(sqlpp::detail::and_t<is_text_t, First, Args...>::value, "at least one non-text argument detected in concat()");
static_assert(sqlpp::detail::all_t<is_text_t, First, Args...>::value, "at least one non-text argument detected in concat()");
using _table_set = typename ::sqlpp::detail::make_joined_set<typename First::_table_set, typename Args::_table_set...>::type;
struct _value_type: public First::_value_type::_base_value_type

View File

@ -58,7 +58,7 @@ namespace sqlpp
~binary_expression_t() = default;
Lhs _lhs;
tvin_wrap_t<Rhs> _rhs;
maybe_tvin_t<Rhs> _rhs;
};
template<typename Context, typename Lhs, typename Rhs>
@ -103,7 +103,7 @@ namespace sqlpp
~binary_expression_t() = default;
Lhs _lhs;
tvin_wrap_t<Rhs> _rhs;
maybe_tvin_t<Rhs> _rhs;
};
template<typename Context, typename Lhs, typename Rhs>
@ -209,6 +209,7 @@ namespace sqlpp
{
using _value_type = typename O::_value_type;
using _parameter_tuple_t = std::tuple<Rhs>;
using _table_set = typename Rhs::_table_set;
unary_expression_t(Rhs rhs):
_rhs(rhs)

View File

@ -33,11 +33,12 @@ namespace sqlpp
{
namespace vendor
{
template<typename NameType, typename ValueType>
template<typename NameType, typename ValueType, bool TrivialValueIsNull>
struct field_t
{
using _name_t = NameType;
using _value_type = ValueType;
static constexpr bool _trivial_value_is_null = TrivialValueIsNull;
};
template<typename AliasProvider, typename FieldTuple>
@ -50,7 +51,9 @@ namespace sqlpp
template<typename NamedExpr>
struct make_field_t_impl
{
using type = field_t<typename NamedExpr::_name_t, typename NamedExpr::_value_type::_base_value_type>;
using type = field_t<typename NamedExpr::_name_t,
typename NamedExpr::_value_type::_base_value_type,
trivial_value_is_null_t<NamedExpr>::value>;
};
template<typename AliasProvider, typename... NamedExpr>

View File

@ -49,7 +49,7 @@ namespace sqlpp
// FIXME: Joins contain two tables. This is not being dealt with at the moment when looking at duplicates, for instance
static_assert(not ::sqlpp::detail::has_duplicates<Tables...>::value, "at least one duplicate argument detected in from()");
static_assert(::sqlpp::detail::and_t<is_table_t, Tables...>::value, "at least one argument is not a table or join in from()");
static_assert(::sqlpp::detail::all_t<is_table_t, Tables...>::value, "at least one argument is not a table or join in from()");
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Tables::_table_set...>;

View File

@ -51,7 +51,7 @@ namespace sqlpp
static_assert(not ::sqlpp::detail::has_duplicates<Expressions...>::value, "at least one duplicate argument detected in group_by()");
static_assert(::sqlpp::detail::and_t<is_expression_t, Expressions...>::value, "at least one argument is not an expression in group_by()");
static_assert(::sqlpp::detail::all_t<is_expression_t, Expressions...>::value, "at least one argument is not an expression in group_by()");
group_by_t(Expressions... expressions):
_expressions(expressions...)

View File

@ -47,7 +47,7 @@ namespace sqlpp
using _parameter_tuple_t = std::tuple<Expressions...>;
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in having()");
static_assert(::sqlpp::detail::and_t<is_expression_t, Expressions...>::value, "at least one argument is not an expression in having()");
static_assert(::sqlpp::detail::all_t<is_expression_t, Expressions...>::value, "at least one argument is not an expression in having()");
using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type;

View File

@ -61,15 +61,15 @@ namespace sqlpp
static_assert(not ::sqlpp::detail::has_duplicates<Assignments...>::value, "at least one duplicate argument detected in set()");
static_assert(sqlpp::detail::and_t<is_assignment_t, Assignments...>::value, "at least one argument is not an assignment in set()");
static_assert(sqlpp::detail::all_t<is_assignment_t, Assignments...>::value, "at least one argument is not an assignment in set()");
static_assert(not sqlpp::detail::or_t<must_not_insert_t, typename Assignments::_column_t...>::value, "at least one assignment is prohibited by its column definition in set()");
static_assert(not sqlpp::detail::any_t<must_not_insert_t, typename Assignments::_column_t...>::value, "at least one assignment is prohibited by its column definition in set()");
using _column_table_set = typename ::sqlpp::detail::make_joined_set<typename Assignments::_column_t::_table_set...>::type;
using _value_table_set = typename ::sqlpp::detail::make_joined_set<typename Assignments::value_type::_table_set...>::type;
using _table_set = typename ::sqlpp::detail::make_joined_set<_column_table_set, _value_table_set>::type;
static_assert(sizeof...(Assignments) ? (_column_table_set::size::value == 1) : true, "set() contains assignments for tables from several columns");
static_assert(_value_table_set::template is_subset_of<_column_table_set>::value, "set() contains values from foreign tables");
static_assert(::sqlpp::detail::is_subset_of<_value_table_set, _column_table_set>::value, "set() contains values from foreign tables");
insert_list_t(Assignments... assignment):
_assignments(assignment...),
@ -90,8 +90,8 @@ namespace sqlpp
static_assert(not must_not_insert_t<Assignment>::value, "add_set() argument must not be used in insert");
using _column_table_set = typename Assignment::_column_t::_table_set;
using _value_table_set = typename Assignment::value_type::_table_set;
static_assert(_value_table_set::template is_subset_of<typename Insert::_table_set>::value, "add_set() contains a column from a foreign table");
static_assert(_column_table_set::template is_subset_of<typename Insert::_table_set>::value, "add_set() contains a value from a foreign table");
static_assert(::sqlpp::detail::is_subset_of<_value_table_set, typename Insert::_table_set>::value, "add_set() contains a column from a foreign table");
static_assert(::sqlpp::detail::is_subset_of<_column_table_set, typename Insert::_table_set>::value, "add_set() contains a value from a foreign table");
_dynamic_columns.emplace_back(simple_column_t<typename Assignment::_column_t>{assignment._lhs});
_dynamic_values.emplace_back(assignment._rhs);
}
@ -114,9 +114,9 @@ namespace sqlpp
static_assert(not ::sqlpp::detail::has_duplicates<Columns...>::value, "at least one duplicate argument detected in columns()");
static_assert(::sqlpp::detail::and_t<is_column_t, Columns...>::value, "at least one argument is not a column in columns()");
static_assert(::sqlpp::detail::all_t<is_column_t, Columns...>::value, "at least one argument is not a column in columns()");
static_assert(not ::sqlpp::detail::or_t<must_not_insert_t, Columns...>::value, "at least one column argument has a must_not_insert flag in its definition");
static_assert(not ::sqlpp::detail::any_t<must_not_insert_t, Columns...>::value, "at least one column argument has a must_not_insert flag in its definition");
using _value_tuple_t = std::tuple<vendor::insert_value_t<Columns>...>;
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Columns::_table_set...>::type;
@ -136,7 +136,7 @@ namespace sqlpp
template<typename... Assignments>
void add_values(Assignments... assignments)
{
static_assert(::sqlpp::detail::and_t<is_assignment_t, Assignments...>::value, "add_values() arguments have to be assignments");
static_assert(::sqlpp::detail::all_t<is_assignment_t, Assignments...>::value, "add_values() arguments have to be assignments");
using _arg_value_tuple = std::tuple<vendor::insert_value_t<typename Assignments::_column_t>...>;
using _args_correct = std::is_same<_arg_value_tuple, _value_tuple_t>;
static_assert(_args_correct::value, "add_values() arguments do not match columns() arguments");

View File

@ -59,9 +59,13 @@ namespace sqlpp
return _impl->serialize(context);
}
_serializer_context_t& serialize(_serializer_context_t& context) const
// This method only exists if Db::_serializer_context_t and sqlpp::serializer_context_t are not the same
template<typename Context>
auto serialize(Context& context) const
-> typename std::enable_if<std::is_same<Context, _serializer_context_t>::value
and not std::is_same<Context, sqlpp::serializer_context_t>::value, Context&>::type
{
return _impl->serialize(context);
return _impl->db_serialize(context);
}
_interpreter_context_t& interpret(_interpreter_context_t& context) const
@ -73,7 +77,7 @@ namespace sqlpp
struct _impl_base
{
virtual sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const = 0;
virtual _serializer_context_t& serialize(_serializer_context_t& context) const = 0;
virtual _serializer_context_t& db_serialize(_serializer_context_t& context) const = 0;
virtual _interpreter_context_t& interpret(_interpreter_context_t& context) const = 0;
};
@ -91,7 +95,7 @@ namespace sqlpp
return context;
}
_serializer_context_t& serialize(_serializer_context_t& context) const
_serializer_context_t& db_serialize(_serializer_context_t& context) const
{
Db::_serialize_interpretable(_t, context);
return context;

View File

@ -57,9 +57,13 @@ namespace sqlpp
return _impl->serialize(context);
}
_serializer_context_t& serialize(_serializer_context_t& context) const
// This method only exists if Db::_serializer_context_t and sqlpp::serializer_context_t are not the same
template<typename Context>
auto serialize(Context& context) const
-> typename std::enable_if<std::is_same<Context, _serializer_context_t>::value
and not std::is_same<Context, sqlpp::serializer_context_t>::value, Context&>::type
{
return _impl->serialize(context);
return _impl->db_serialize(context);
}
_interpreter_context_t& interpret(_interpreter_context_t& context) const
@ -76,7 +80,7 @@ namespace sqlpp
struct _impl_base
{
virtual sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const = 0;
virtual _serializer_context_t& serialize(_serializer_context_t& context) const = 0;
virtual _serializer_context_t& db_serialize(_serializer_context_t& context) const = 0;
virtual _interpreter_context_t& interpret(_interpreter_context_t& context) const = 0;
virtual std::string _get_name() const = 0;
};
@ -95,7 +99,7 @@ namespace sqlpp
return context;
}
_serializer_context_t& serialize(_serializer_context_t& context) const
_serializer_context_t& db_serialize(_serializer_context_t& context) const
{
Db::_serialize_interpretable(_t, context);
return context;

View File

@ -49,7 +49,7 @@ namespace sqlpp
static_assert(not ::sqlpp::detail::has_duplicates<Expressions...>::value, "at least one duplicate argument detected in order_by()");
static_assert(::sqlpp::detail::and_t<is_sort_order_t, Expressions...>::value, "at least one argument is not a sort order expression in order_by()");
static_assert(::sqlpp::detail::all_t<is_sort_order_t, Expressions...>::value, "at least one argument is not a sort order expression in order_by()");
order_by_t(Expressions... expressions):
_expressions(expressions...)

View File

@ -143,7 +143,7 @@ namespace sqlpp
template<typename T>
using is_valid_expression_t = std::integral_constant<bool, is_named_expression_t<T>::value or is_multi_column_t<T>::value>;
static_assert(::sqlpp::detail::and_t<is_valid_expression_t, Columns...>::value, "at least one argument is not a named expression");
static_assert(::sqlpp::detail::all_t<is_valid_expression_t, Columns...>::value, "at least one argument is not a named expression");
static_assert(not ::sqlpp::detail::has_duplicates<typename Columns::_name_t...>::value, "at least one duplicate name detected");
@ -156,9 +156,10 @@ namespace sqlpp
};
using _name_t = typename ::sqlpp::detail::get_first_argument_if_unique<Columns...>::_name_t;
template<typename Db>
using _result_row_t = typename std::conditional<_is_dynamic::value,
dynamic_result_row_t<make_field_t<Columns>...>,
result_row_t<make_field_t<Columns>...>>::type;
dynamic_result_row_t<Db, make_field_t<Columns>...>,
result_row_t<Db, make_field_t<Columns>...>>::type;
using _dynamic_names_t = typename dynamic_select_column_list<Database>::_names_t;
@ -198,7 +199,8 @@ namespace sqlpp
struct no_select_column_list_t
{
using _is_noop = std::true_type;
using _result_row_t = ::sqlpp::result_row_t<>;
template<typename Db>
using _result_row_t = ::sqlpp::result_row_t<Db>;
using _dynamic_names_t = typename dynamic_select_column_list<void>::_names_t;
using _value_type = no_value_t;
struct _name_t {};

View File

@ -49,7 +49,7 @@ namespace sqlpp
static_assert(not ::sqlpp::detail::has_duplicates<Flags...>::value, "at least one duplicate argument detected in select flag list");
static_assert(::sqlpp::detail::and_t<is_select_flag_t, Flags...>::value, "at least one argument is not a select flag in select flag list");
static_assert(::sqlpp::detail::all_t<is_select_flag_t, Flags...>::value, "at least one argument is not a select flag in select flag list");
select_flag_list_t(Flags... flags):
_flags(flags...)

View File

@ -48,15 +48,15 @@ namespace sqlpp
static_assert(not ::sqlpp::detail::has_duplicates<Assignments...>::value, "at least one duplicate argument detected in set()");
static_assert(::sqlpp::detail::and_t<is_assignment_t, Assignments...>::value, "at least one argument is not an assignment in set()");
static_assert(::sqlpp::detail::all_t<is_assignment_t, Assignments...>::value, "at least one argument is not an assignment in set()");
static_assert(not ::sqlpp::detail::or_t<must_not_update_t, typename Assignments::_column_t...>::value, "at least one assignment is prohibited by its column definition in set()");
static_assert(not ::sqlpp::detail::any_t<must_not_update_t, typename Assignments::_column_t...>::value, "at least one assignment is prohibited by its column definition in set()");
using _column_table_set = typename ::sqlpp::detail::make_joined_set<typename Assignments::_column_t::_table_set...>::type;
using _value_table_set = typename ::sqlpp::detail::make_joined_set<typename Assignments::value_type::_table_set...>::type;
using _table_set = typename ::sqlpp::detail::make_joined_set<_column_table_set, _value_table_set>::type;
static_assert(sizeof...(Assignments) ? (_column_table_set::size::value == 1) : true, "set() contains assignments for tables from several columns");
static_assert(_value_table_set::template is_subset_of<_column_table_set>::value, "set() contains values from foreign tables");
static_assert(::sqlpp::detail::is_subset_of<_value_table_set, _column_table_set>::value, "set() contains values from foreign tables");
update_list_t(Assignments... assignments):
_assignments(assignments...)

View File

@ -49,7 +49,7 @@ namespace sqlpp
static_assert(not ::sqlpp::detail::has_duplicates<Tables...>::value, "at least one duplicate argument detected in using()");
static_assert(::sqlpp::detail::and_t<is_table_t, Tables...>::value, "at least one argument is not an table in using()");
static_assert(::sqlpp::detail::all_t<is_table_t, Tables...>::value, "at least one argument is not an table in using()");
using_t(Tables... tables):
_tables(tables...)

View File

@ -47,8 +47,8 @@ namespace sqlpp
using _parameter_tuple_t = std::tuple<Expressions...>;
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in where()");
static_assert(not sqlpp::detail::or_t<is_assignment_t, Expressions...>::value, "at least one argument is an assignment in where()");
static_assert(sqlpp::detail::and_t<is_expression_t, Expressions...>::value, "at least one argument is not valid expression in where()");
static_assert(not sqlpp::detail::any_t<is_assignment_t, Expressions...>::value, "at least one argument is an assignment in where()");
static_assert(sqlpp::detail::all_t<is_expression_t, Expressions...>::value, "at least one argument is not valid expression in where()");
using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type;

View File

@ -11,6 +11,7 @@ build_and_run(InsertTest)
build_and_run(RemoveTest)
build_and_run(UpdateTest)
build_and_run(SelectTest)
build_and_run(SelectTypeTest)
build_and_run(FunctionTest)
build_and_run(PreparedTest)

View File

@ -32,7 +32,7 @@
#include <iostream>
DbMock db = {};
MockDb db = {};
SQLPP_ALIAS_PROVIDER(kaesekuchen);
int main()

View File

@ -29,8 +29,8 @@
#include <sqlpp11/insert.h>
#include <iostream>
DbMock db;
DbMock::_serializer_context_t printer(std::cerr);
MockDb db;
MockDb::_serializer_context_t printer;
int main()
{
@ -58,16 +58,22 @@ int main()
static_assert(sqlpp::is_regular<T>::value, "type requirement");
}
serialize(insert_into(t).default_values(), printer).flush();
serialize(insert_into(t), printer).flush();
serialize(insert_into(t).set(t.beta = "kirschauflauf"), printer).flush();
serialize(insert_into(t).columns(t.beta), printer).flush();
db(insert_into(t).default_values());
db(insert_into(t).set(t.beta = "kirschauflauf"));
serialize(insert_into(t).default_values(), printer).str();
serialize(insert_into(t), printer).str();
serialize(insert_into(t).set(t.beta = "kirschauflauf"), printer).str();
serialize(insert_into(t).columns(t.beta), printer).str();
auto multi_insert = insert_into(t).columns(t.beta, t.delta);
multi_insert.add_values(t.beta = "cheesecake", t.delta = 1);
multi_insert.add_values(t.beta = sqlpp::default_value, t.delta = sqlpp::default_value);
auto i = dynamic_insert_into(db, t).dynamic_set();
i.add_set(t.beta = "kirschauflauf");
serialize(i, printer).flush();
serialize(i, printer).str();
db(multi_insert);
return 0;
}

View File

@ -34,8 +34,8 @@
#include <iostream>
DbMock db = {};
DbMock::_serializer_context_t printer(std::cerr);
MockDb db = {};
MockDb::_serializer_context_t printer;
SQLPP_ALIAS_PROVIDER(kaesekuchen);
int main()
@ -43,122 +43,123 @@ int main()
test::TabFoo f;
test::TabBar t;
serialize(insert_into(t).columns(t.beta, t.gamma), printer).flush();
serialize(insert_into(t).columns(t.beta, t.gamma), printer).str();
{
auto i = insert_into(t).columns(t.gamma, t.beta);
i.add_values(t.gamma = true, t.beta = "cheesecake");
serialize(i, printer).flush();
serialize(i, printer).str();
i.add_values(t.gamma = false, t.beta = sqlpp::tvin("coffee"));
i.add_values(t.gamma = false, t.beta = sqlpp::tvin(std::string()));
serialize(i, printer).flush();
serialize(i, printer).str();
i.add_values(t.gamma = sqlpp::default_value, t.beta = sqlpp::null);
serialize(i, printer).flush();
serialize(i, printer).str();
}
serialize(t.alpha = sqlpp::null, printer).flush();
serialize(t.alpha = sqlpp::default_value, printer).flush();
serialize(t.alpha, printer).flush();
serialize(-t.alpha, printer).flush();
serialize(+t.alpha, printer).flush();
serialize(-(t.alpha + 7), printer).flush();
serialize(t.alpha = 0, printer).flush();
serialize(t.alpha = sqlpp::tvin(0), printer).flush();
serialize(t.alpha == 0, printer).flush();
serialize(t.alpha == sqlpp::tvin(0), printer).flush();
serialize(t.alpha != 0, printer).flush();
serialize(t.gamma != sqlpp::tvin(false), printer).flush();
serialize(t.alpha == 7, printer).flush();
serialize(t.beta + "kaesekuchen", printer).flush();
serialize(t.alpha = sqlpp::null, printer).str();
serialize(t.alpha = sqlpp::default_value, printer).str();
serialize(t.alpha, printer).str();
serialize(-t.alpha, printer).str();
serialize(+t.alpha, printer).str();
serialize(-(t.alpha + 7), printer).str();
serialize(t.alpha = 0, printer).str();
serialize(t.alpha = sqlpp::tvin(0), printer).str();
serialize(t.alpha == 0, printer).str();
serialize(t.alpha == sqlpp::tvin(0), printer).str();
serialize(t.alpha != 0, printer).str();
serialize(t.gamma != sqlpp::tvin(false), printer).str();
serialize(t.alpha == 7, printer).str();
serialize(t.beta + "kaesekuchen", printer).str();
serialize(sqlpp::select(), printer).flush();
serialize(sqlpp::select().flags(sqlpp::distinct), printer).flush();
serialize(select(t.alpha, t.beta).flags(sqlpp::distinct), printer).flush();
serialize(select(t.alpha, t.beta), printer).flush();
serialize(select(t.alpha, t.beta).from(t), printer).flush();
serialize(select(t.alpha, t.beta).from(t).where(t.alpha == 3), printer).flush();
serialize(select(t.alpha, t.beta).from(t).where(t.alpha == 3).group_by(t.gamma), printer).flush();
serialize(select(t.alpha, t.beta).from(t).where(t.alpha == 3).group_by(t.gamma).having(t.beta.like("%kuchen")), printer).flush();
serialize(select(t.alpha, t.beta).from(t).where(t.alpha == 3).group_by(t.gamma).having(t.beta.like("%kuchen")).order_by(t.beta.asc()), printer).flush();
serialize(select(t.alpha, t.beta).from(t).where(t.alpha == 3).group_by(t.gamma).having(t.beta.like("%kuchen")).order_by(t.beta.asc()).limit(17).offset(3), printer).flush();
serialize(sqlpp::select(), printer).str();
serialize(sqlpp::select().flags(sqlpp::distinct), printer).str();
serialize(select(t.alpha, t.beta).flags(sqlpp::distinct), printer).str();
serialize(select(t.alpha, t.beta), printer).str();
serialize(select(t.alpha, t.beta).from(t), printer).str();
serialize(select(t.alpha, t.beta).from(t).where(t.alpha == 3), printer).str();
serialize(select(t.alpha, t.beta).from(t).where(t.alpha == 3).group_by(t.gamma), printer).str();
serialize(select(t.alpha, t.beta).from(t).where(t.alpha == 3).group_by(t.gamma).having(t.beta.like("%kuchen")), printer).str();
serialize(select(t.alpha, t.beta).from(t).where(t.alpha == 3).group_by(t.gamma).having(t.beta.like("%kuchen")).order_by(t.beta.asc()), printer).str();
serialize(select(t.alpha, t.beta).from(t).where(t.alpha == 3).group_by(t.gamma).having(t.beta.like("%kuchen")).order_by(t.beta.asc()).limit(17).offset(3), printer).str();
serialize(parameter(sqlpp::bigint(), t.alpha), printer).flush();
serialize(parameter(t.alpha), printer).flush();
serialize(t.alpha == parameter(t.alpha), printer).flush();
serialize(t.alpha == parameter(t.alpha) and (t.beta + "gimmick").like(parameter(t.beta)), printer).flush();
serialize(parameter(sqlpp::bigint(), t.alpha), printer).str();
serialize(parameter(t.alpha), printer).str();
serialize(t.alpha == parameter(t.alpha), printer).str();
serialize(t.alpha == parameter(t.alpha) and (t.beta + "gimmick").like(parameter(t.beta)), printer).str();
serialize(insert_into(t), printer).flush();
serialize(insert_into(f).default_values(), printer).flush();
serialize(insert_into(t).set(t.gamma = true), printer).flush();
//serialize(insert_into(t).set(t.gamma = sqlpp::tvin(false)), printer).flush(); cannot test this since gamma cannot be null and a static assert is thrown
serialize(insert_into(t), printer).str();
serialize(insert_into(f).default_values(), printer).str();
serialize(insert_into(t).set(t.gamma = true), printer).str();
//serialize(insert_into(t).set(t.gamma = sqlpp::tvin(false)), printer).str(); cannot test this since gamma cannot be null and a static assert is thrown
serialize(update(t), printer).flush();
serialize(update(t).set(t.gamma = true), printer).flush();
serialize(update(t).set(t.gamma = true).where(t.beta.in("kaesekuchen", "cheesecake")), printer).flush();
serialize(update(t), printer).str();
serialize(update(t).set(t.gamma = true), printer).str();
serialize(update(t).set(t.gamma = true).where(t.beta.in("kaesekuchen", "cheesecake")), printer).str();
serialize(remove_from(t), printer).flush();
serialize(remove_from(t).using_(t), printer).flush();
serialize(remove_from(t).where(t.alpha == sqlpp::tvin(0)), printer).flush();
serialize(remove_from(t).using_(t).where(t.alpha == sqlpp::tvin(0)), printer).flush();
serialize(remove_from(t), printer).str();
serialize(remove_from(t).using_(t), printer).str();
serialize(remove_from(t).where(t.alpha == sqlpp::tvin(0)), printer).str();
serialize(remove_from(t).using_(t).where(t.alpha == sqlpp::tvin(0)), printer).str();
// functions
serialize(sqlpp::value(7), printer).flush();
serialize(sqlpp::verbatim<sqlpp::detail::integral>("irgendwas integrales"), printer).flush();
serialize(sqlpp::value_list(std::vector<int>({1,2,3,4,5,6,8})), printer).flush();
serialize(exists(select(t.alpha).from(t)), printer).flush();
serialize(any(select(t.alpha).from(t)), printer).flush();
serialize(some(select(t.alpha).from(t)), printer).flush();
serialize(count(t.alpha), printer).flush();
serialize(min(t.alpha), printer).flush();
serialize(max(t.alpha), printer).flush();
serialize(avg(t.alpha), printer).flush();
serialize(sum(t.alpha), printer).flush();
serialize(sqlpp::verbatim_table("whatever"), printer).flush();
sqlpp::serialize(sqlpp::value(7), printer).str();// FIXME: Maybe the vendor namespace is not a good idea? argument lives in namespace vendor
serialize(sqlpp::verbatim<sqlpp::detail::integral>("irgendwas integrales"), printer).str();
serialize(sqlpp::value_list(std::vector<int>({1,2,3,4,5,6,8})), printer).str();
serialize(exists(select(t.alpha).from(t)), printer).str();
serialize(any(select(t.alpha).from(t)), printer).str();
serialize(some(select(t.alpha).from(t)), printer).str();
serialize(count(t.alpha), printer).str();
serialize(min(t.alpha), printer).str();
serialize(max(t.alpha), printer).str();
serialize(avg(t.alpha), printer).str();
serialize(sum(t.alpha), printer).str();
serialize(sqlpp::verbatim_table("whatever"), printer).str();
// alias
serialize(t.as(t.alpha), printer).flush();
serialize(t.as(t.alpha).beta, printer).flush();
serialize(t.as(t.alpha), printer).str();
serialize(t.as(t.alpha).beta, printer).str();
// select alias
serialize(select(t.alpha).from(t).where(t.beta > "kaesekuchen").as(t.gamma), printer).flush();
serialize(select(t.alpha).from(t).where(t.beta > "kaesekuchen").as(t.gamma), printer).str();
serialize(t.alpha.is_null(), printer).flush();
serialize(t.alpha.is_null(), printer).str();
// join
serialize(t.inner_join(t.as(t.alpha)).on(t.beta == t.as(t.alpha).beta), printer).flush();
serialize(t.inner_join(t.as(t.alpha)).on(t.beta == t.as(t.alpha).beta), printer).str();
// multi_column
serialize(multi_column(t.alpha, (t.beta + "cake").as(t.gamma)).as(t.alpha), printer).flush();
serialize(multi_column(all_of(t)).as(t), printer).flush();
serialize(all_of(t).as(t), printer).flush();
serialize(multi_column(t.alpha, (t.beta + "cake").as(t.gamma)).as(t.alpha), printer).str();
serialize(multi_column(all_of(t)).as(t), printer).str();
serialize(all_of(t).as(t), printer).str();
// dynamic select
{
auto s = dynamic_select(db).dynamic_flags().dynamic_columns();
s.add_column(t.beta);
s.add_column(t.gamma);
serialize(s, printer).flush();
serialize(s, printer).str();
}
{
auto s = dynamic_select(db).dynamic_flags().dynamic_columns();
s.add_flag(sqlpp::distinct);
s.add_column(t.beta);
s.add_column(t.gamma);
serialize(s, printer).flush();
serialize(s, printer).str();
}
{
auto s = dynamic_select(db).dynamic_flags(sqlpp::distinct).dynamic_columns(t.alpha);
s.add_flag(sqlpp::all);
s.add_column(t.beta);
s.add_column(t.gamma);
serialize(s, printer).flush();
serialize(s, printer).str();
}
// distinct aggregate
serialize(count(sqlpp::distinct, t.alpha % 7), printer).flush();
serialize(avg(sqlpp::distinct, t.alpha - 7), printer).flush();
serialize(sum(sqlpp::distinct, t.alpha + 7), printer).flush();
serialize(count(sqlpp::distinct, t.alpha % 7), printer).str();
serialize(avg(sqlpp::distinct, t.alpha - 7), printer).str();
serialize(sum(sqlpp::distinct, t.alpha + 7), printer).str();
serialize(select(all_of(t)).from(t).where(true), printer).str();
serialize(select(all_of(t)).from(t).where(false), printer).str();
serialize(select(all_of(t)).from(t).where(true), printer).flush();
serialize(select(all_of(t)).from(t).where(false), printer).flush();
return 0;
}

View File

@ -24,17 +24,38 @@
*/
#ifndef SQLPP_MOCK_DB_H
#define SQLPP_MOCK_DB_H
#define SQLPP_MOCK_DB_H
#include <sqlpp11/connection.h>
#include <sstream>
#include <sqlpp11/serializer_context.h>
#include <sqlpp11/serialize.h>
#include <sqlpp11/connection.h>
struct DbMock: public sqlpp::connection
struct MockDb: public sqlpp::connection
{
struct _serializer_context_t : public sqlpp::serializer_context_t
struct _serializer_context_t
{
_serializer_context_t(std::ostream& os): sqlpp::serializer_context_t(os) {}
std::ostringstream _os;
std::string str() const
{
return _os.str();
}
void reset()
{
_os.clear();
}
template<typename T>
std::ostream& operator<<(T t)
{
return _os << t;
}
static std::string escape(std::string arg)
{
return sqlpp::serializer_context_t::escape(arg);
}
};
using _interpreter_context_t = _serializer_context_t;
@ -42,14 +63,97 @@ struct DbMock: public sqlpp::connection
template<typename T>
static _serializer_context_t& _serialize_interpretable(const T& t, _serializer_context_t& context)
{
return ::sqlpp::serialize(t, context);
sqlpp::serialize(t, context);
return context;
}
template<typename T>
static _interpreter_context_t& _interpret_interpretable(const T& t, _interpreter_context_t& context)
static _serializer_context_t& _interpret_interpretable(const T& t, _interpreter_context_t& context)
{
return ::sqlpp::serialize(t, context);
sqlpp::serialize(t, context);
return context;
}
class result_t
{
public:
constexpr bool operator==(const result_t& rhs) const
{
return true;
}
template<typename ResultRow>
void next(ResultRow& result_row)
{
result_row.invalidate();
};
};
// Directly executed statements start here
template<typename T>
auto operator() (const T& t) -> decltype(t._run(*this))
{
return t._run(*this);
}
template<typename Insert>
size_t insert(const Insert& x)
{
return 0;
}
template<typename Update>
size_t update(const Update& x)
{
return 0;
}
template<typename Remove>
size_t remove(const Remove& x)
{
return 0;
}
template<typename Select>
result_t select(const Select& s)
{
return {};
}
// Prepared statements start here
using _prepared_statement_t = std::nullptr_t;
template<typename T>
auto prepare(const T& t) -> decltype(t._prepare(*this))
{
return t._prepare(*this);
}
template<typename Insert>
_prepared_statement_t prepare_insert(Insert& x)
{
return nullptr;
}
template<typename PreparedInsert>
size_t run_prepared_insert(const PreparedInsert& x)
{
return 0;
}
template<typename Select>
_prepared_statement_t prepare_select(Select& x)
{
return nullptr;
}
template<typename PreparedSelect>
result_t run_prepared_select(PreparedSelect& x)
{
return {};
}
};
#endif

View File

@ -31,7 +31,7 @@
#include <iostream>
DbMock db = {};
MockDb db = {};
int main()
{
@ -88,6 +88,7 @@ int main()
// Wonderful, now take a look at the parameter list of a select
{
auto s = select(all_of(t)).from(t).where(t.beta.like(parameter(t.beta)) and t.alpha == parameter(t.alpha) or t.gamma != parameter(t.gamma));
auto p = db.prepare(s);
using S = decltype(s);
using T = sqlpp::make_parameter_list_t<S>::type;
T npl;

View File

@ -30,8 +30,8 @@
#include "is_regular.h"
DbMock db;
DbMock::_serializer_context_t printer(std::cerr);
MockDb db;
MockDb::_serializer_context_t printer;
int main()
{
@ -56,13 +56,15 @@ int main()
static_assert(sqlpp::is_regular<T>::value, "type requirement");
}
serialize(remove_from(t), printer).flush();
serialize(remove_from(t).where(t.beta != "transparent"), printer).flush();
serialize(remove_from(t).using_(t), printer).flush();
serialize(remove_from(t), printer).str();
serialize(remove_from(t).where(t.beta != "transparent"), printer).str();
serialize(remove_from(t).using_(t), printer).str();
auto r = dynamic_remove_from(db, t).dynamic_using().dynamic_where();
r.add_using(t);
r.add_where(t.beta != "transparent");
serialize(r, printer).flush();
serialize(r, printer).str();
db(r);
return 0;
}

View File

@ -33,8 +33,8 @@
#include <sqlpp11/connection.h>
DbMock db = {};
DbMock::_serializer_context_t printer(std::cerr);
MockDb db = {};
MockDb::_serializer_context_t printer;
namespace alias
{
@ -49,323 +49,26 @@ int main()
test::TabFoo f;
test::TabBar t;
// Test a table
for (const auto& row : db(select(all_of(t)).from(t).where(true)))
{
using T = decltype(t);
static_assert(not sqlpp::is_numeric_t<T>::value, "type requirement");
static_assert(not sqlpp::is_integral_t<T>::value, "type requirement");
static_assert(not sqlpp::is_floating_point_t<T>::value, "type requirement");
static_assert(not sqlpp::is_expression_t<T>::value, "type requirement");
static_assert(not sqlpp::is_named_expression_t<T>::value, "type requirement");
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_update_t<T>::value, "type requirement");
static_assert(not sqlpp::is_boolean_t<T>::value, "type requirement");
static_assert(not sqlpp::is_text_t<T>::value, "type requirement");
static_assert(not sqlpp::is_alias_t<T>::value, "type requirement");
static_assert(sqlpp::is_table_t<T>::value, "type requirement");
static_assert(sqlpp::is_regular<T>::value, "type requirement");
int64_t a = row.alpha;
const std::string b = row.beta;
}
// Test an alias of table
for (const auto& row : db(select(all_of(t).as(t)).from(t).where(true)))
{
using T = decltype(t.as(alias::a));
static_assert(not sqlpp::is_numeric_t<T>::value, "type requirement");
static_assert(not sqlpp::is_integral_t<T>::value, "type requirement");
static_assert(not sqlpp::is_floating_point_t<T>::value, "type requirement");
static_assert(not sqlpp::is_expression_t<T>::value, "type requirement");
static_assert(not sqlpp::is_named_expression_t<T>::value, "type requirement");
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_update_t<T>::value, "type requirement");
static_assert(not sqlpp::is_boolean_t<T>::value, "type requirement");
static_assert(not sqlpp::is_text_t<T>::value, "type requirement");
static_assert(sqlpp::is_alias_t<T>::value, "type requirement");
static_assert(sqlpp::is_table_t<T>::value, "type requirement");
static_assert(sqlpp::is_regular<T>::value, "type requirement");
int64_t a = row.tabBar.alpha;
const std::string b = row.tabBar.beta;
}
// Test an integral column of an alias of table
#warning this should fail because f is not in from()
for (const auto& row : db(select(f.omega, all_of(t).as(t), t.gamma).from(t).where(true)))
{
using T = decltype(t.as(alias::a).alpha);
static_assert(sqlpp::is_numeric_t<T>::value, "type requirement");
static_assert(sqlpp::is_integral_t<T>::value, "type requirement");
static_assert(not sqlpp::is_floating_point_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");
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
static_assert(sqlpp::must_not_insert_t<T>::value, "type requirement");
static_assert(sqlpp::must_not_update_t<T>::value, "type requirement");
static_assert(not sqlpp::is_boolean_t<T>::value, "type requirement");
static_assert(not sqlpp::is_text_t<T>::value, "type requirement");
static_assert(not sqlpp::is_alias_t<T>::value, "type requirement");
static_assert(not sqlpp::is_table_t<T>::value, "type requirement");
static_assert(sqlpp::is_regular<T>::value, "type requirement");
int64_t a = row.tabBar.alpha;
const std::string b = row.tabBar.beta;
const bool g = row.gamma;
const float o = row.omega;
}
// Test an integral table column
{
using T = decltype(t.alpha);
static_assert(sqlpp::is_numeric_t<T>::value, "type requirement");
static_assert(sqlpp::is_integral_t<T>::value, "type requirement");
static_assert(not sqlpp::is_floating_point_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");
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
static_assert(sqlpp::must_not_insert_t<T>::value, "type requirement");
static_assert(sqlpp::must_not_update_t<T>::value, "type requirement");
static_assert(not sqlpp::is_boolean_t<T>::value, "type requirement");
static_assert(not sqlpp::is_text_t<T>::value, "type requirement");
static_assert(not sqlpp::is_alias_t<T>::value, "type requirement");
static_assert(not sqlpp::is_table_t<T>::value, "type requirement");
static_assert(sqlpp::is_regular<T>::value, "type requirement");
}
// Test a floating point table column
{
using T = decltype(f.omega);
static_assert(sqlpp::is_numeric_t<T>::value, "type requirement");
static_assert(not sqlpp::is_integral_t<T>::value, "type requirement");
static_assert(sqlpp::is_floating_point_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");
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_update_t<T>::value, "type requirement");
static_assert(not sqlpp::is_boolean_t<T>::value, "type requirement");
static_assert(not sqlpp::is_text_t<T>::value, "type requirement");
static_assert(not sqlpp::is_alias_t<T>::value, "type requirement");
static_assert(not sqlpp::is_table_t<T>::value, "type requirement");
static_assert(sqlpp::is_regular<T>::value, "type requirement");
}
// Test a an alias of a numeric table column
{
using T = decltype(t.alpha.as(alias::a));
static_assert(sqlpp::is_numeric_t<T>::value, "type requirement");
static_assert(not sqlpp::is_expression_t<T>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<T>::value, "type requirement");
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_update_t<T>::value, "type requirement");
static_assert(not sqlpp::is_boolean_t<T>::value, "type requirement");
static_assert(not sqlpp::is_text_t<T>::value, "type requirement");
static_assert(sqlpp::is_alias_t<T>::value, "type requirement");
static_assert(not sqlpp::is_table_t<T>::value, "type requirement");
static_assert(sqlpp::is_regular<T>::value, "type requirement");
}
// Test a select of a single column without a from
{
using T = decltype(select(t.alpha)); // Hint: The current rule is pretty crude (a from is required), but certainly better than nothing
static_assert(not sqlpp::is_numeric_t<T>::value, "type requirement");
static_assert(not sqlpp::is_expression_t<T>::value, "type requirement");
static_assert(not sqlpp::is_named_expression_t<T>::value, "type requirement");
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_update_t<T>::value, "type requirement");
static_assert(not sqlpp::is_boolean_t<T>::value, "type requirement");
static_assert(not sqlpp::is_text_t<T>::value, "type requirement");
static_assert(not sqlpp::is_alias_t<T>::value, "type requirement");
static_assert(not sqlpp::is_table_t<T>::value, "type requirement");
static_assert(sqlpp::is_regular<T>::value, "type requirement");
}
// Test a select of a single numeric table column
{
using T = decltype(select(t.alpha).from(t));
static_assert(sqlpp::is_select_column_list_t<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");
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_update_t<T>::value, "type requirement");
static_assert(not sqlpp::is_boolean_t<T>::value, "type requirement");
static_assert(not sqlpp::is_text_t<T>::value, "type requirement");
static_assert(not sqlpp::is_alias_t<T>::value, "type requirement");
static_assert(not sqlpp::is_table_t<T>::value, "type requirement");
static_assert(sqlpp::is_regular<T>::value, "type requirement");
}
// Test a select of an alias of a single numeric table column
{
using T = decltype(select(t.alpha.as(alias::a)).from(t));
static_assert(sqlpp::is_numeric_t<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");
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_update_t<T>::value, "type requirement");
static_assert(not sqlpp::is_boolean_t<T>::value, "type requirement");
static_assert(not sqlpp::is_text_t<T>::value, "type requirement");
static_assert(not sqlpp::is_alias_t<T>::value, "type requirement");
static_assert(not sqlpp::is_table_t<T>::value, "type requirement");
static_assert(sqlpp::is_regular<T>::value, "type requirement");
}
// Test an alias of a select of a single numeric table column
{
using T = decltype(select(t.alpha).from(t).as(alias::b));
static_assert(not sqlpp::is_numeric_t<T>::value, "type requirement");
static_assert(not sqlpp::is_expression_t<T>::value, "type requirement");
static_assert(not sqlpp::is_named_expression_t<T>::value, "type requirement");
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_update_t<T>::value, "type requirement");
static_assert(not sqlpp::is_boolean_t<T>::value, "red to not be boolean");
static_assert(not sqlpp::is_text_t<T>::value, "type requirement");
static_assert(sqlpp::is_alias_t<T>::value, "type requirement");
static_assert(sqlpp::is_table_t<T>::value, "type requirement");
static_assert(sqlpp::is_regular<T>::value, "type requirement");
}
// Test the column of an alias of a select of an alias of a single numeric table column
{
using T = decltype(select(t.alpha.as(alias::a)).from(t).as(alias::b));
static_assert(not sqlpp::is_numeric_t<T>::value, "type requirement");
static_assert(not sqlpp::is_expression_t<T>::value, "type requirement");
static_assert(not sqlpp::is_named_expression_t<T>::value, "type requirement");
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_update_t<T>::value, "type requirement");
static_assert(not sqlpp::is_boolean_t<T>::value, "type requirement");
static_assert(not sqlpp::is_text_t<T>::value, "type requirement");
static_assert(sqlpp::is_alias_t<T>::value, "type requirement");
static_assert(sqlpp::is_table_t<T>::value, "type requirement");
static_assert(sqlpp::is_regular<T>::value, "type requirement");
}
// Test the column of an alias of a select of a single numeric table column
{
using T = decltype(select(t.alpha).from(t).as(alias::b).alpha);
static_assert(sqlpp::is_numeric_t<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");
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_update_t<T>::value, "type requirement");
static_assert(not sqlpp::is_boolean_t<T>::value, "type requirement");
static_assert(not sqlpp::is_text_t<T>::value, "type requirement");
static_assert(not sqlpp::is_alias_t<T>::value, "type requirement");
static_assert(not sqlpp::is_table_t<T>::value, "type requirement");
static_assert(sqlpp::is_regular<T>::value, "type requirement");
}
// Test an alias of a select of an alias of a single numeric table column
{
using T = decltype(select(t.alpha.as(alias::a)).from(t).as(alias::b).a);
static_assert(sqlpp::is_numeric_t<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");
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_update_t<T>::value, "type requirement");
static_assert(not sqlpp::is_boolean_t<T>::value, "type requirement");
static_assert(not sqlpp::is_text_t<T>::value, "type requirement");
static_assert(not sqlpp::is_alias_t<T>::value, "type requirement");
static_assert(not sqlpp::is_table_t<T>::value, "type requirement");
static_assert(sqlpp::is_regular<T>::value, "type requirement");
}
// Test that select(all_of(tab)) is expanded in select
{
auto a = select(all_of(t));
auto b = select(t.alpha, t.beta, t.gamma, t.delta);
//auto c = select(t);
static_assert(std::is_same<decltype(a), decltype(b)>::value, "all_of(t) has to be expanded by select()");
//static_assert(std::is_same<decltype(b), decltype(c)>::value, "t has to be expanded by select()");
}
// Test that select(all_of(tab)) is expanded in multi_column
{
auto a = multi_column(all_of(t)).as(alias::a);
auto b = multi_column(t.alpha, t.beta, t.gamma, t.delta).as(alias::a);
static_assert(std::is_same<decltype(a), decltype(b)>::value, "all_of(t) has to be expanded by multi_column");
}
// Test that a multicolumn is not a value
{
auto m = multi_column(t.alpha, t.beta).as(alias::a);
auto a = select(m).from(t).as(alias::b).a;
static_assert(not sqlpp::is_value_t<decltype(a)>::value, "a multi_column is not a value");
}
// Test that result sets with identical name/value combinations have identical types
{
auto a = select(t.alpha);
auto b = select(f.epsilon.as(t.alpha));
using A = typename decltype(a)::_result_row_t;
using B = typename decltype(b)::_result_row_t;
static_assert(std::is_same<
decltype(t.alpha)::_value_type::_base_value_type,
decltype(f.epsilon)::_value_type::_base_value_type>::value, "Two bigint columns must have identical base_value_type");
static_assert(std::is_same<A, B>::value, "select with identical columns(name/value_type) need to have identical result_types");
}
{
auto s = dynamic_select(db, all_of(t)).dynamic_from().dynamic_where().dynamic_limit().dynamic_offset();
s.add_from(t);
s.add_where(t.alpha > 7 and t.alpha == any(select(t.alpha).from(t).where(t.alpha < 3)));
s.set_limit(30);
s.set_limit(3);
std::cerr << "------------------------\n";
serialize(s, printer).flush();
std::cerr << "------------------------\n";
using T = decltype(s);
static_assert(sqlpp::is_regular<T>::value, "type requirement");
}
// Test that select can be called with zero columns if it is used with dynamic columns.
{
auto s = dynamic_select(db).dynamic_columns();
s.add_column(t.alpha);
serialize(s, printer).flush();
}
// Test that verbatim_table compiles
{
auto s = select(t.alpha).from(sqlpp::verbatim_table("my_unknown_table"));
serialize(s, printer).flush();
}
static_assert(sqlpp::is_select_flag_t<decltype(sqlpp::all)>::value, "sqlpp::all has to be a select_flag");
using T = sqlpp::vendor::wrap_operand<int>::type;
static_assert(sqlpp::is_regular<T>::value, "type requirement");
static_assert(T::_is_expression, "T has to be an expression");
static_assert(std::is_same<typename T::_value_type::_is_numeric, std::true_type>::value, "T has to be a numeric");
static_assert(sqlpp::is_numeric_t<T>::value, "T has to be a numeric");
static_assert(sqlpp::is_numeric_t<decltype(t.alpha)>::value, "TabBar.alpha has to be a numeric");
((t.alpha + 7) + 4).asc();
static_assert(sqlpp::is_boolean_t<decltype(t.gamma == t.gamma)>::value, "Comparison expression have to be boolean");
auto x = (t.gamma == true) and (t.alpha == 7);
auto y = t.gamma and true and t.gamma;
!t.gamma;
t.beta < "kaesekuchen";
serialize(t.beta + "hallenhalma", printer).flush();
static_assert(sqlpp::must_not_insert_t<decltype(t.alpha)>::value, "alpha must not be inserted");
serialize(t.alpha, printer).flush();
std::cerr << "\n" << sizeof(test::TabBar) << std::endl;
static_assert(std::is_same<typename decltype(t.alpha)::_value_type::_is_named_expression, std::true_type>::value, "alpha should be a named expression");
static_assert(sqlpp::is_named_expression_t<decltype(t.alpha)>::value, "alpha should be a named expression");
static_assert(sqlpp::is_named_expression_t<decltype(t.alpha.as(alias::a))>::value, "an alias of alpha should be a named expression");
static_assert(sqlpp::is_alias_t<decltype(t.alpha.as(alias::a))>::value, "an alias of alpha should be an alias");
auto z = select(t.alpha).from(t) == 7;
auto l = t.as(alias::left);
auto r = select(t.gamma.as(alias::a)).from(t).where(t.gamma == true).as(alias::right);
static_assert(sqlpp::is_boolean_t<decltype(select(t.gamma).from(t))>::value, "select(bool) has to be a bool");
serialize(sqlpp::select().flags(sqlpp::distinct, sqlpp::straight_join).columns(l.alpha, l.beta, select(r.a).from(r))
.from(l, r)
.where(t.beta == "hello world" and select(t.gamma).from(t))// .as(alias::right))
.group_by(l.gamma, r.a)
.having(r.a != true)
.order_by(l.beta.asc())
.limit(17)
.offset(3)
.as(alias::a)
, printer).flush();
return 0;
}

376
tests/SelectTypeTest.cpp Normal file
View File

@ -0,0 +1,376 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include "Sample.h"
#include "MockDb.h"
#include "is_regular.h"
#include <sqlpp11/alias_provider.h>
#include <sqlpp11/select.h>
#include <sqlpp11/functions.h>
#include <sqlpp11/connection.h>
MockDb db = {};
MockDb::_serializer_context_t printer;
namespace alias
{
SQLPP_ALIAS_PROVIDER(a);
SQLPP_ALIAS_PROVIDER(b);
SQLPP_ALIAS_PROVIDER(left);
SQLPP_ALIAS_PROVIDER(right);
}
int main()
{
test::TabFoo f;
test::TabBar t;
// Test a table
{
using T = decltype(t);
static_assert(not sqlpp::is_numeric_t<T>::value, "type requirement");
static_assert(not sqlpp::is_integral_t<T>::value, "type requirement");
static_assert(not sqlpp::is_floating_point_t<T>::value, "type requirement");
static_assert(not sqlpp::is_expression_t<T>::value, "type requirement");
static_assert(not sqlpp::is_named_expression_t<T>::value, "type requirement");
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_update_t<T>::value, "type requirement");
static_assert(not sqlpp::is_boolean_t<T>::value, "type requirement");
static_assert(not sqlpp::is_text_t<T>::value, "type requirement");
static_assert(not sqlpp::is_alias_t<T>::value, "type requirement");
static_assert(sqlpp::is_table_t<T>::value, "type requirement");
static_assert(sqlpp::is_regular<T>::value, "type requirement");
}
// Test an alias of table
{
using T = decltype(t.as(alias::a));
static_assert(not sqlpp::is_numeric_t<T>::value, "type requirement");
static_assert(not sqlpp::is_integral_t<T>::value, "type requirement");
static_assert(not sqlpp::is_floating_point_t<T>::value, "type requirement");
static_assert(not sqlpp::is_expression_t<T>::value, "type requirement");
static_assert(not sqlpp::is_named_expression_t<T>::value, "type requirement");
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_update_t<T>::value, "type requirement");
static_assert(not sqlpp::is_boolean_t<T>::value, "type requirement");
static_assert(not sqlpp::is_text_t<T>::value, "type requirement");
static_assert(sqlpp::is_alias_t<T>::value, "type requirement");
static_assert(sqlpp::is_table_t<T>::value, "type requirement");
static_assert(sqlpp::is_regular<T>::value, "type requirement");
}
// Test an integral column of an alias of table
{
using T = decltype(t.as(alias::a).alpha);
static_assert(sqlpp::is_numeric_t<T>::value, "type requirement");
static_assert(sqlpp::is_integral_t<T>::value, "type requirement");
static_assert(not sqlpp::is_floating_point_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");
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
static_assert(sqlpp::must_not_insert_t<T>::value, "type requirement");
static_assert(sqlpp::must_not_update_t<T>::value, "type requirement");
static_assert(not sqlpp::is_boolean_t<T>::value, "type requirement");
static_assert(not sqlpp::is_text_t<T>::value, "type requirement");
static_assert(not sqlpp::is_alias_t<T>::value, "type requirement");
static_assert(not sqlpp::is_table_t<T>::value, "type requirement");
static_assert(sqlpp::is_regular<T>::value, "type requirement");
}
// Test an integral table column
{
using T = decltype(t.alpha);
static_assert(sqlpp::is_numeric_t<T>::value, "type requirement");
static_assert(sqlpp::is_integral_t<T>::value, "type requirement");
static_assert(not sqlpp::is_floating_point_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");
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
static_assert(sqlpp::must_not_insert_t<T>::value, "type requirement");
static_assert(sqlpp::must_not_update_t<T>::value, "type requirement");
static_assert(not sqlpp::is_boolean_t<T>::value, "type requirement");
static_assert(not sqlpp::is_text_t<T>::value, "type requirement");
static_assert(not sqlpp::is_alias_t<T>::value, "type requirement");
static_assert(not sqlpp::is_table_t<T>::value, "type requirement");
static_assert(sqlpp::is_regular<T>::value, "type requirement");
}
// Test a floating point table column
{
using T = decltype(f.omega);
static_assert(sqlpp::is_numeric_t<T>::value, "type requirement");
static_assert(not sqlpp::is_integral_t<T>::value, "type requirement");
static_assert(sqlpp::is_floating_point_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");
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_update_t<T>::value, "type requirement");
static_assert(not sqlpp::is_boolean_t<T>::value, "type requirement");
static_assert(not sqlpp::is_text_t<T>::value, "type requirement");
static_assert(not sqlpp::is_alias_t<T>::value, "type requirement");
static_assert(not sqlpp::is_table_t<T>::value, "type requirement");
static_assert(sqlpp::is_regular<T>::value, "type requirement");
}
// Test a an alias of a numeric table column
{
using T = decltype(t.alpha.as(alias::a));
static_assert(sqlpp::is_numeric_t<T>::value, "type requirement");
static_assert(not sqlpp::is_expression_t<T>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<T>::value, "type requirement");
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_update_t<T>::value, "type requirement");
static_assert(not sqlpp::is_boolean_t<T>::value, "type requirement");
static_assert(not sqlpp::is_text_t<T>::value, "type requirement");
static_assert(sqlpp::is_alias_t<T>::value, "type requirement");
static_assert(not sqlpp::is_table_t<T>::value, "type requirement");
static_assert(sqlpp::is_regular<T>::value, "type requirement");
}
// Test a select of a single column without a from
{
using T = decltype(select(t.alpha)); // Hint: The current rule is pretty crude (a from is required), but certainly better than nothing
static_assert(not sqlpp::is_numeric_t<T>::value, "type requirement");
static_assert(not sqlpp::is_expression_t<T>::value, "type requirement");
static_assert(not sqlpp::is_named_expression_t<T>::value, "type requirement");
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_update_t<T>::value, "type requirement");
static_assert(not sqlpp::is_boolean_t<T>::value, "type requirement");
static_assert(not sqlpp::is_text_t<T>::value, "type requirement");
static_assert(not sqlpp::is_alias_t<T>::value, "type requirement");
static_assert(not sqlpp::is_table_t<T>::value, "type requirement");
static_assert(sqlpp::is_regular<T>::value, "type requirement");
}
// Test a select of a single numeric table column
{
using T = decltype(select(t.alpha).from(t));
static_assert(sqlpp::is_select_column_list_t<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");
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_update_t<T>::value, "type requirement");
static_assert(not sqlpp::is_boolean_t<T>::value, "type requirement");
static_assert(not sqlpp::is_text_t<T>::value, "type requirement");
static_assert(not sqlpp::is_alias_t<T>::value, "type requirement");
static_assert(not sqlpp::is_table_t<T>::value, "type requirement");
static_assert(sqlpp::is_regular<T>::value, "type requirement");
}
// Test a select of an alias of a single numeric table column
{
using T = decltype(select(t.alpha.as(alias::a)).from(t));
static_assert(sqlpp::is_numeric_t<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");
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_update_t<T>::value, "type requirement");
static_assert(not sqlpp::is_boolean_t<T>::value, "type requirement");
static_assert(not sqlpp::is_text_t<T>::value, "type requirement");
static_assert(not sqlpp::is_alias_t<T>::value, "type requirement");
static_assert(not sqlpp::is_table_t<T>::value, "type requirement");
static_assert(sqlpp::is_regular<T>::value, "type requirement");
}
// Test an alias of a select of a single numeric table column
{
using T = decltype(select(t.alpha).from(t).as(alias::b));
static_assert(not sqlpp::is_numeric_t<T>::value, "type requirement");
static_assert(not sqlpp::is_expression_t<T>::value, "type requirement");
static_assert(not sqlpp::is_named_expression_t<T>::value, "type requirement");
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_update_t<T>::value, "type requirement");
static_assert(not sqlpp::is_boolean_t<T>::value, "red to not be boolean");
static_assert(not sqlpp::is_text_t<T>::value, "type requirement");
static_assert(sqlpp::is_alias_t<T>::value, "type requirement");
static_assert(sqlpp::is_table_t<T>::value, "type requirement");
static_assert(sqlpp::is_regular<T>::value, "type requirement");
}
// Test the column of an alias of a select of an alias of a single numeric table column
{
using T = decltype(select(t.alpha.as(alias::a)).from(t).as(alias::b));
static_assert(not sqlpp::is_numeric_t<T>::value, "type requirement");
static_assert(not sqlpp::is_expression_t<T>::value, "type requirement");
static_assert(not sqlpp::is_named_expression_t<T>::value, "type requirement");
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_update_t<T>::value, "type requirement");
static_assert(not sqlpp::is_boolean_t<T>::value, "type requirement");
static_assert(not sqlpp::is_text_t<T>::value, "type requirement");
static_assert(sqlpp::is_alias_t<T>::value, "type requirement");
static_assert(sqlpp::is_table_t<T>::value, "type requirement");
static_assert(sqlpp::is_regular<T>::value, "type requirement");
}
// Test the column of an alias of a select of a single numeric table column
{
using T = decltype(select(t.alpha).from(t).as(alias::b).alpha);
static_assert(sqlpp::is_numeric_t<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");
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_update_t<T>::value, "type requirement");
static_assert(not sqlpp::is_boolean_t<T>::value, "type requirement");
static_assert(not sqlpp::is_text_t<T>::value, "type requirement");
static_assert(not sqlpp::is_alias_t<T>::value, "type requirement");
static_assert(not sqlpp::is_table_t<T>::value, "type requirement");
static_assert(sqlpp::is_regular<T>::value, "type requirement");
}
// Test an alias of a select of an alias of a single numeric table column
{
using T = decltype(select(t.alpha.as(alias::a)).from(t).as(alias::b).a);
static_assert(sqlpp::is_numeric_t<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");
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_insert_t<T>::value, "type requirement");
static_assert(not sqlpp::must_not_update_t<T>::value, "type requirement");
static_assert(not sqlpp::is_boolean_t<T>::value, "type requirement");
static_assert(not sqlpp::is_text_t<T>::value, "type requirement");
static_assert(not sqlpp::is_alias_t<T>::value, "type requirement");
static_assert(not sqlpp::is_table_t<T>::value, "type requirement");
static_assert(sqlpp::is_regular<T>::value, "type requirement");
}
// Test that select(all_of(tab)) is expanded in select
{
auto a = select(all_of(t));
auto b = select(t.alpha, t.beta, t.gamma, t.delta);
//auto c = select(t);
static_assert(std::is_same<decltype(a), decltype(b)>::value, "all_of(t) has to be expanded by select()");
//static_assert(std::is_same<decltype(b), decltype(c)>::value, "t has to be expanded by select()");
}
// Test that select(all_of(tab)) is expanded in multi_column
{
auto a = multi_column(all_of(t)).as(alias::a);
auto b = multi_column(t.alpha, t.beta, t.gamma, t.delta).as(alias::a);
static_assert(std::is_same<decltype(a), decltype(b)>::value, "all_of(t) has to be expanded by multi_column");
}
// Test that a multicolumn is not a value
{
auto m = multi_column(t.alpha, t.beta).as(alias::a);
auto a = select(m).from(t).as(alias::b).a;
static_assert(not sqlpp::is_value_t<decltype(a)>::value, "a multi_column is not a value");
}
// Test that result sets with identical name/value combinations have identical types
{
auto a = select(t.alpha);
auto b = select(f.epsilon.as(t.alpha));
using A = typename decltype(a)::_result_row_t<MockDb>;
using B = typename decltype(b)::_result_row_t<MockDb>;
static_assert(std::is_same<
decltype(t.alpha)::_value_type::_base_value_type,
decltype(f.epsilon)::_value_type::_base_value_type>::value, "Two bigint columns must have identical base_value_type");
static_assert(std::is_same<A, B>::value, "select with identical columns(name/value_type) need to have identical result_types");
}
for (const auto& row : db(select(all_of(t)).from(t).where(true)))
{
int64_t a = row.alpha;
}
{
auto s = dynamic_select(db, all_of(t)).dynamic_from().dynamic_where().dynamic_limit().dynamic_offset();
s.add_from(t);
s.add_where(t.alpha > 7 and t.alpha == any(select(t.alpha).from(t).where(t.alpha < 3)));
s.set_limit(30);
s.set_limit(3);
std::cerr << "------------------------\n";
serialize(s, printer).str();
std::cerr << "------------------------\n";
using T = decltype(s);
static_assert(sqlpp::is_regular<T>::value, "type requirement");
}
// Test that select can be called with zero columns if it is used with dynamic columns.
{
auto s = dynamic_select(db).dynamic_columns();
s.add_column(t.alpha);
serialize(s, printer).str();
}
// Test that verbatim_table compiles
{
auto s = select(t.alpha).from(sqlpp::verbatim_table("my_unknown_table"));
serialize(s, printer).str();
}
static_assert(sqlpp::is_select_flag_t<decltype(sqlpp::all)>::value, "sqlpp::all has to be a select_flag");
using T = sqlpp::vendor::wrap_operand<int>::type;
static_assert(sqlpp::is_regular<T>::value, "type requirement");
static_assert(T::_is_expression, "T has to be an expression");
static_assert(std::is_same<typename T::_value_type::_is_numeric, std::true_type>::value, "T has to be a numeric");
static_assert(sqlpp::is_numeric_t<T>::value, "T has to be a numeric");
static_assert(sqlpp::is_numeric_t<decltype(t.alpha)>::value, "TabBar.alpha has to be a numeric");
((t.alpha + 7) + 4).asc();
static_assert(sqlpp::is_boolean_t<decltype(t.gamma == t.gamma)>::value, "Comparison expression have to be boolean");
auto x = (t.gamma == true) and (t.alpha == 7);
auto y = t.gamma and true and t.gamma;
!t.gamma;
t.beta < "kaesekuchen";
serialize(t.beta + "hallenhalma", printer).str();
static_assert(sqlpp::must_not_insert_t<decltype(t.alpha)>::value, "alpha must not be inserted");
serialize(t.alpha, printer).str();
std::cerr << "\n" << sizeof(test::TabBar) << std::endl;
static_assert(std::is_same<typename decltype(t.alpha)::_value_type::_is_named_expression, std::true_type>::value, "alpha should be a named expression");
static_assert(sqlpp::is_named_expression_t<decltype(t.alpha)>::value, "alpha should be a named expression");
static_assert(sqlpp::is_named_expression_t<decltype(t.alpha.as(alias::a))>::value, "an alias of alpha should be a named expression");
static_assert(sqlpp::is_alias_t<decltype(t.alpha.as(alias::a))>::value, "an alias of alpha should be an alias");
auto z = select(t.alpha).from(t) == 7;
auto l = t.as(alias::left);
auto r = select(t.gamma.as(alias::a)).from(t).where(t.gamma == true).as(alias::right);
static_assert(sqlpp::is_boolean_t<decltype(select(t.gamma).from(t))>::value, "select(bool) has to be a bool");
serialize(sqlpp::select().flags(sqlpp::distinct, sqlpp::straight_join).columns(l.alpha, l.beta, select(r.a).from(r))
.from(l, r)
.where(t.beta == "hello world" and select(t.gamma).from(t))// .as(alias::right))
.group_by(l.gamma, r.a)
.having(r.a != true)
.order_by(l.beta.asc())
.limit(17)
.offset(3)
.as(alias::a)
, printer).str();
return 0;
}

View File

@ -29,8 +29,8 @@
#include "MockDb.h"
#include "is_regular.h"
DbMock db;
DbMock::_serializer_context_t printer(std::cerr);
MockDb db;
MockDb::_serializer_context_t printer;
int main()
{
@ -56,13 +56,15 @@ int main()
static_assert(sqlpp::is_regular<T>::value, "type requirement");
}
serialize(update(t), printer).flush();
serialize(update(t).set(t.gamma = false), printer).flush();
serialize(update(t).set(t.gamma = false).where(t.beta != "transparent"), printer).flush();
serialize(update(t).set(t.beta = "opaque").where(t.beta != t.beta), printer).flush();
serialize(update(t), printer).str();
serialize(update(t).set(t.gamma = false), printer).str();
serialize(update(t).set(t.gamma = false).where(t.beta != "transparent"), printer).str();
serialize(update(t).set(t.beta = "opaque").where(t.beta != t.beta), printer).str();
auto u = dynamic_update(db, t).dynamic_set(t.gamma = false).dynamic_where();
u.add_set(t.gamma = false);
serialize(u, printer).flush();
serialize(u, printer).str();
db(u);
return 0;
}